diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt index 58b4a2dff28..00bc36ec367 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/jsScopes.kt @@ -37,8 +37,8 @@ open class JsDeclarationScope(parent: JsScope, description: String, useParentSco private val topLabelScope get() = if (labelScopes.isNotEmpty()) labelScopes.peek() else null - open fun enterLabel(label: String): JsName { - val scope = LabelScope(topLabelScope, label) + open fun enterLabel(label: String, outputName: String): JsName { + val scope = LabelScope(topLabelScope, label, outputName) labelScopes.push(scope) return scope.labelName } @@ -51,18 +51,8 @@ open class JsDeclarationScope(parent: JsScope, description: String, useParentSco open fun findLabel(label: String): JsName? = topLabelScope?.findName(label) - private inner class LabelScope(parent: LabelScope?, val ident: String) : JsScope(parent, "Label scope for $ident") { - val labelName: JsName - - init { - val freshIdent = when { - ident in RESERVED_WORDS -> getFreshIdent(ident) - parent != null -> parent.getFreshIdent(ident) - else -> ident - } - - labelName = JsName(freshIdent, false) - } + private inner class LabelScope(parent: LabelScope?, val ident: String, outputIdent: String) : JsScope(parent, "Label scope for $ident") { + val labelName: JsName = JsName(outputIdent, true) override fun findOwnName(name: String): JsName? = if (name == ident) labelName else null @@ -130,8 +120,8 @@ class DelegatingJsFunctionScopeWithTemporaryParent( override fun declareFreshName(suggestedName: String): JsName = delegatingScope.declareFreshName(suggestedName) - override fun enterLabel(label: String): JsName = - delegatingScope.enterLabel(label) + override fun enterLabel(label: String, outputName: String): JsName = + delegatingScope.enterLabel(label, outputName) override fun exitLabel() = delegatingScope.exitLabel() diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/LabelNameRefreshingVisitor.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/LabelNameRefreshingVisitor.kt index 3b494ea0fa3..9a055b35a54 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/LabelNameRefreshingVisitor.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/rewriters/LabelNameRefreshingVisitor.kt @@ -42,7 +42,7 @@ class LabelNameRefreshingVisitor(val functionScope: JsFunctionScope) : JsVisitor override fun visit(x: JsLabel, ctx: JsContext): Boolean { val labelName = x.name - val freshName = functionScope.enterLabel(labelName.ident) + val freshName = functionScope.enterLabel(labelName.ident, labelName.ident) substitutions.getOrPut(labelName) { ArrayDeque() }.push(freshName) return super.visit(x, ctx) @@ -57,5 +57,5 @@ class LabelNameRefreshingVisitor(val functionScope: JsFunctionScope) : JsVisitor super.endVisit(x, ctx) } - private fun getSubstitution(name: JsName) = substitutions[name]?.let { it.peek() } ?: name + private fun getSubstitution(name: JsName) = substitutions[name]?.peek() ?: name } diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java index 078ba9c7977..d9470de1b8c 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java +++ b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java @@ -665,7 +665,7 @@ public class JsAstMapper { private JsLabel mapLabel(Node labelNode) throws JsParserException { String fromName = labelNode.getFirstChild().getString(); - JsName toName = scopeContext.enterLabel(fromName); + JsName toName = scopeContext.enterLabel(fromName, fromName); Node fromStmt = labelNode.getFirstChild().getNext(); JsLabel toLabel = new JsLabel(toName); diff --git a/js/js.parser/src/com/google/gwt/dev/js/ScopeContext.kt b/js/js.parser/src/com/google/gwt/dev/js/ScopeContext.kt index 02bfc251d81..3d3144faad5 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/ScopeContext.kt +++ b/js/js.parser/src/com/google/gwt/dev/js/ScopeContext.kt @@ -49,8 +49,8 @@ class ScopeContext(scope: JsScope) { exitScope() } - fun enterLabel(ident: String): JsName = - (currentScope as JsDeclarationScope).enterLabel(ident) + fun enterLabel(ident: String, outputName: String): JsName = + (currentScope as JsDeclarationScope).enterLabel(ident, outputName) fun exitLabel() = (currentScope as JsDeclarationScope).exitLabel() diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 9095720de48..b4365f2d5ec 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -5450,6 +5450,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("peculiarNames.kt") + public void testPeculiarNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/labels/peculiarNames.kt"); + doTest(fileName); + } + @TestMetadata("siblingLabels.kt") public void testSiblingLabels() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/labels/siblingLabels.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java index 9a660417777..8946a378497 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention; import org.jetbrains.kotlin.js.backend.ast.*; import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; +import org.jetbrains.kotlin.js.naming.NameSuggestion; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator; import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt; @@ -363,7 +364,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { String labelIdent = getReferencedName(expression.getTargetLabel()); - JsName labelName = functionScope.enterLabel(labelIdent); + JsName labelName = functionScope.enterLabel(labelIdent, NameSuggestion.sanitizeName(labelIdent)); JsStatement baseStatement = Translation.translateAsStatement(baseExpression, context); functionScope.exitLabel(); diff --git a/js/js.translator/testData/box/labels/peculiarNames.kt b/js/js.translator/testData/box/labels/peculiarNames.kt new file mode 100644 index 00000000000..98f6375ac7e --- /dev/null +++ b/js/js.translator/testData/box/labels/peculiarNames.kt @@ -0,0 +1,18 @@ +// EXPECTED_REACHABLE_NODES: 487 +fun box(): String { + var log = "" + + var i = 0 + `!`@while (true) { + log += "i=$i;" + for (j in 1..3) { + log += "j=$j;" + if (i++ + j > 5) break@`!` + log += "!" + } + } + + if (log != "i=0;j=1;!j=2;!j=3;!i=3;j=1;!j=2;") return "fail: $log" + + return "OK" +} \ No newline at end of file