src/jdk/nashorn/internal/codegen/AssignSymbols.java

Print this page

        

@@ -187,32 +187,33 @@
      *
      * @param functionNode the FunctionNode we are entering
      * @param body the body of the FunctionNode we are entering
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
-        // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
+        // This visitor will assign symbol to all declared variables.
         body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             protected boolean enterDefault(final Node node) {
                 // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
                 // This will also prevent visiting nested functions (as FunctionNode is an expression).
                 return !(node instanceof Expression);
             }
 
             @Override
             public Node leaveVarNode(final VarNode varNode) {
-                if (varNode.isStatement()) {
                     final IdentNode ident  = varNode.getName();
-                    final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body;
+                final boolean blockScoped = varNode.isBlockScoped();
+                if (blockScoped && lc.inUnprotectedSwitchContext()) {
+                    throwUnprotectedSwitchError(varNode);
+                }
+                final Block block = blockScoped ? lc.getCurrentBlock() : body;
                     final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
                     if (varNode.isFunctionDeclaration()) {
                         symbol.setIsFunctionDeclaration();
                     }
                     return varNode.setName(ident.setSymbol(symbol));
                 }
-                return varNode;
-            }
         });
     }
 
     private IdentNode compilerConstantIdentifier(final CompilerConstants cc) {
         return createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc));

@@ -1046,10 +1047,19 @@
         }
         final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
         return !(units == null || units.isEmpty());
     }
 
+    private void throwUnprotectedSwitchError(final VarNode varNode) {
+        // Block scoped declarations in switch statements without explicit blocks should be declared
+        // in a common block that contains all the case clauses. We cannot support this without a
+        // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
+        // directly contained by switch node). As a temporary solution we throw a reference error here.
+        final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
+        throwParserException(msg, varNode);
+    }
+
     private void throwParserException(final String message, final Node origin) {
         if (origin == null) {
             throw new ParserException(message);
         }
         final Source source = compiler.getSource();