diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt index 36df265b473..179e0dfda96 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt @@ -294,7 +294,7 @@ class NameSuggestion { // Make all public declarations stable effectiveVisibility == Visibilities.PUBLIC -> mangledAndStable() - descriptor is CallableMemberDescriptor && descriptor.isOverridableOrOverrides -> mangledAndStable() + descriptor.isOverridableOrOverrides -> mangledAndStable() // Make all protected declarations of non-final public classes stable effectiveVisibility == Visibilities.PROTECTED && @@ -346,8 +346,28 @@ class NameSuggestion { @JvmStatic fun sanitizeName(name: String): String { if (name.isEmpty()) return "_" - val first = name.first().let { if (java.lang.Character.isJavaIdentifierStart(it)) it else '_' } - return first.toString() + name.drop(1).map { if (java.lang.Character.isJavaIdentifierPart(it)) it else '_' }.joinToString("") + val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' } + return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("") } + + // See ES 5.1 spec: https://www.ecma-international.org/ecma-262/5.1/#sec-7.6 + private fun Char.isES5IdentifierStart() = + Character.isLetter(this) || // Lu | Ll | Lt | Lm | Lo + Character.getType(this).toByte() == Character.LETTER_NUMBER || + // Nl which is missing in Character.isLetter, but present in UnicodeLetter in spec + this == '_' || + this == '$' + + private fun Char.isES5IdentifierPart() = + isES5IdentifierStart() || + when (Character.getType(this).toByte()) { + Character.NON_SPACING_MARK, + Character.COMBINING_SPACING_MARK, + Character.DECIMAL_DIGIT_NUMBER, + Character.CONNECTOR_PUNCTUATION -> true + else -> false + } || + this == '\u200C' || // Zero-width non-joiner + this == '\u200D' // Zero-width joiner } } diff --git a/js/js.translator/testData/box/jsName/peculiarIdentifiers.kt b/js/js.translator/testData/box/jsName/peculiarIdentifiers.kt index c9339dcd550..d64a5b92472 100644 --- a/js/js.translator/testData/box/jsName/peculiarIdentifiers.kt +++ b/js/js.translator/testData/box/jsName/peculiarIdentifiers.kt @@ -23,9 +23,9 @@ fun test3(): String { } fun test4(): String { - val `()` = "OK" - fun `[]`() = `()` - return `[]`() + val `1(¢)` = "OK" + fun `[£]`() = `1(¢)` + return `[£]`() } fun box(): String {