diff --git a/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java b/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java index f5935d59343..b1e31056eaa 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java @@ -52,4 +52,12 @@ public final class AstUtil { return nodesCopy; } + + @NotNull + public static JsFunctionScope toFunctionScope(JsScope scope) { + assert scope instanceof JsFunctionScope: "JsFunctionScope type is expected, but " + + scope.getClass().getSimpleName() + " is found"; + + return (JsFunctionScope) scope; + } } diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsParser.java b/js/js.parser/src/com/google/gwt/dev/js/JsParser.java index 353bd2edf9b..1f70baa2315 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/JsParser.java +++ b/js/js.parser/src/com/google/gwt/dev/js/JsParser.java @@ -19,6 +19,8 @@ import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.JsLiteral.JsBooleanLiteral; import com.google.dart.compiler.common.SourceInfo; import com.google.gwt.dev.js.rhino.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.Reader; @@ -26,6 +28,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; +import static com.google.dart.compiler.util.AstUtil.toFunctionScope; + /** * Parses JavaScript source. */ @@ -375,7 +379,28 @@ public class JsParser { } private JsBreak mapBreak(Node breakNode) { - return new JsBreak(); + return new JsBreak(getTargetLabel(breakNode)); + } + + @Nullable + private JsNameRef getTargetLabel(@NotNull Node statementWithLabel) { + int type = statementWithLabel.getType(); + if (type != TokenStream.BREAK && type != TokenStream.CONTINUE) { + String tokenTypeName = TokenStream.tokenToName(statementWithLabel.getType()); + throw new AssertionError("Unexpected node type with label: " + tokenTypeName); + } + + Node label = statementWithLabel.getFirstChild(); + if (label == null) return null; + + String identifier = label.getString(); + assert identifier != null: "If label exists identifier should not be null"; + + JsFunctionScope scope = toFunctionScope(getScope()); + JsName labelName = scope.findLabel(identifier); + assert labelName != null: "Unknown label name: " + identifier; + + return labelName.makeRef(); } private JsInvocation mapCall(Node callNode) throws JsParserException { @@ -416,7 +441,7 @@ public class JsParser { } private JsContinue mapContinue(Node contNode) { - return new JsContinue(); + return new JsContinue(getTargetLabel(contNode)); } private JsStatement mapDebuggerStatement(Node node) { @@ -721,10 +746,12 @@ public class JsParser { private JsLabel mapLabel(Node labelNode) throws JsParserException { String fromName = labelNode.getFirstChild().getString(); - JsName toName = getScope().declareName(fromName); + JsFunctionScope scope = toFunctionScope(getScope()); + JsName toName = scope.enterLabel(fromName); Node fromStmt = labelNode.getFirstChild().getNext(); JsLabel toLabel = new JsLabel(toName); toLabel.setStatement(mapStatement(fromStmt)); + scope.exitLabel(); return toLabel; }