diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/jsScopes.kt b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/jsScopes.kt index 00b74a4a297..51d5b299a6b 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/jsScopes.kt +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/jsScopes.kt @@ -49,14 +49,30 @@ public class JsFunctionScope(parent: JsScope, description: String) : JsScope(par topLabelScope?.findName(label) private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident", null) { - val labelName = JsName(this@JsFunctionScope, parent?.getFreshIdent(ident) ?: ident) + val labelName: JsName + + { + val freshIdent = when { + ident in RESERVED_WORDS -> getFreshIdent(ident) + parent != null -> parent.getFreshIdent(ident) + else -> ident + } + + labelName = JsName(this@JsFunctionScope, freshIdent) + } override fun findOwnName(name: String): JsName? = if (name == ident) labelName else null + /** + * Safe call is necessary, because hasOwnName can be called + * in constructor before labelName is initialized (see KT-4394) + */ + [suppress("UNNECESSARY_SAFE_CALL")] override fun hasOwnName(name: String): Boolean = - name == ident - || name == labelName.getIdent() + name in RESERVED_WORDS + || name == ident + || name == labelName?.getIdent() || getParent()?.hasOwnName(name) ?: false } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 5c4f48d5a82..108ee21c886 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -364,7 +364,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { private static String getReferencedName(JetSimpleNameExpression expression) { return expression.getReferencedName() .replaceAll("^@", "") - .replaceAll("(?:^`(.*)`$)", "$1") + "$"; + .replaceAll("(?:^`(.*)`$)", "$1"); } private static JsNameRef getTargetLabel(JetExpressionWithLabel expression, TranslationContext context) { diff --git a/js/js.translator/testData/labels/cases/labelWithVariableClashing.kt b/js/js.translator/testData/labels/cases/labelWithVariableClashing.kt index 122d5f1bd13..8dfafe434cd 100644 --- a/js/js.translator/testData/labels/cases/labelWithVariableClashing.kt +++ b/js/js.translator/testData/labels/cases/labelWithVariableClashing.kt @@ -1,7 +1,7 @@ package foo -// CHECK_LABELS_COUNT: function=test1 name=loop$ count=1 -// CHECK_LABELS_COUNT: function=test2 name=loop$ count=1 +// CHECK_LABELS_COUNT: function=test1 name=loop count=1 +// CHECK_LABELS_COUNT: function=test2 name=loop count=1 fun test1() { var `loop$` = 0 diff --git a/js/js.translator/testData/labels/cases/nestedLabels.kt b/js/js.translator/testData/labels/cases/nestedLabels.kt index 70867078720..8076dff9e17 100644 --- a/js/js.translator/testData/labels/cases/nestedLabels.kt +++ b/js/js.translator/testData/labels/cases/nestedLabels.kt @@ -1,7 +1,7 @@ package foo -// CHECK_LABELS_COUNT: function=test name=loop$ count=1 -// CHECK_LABELS_COUNT: function=test name=loop$_0 count=1 +// CHECK_LABELS_COUNT: function=test name=loop count=1 +// CHECK_LABELS_COUNT: function=test name=loop_0 count=1 fun test() { var i = 0 diff --git a/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashing.kt b/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashing.kt index 97e3b81d181..448f337fe40 100644 --- a/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashing.kt +++ b/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashing.kt @@ -1,9 +1,9 @@ package foo // CHECK_CONTAINS_NO_CALLS: test -// CHECK_LABELS_COUNT: function=test name=loop$ count=1 -// CHECK_LABELS_COUNT: function=test name=loop$_0 count=1 -// CHECK_LABELS_COUNT: function=test name=loop$_1 count=1 +// CHECK_LABELS_COUNT: function=test name=loop count=1 +// CHECK_LABELS_COUNT: function=test name=loop_0 count=1 +// CHECK_LABELS_COUNT: function=test name=loop_1 count=1 class State() { public var value: Int = 0 diff --git a/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashingAtFunctionsWithClosure.kt b/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashingAtFunctionsWithClosure.kt index 1359f68e265..6a9241a1f99 100644 --- a/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashingAtFunctionsWithClosure.kt +++ b/js/js.translator/testData/labels/cases/nestedLabelsInlinedClashingAtFunctionsWithClosure.kt @@ -1,8 +1,8 @@ package foo -// CHECK_LABELS_COUNT: function=test name=loop$ count=1 -// CHECK_LABELS_COUNT: function=test name=loop$_0 count=1 -// CHECK_LABELS_COUNT: function=test name=loop$_1 count=1 +// CHECK_LABELS_COUNT: function=test name=loop count=1 +// CHECK_LABELS_COUNT: function=test name=loop_0 count=1 +// CHECK_LABELS_COUNT: function=test name=loop_1 count=1 class State() { public var value: Int = 0 diff --git a/js/js.translator/testData/labels/cases/siblingLabels.kt b/js/js.translator/testData/labels/cases/siblingLabels.kt index ba9724b6bfe..e9464613db3 100644 --- a/js/js.translator/testData/labels/cases/siblingLabels.kt +++ b/js/js.translator/testData/labels/cases/siblingLabels.kt @@ -1,6 +1,6 @@ package foo -// CHECK_LABELS_COUNT: function=test name=loop$ count=2 +// CHECK_LABELS_COUNT: function=test name=loop count=2 fun test() { var i = 0 diff --git a/js/js.translator/testData/labels/cases/siblingLabelsInlined.kt b/js/js.translator/testData/labels/cases/siblingLabelsInlined.kt index 4094f05df36..e885f019062 100644 --- a/js/js.translator/testData/labels/cases/siblingLabelsInlined.kt +++ b/js/js.translator/testData/labels/cases/siblingLabelsInlined.kt @@ -1,7 +1,7 @@ package foo // CHECK_NOT_CALLED: testInline -// CHECK_LABELS_COUNT: function=testNoinline name=loop$ count=2 +// CHECK_LABELS_COUNT: function=testNoinline name=loop count=2 inline fun testInline(): Int { var c = 0 diff --git a/js/js.translator/testData/labels/cases/siblingLabelsInlinedClashing.kt b/js/js.translator/testData/labels/cases/siblingLabelsInlinedClashing.kt index fb1d3d155d4..92c2173a173 100644 --- a/js/js.translator/testData/labels/cases/siblingLabelsInlinedClashing.kt +++ b/js/js.translator/testData/labels/cases/siblingLabelsInlinedClashing.kt @@ -1,8 +1,8 @@ package foo // CHECK_NOT_CALLED: testLabelInline -// CHECK_LABELS_COUNT: function=testLabel name=loop$ count=1 -// CHECK_LABELS_COUNT: function=testLabel name=loop$_0 count=2 +// CHECK_LABELS_COUNT: function=testLabel name=loop count=1 +// CHECK_LABELS_COUNT: function=testLabel name=loop_0 count=2 inline fun testLabelInline(): Int { var a = 0 diff --git a/js/js.translator/testData/labels/cases/simpleLabel.kt b/js/js.translator/testData/labels/cases/simpleLabel.kt index 7d30876c8a9..3d589ba6ae8 100644 --- a/js/js.translator/testData/labels/cases/simpleLabel.kt +++ b/js/js.translator/testData/labels/cases/simpleLabel.kt @@ -1,7 +1,7 @@ package foo -// CHECK_LABELS_COUNT: function=testBreak name=loop$ count=1 -// CHECK_LABELS_COUNT: function=testContinue name=loop$ count=1 +// CHECK_LABELS_COUNT: function=testBreak name=loop count=1 +// CHECK_LABELS_COUNT: function=testContinue name=loop count=1 fun testBreak() { var i = 0 diff --git a/js/js.translator/testData/labels/cases/simpleLabelInlined.kt b/js/js.translator/testData/labels/cases/simpleLabelInlined.kt index a71188764d1..6b176d48452 100644 --- a/js/js.translator/testData/labels/cases/simpleLabelInlined.kt +++ b/js/js.translator/testData/labels/cases/simpleLabelInlined.kt @@ -2,8 +2,8 @@ package foo // CHECK_NOT_CALLED: testBreak // CHECK_NOT_CALLED: testContinue -// CHECK_LABELS_COUNT: function=testBreakNoinline name=loop$ count=1 -// CHECK_LABELS_COUNT: function=testContinueNoinline name=loop$ count=1 +// CHECK_LABELS_COUNT: function=testBreakNoinline name=loop count=1 +// CHECK_LABELS_COUNT: function=testContinueNoinline name=loop count=1 inline fun testBreak(): Int { var i = 0