< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java

Print this page

        

@@ -890,11 +890,11 @@
         switch (type) {
         case LBRACE:
             block();
             break;
         case VAR:
-            variableStatement(type, true);
+            variableStatement(type);
             break;
         case SEMICOLON:
             emptyStatement();
             break;
         case IF:

@@ -944,15 +944,15 @@
         default:
             if (useBlockScope() && (type == LET || type == CONST)) {
                 if (singleStatement) {
                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
                 }
-                variableStatement(type, true);
+                variableStatement(type);
                 break;
             }
             if (env._const_as_var && type == CONST) {
-                variableStatement(TokenType.VAR, true);
+                variableStatement(TokenType.VAR);
                 break;
             }
 
             if (type == IDENT || isNonStrictModeIdent()) {
                 if (T(k + 1) == COLON) {

@@ -1045,11 +1045,11 @@
                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
             }
         }
     }
 
-    /**
+    /*
      * VariableStatement :
      *      var VariableDeclarationList ;
      *
      * VariableDeclarationList :
      *      VariableDeclaration

@@ -1064,12 +1064,12 @@
      * See 12.2
      *
      * Parse a VAR statement.
      * @param isStatement True if a statement (not used in a FOR.)
      */
-    private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
-        return variableStatement(varType, isStatement, -1);
+    private List<VarNode> variableStatement(final TokenType varType) {
+        return variableStatement(varType, true, -1);
     }
 
     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
         // VAR tested in caller.
         next();

@@ -1213,10 +1213,11 @@
      *
      * See 12.6
      *
      * Parse a FOR statement.
      */
+    @SuppressWarnings("fallthrough")
     private void forStatement() {
         final long forToken = token;
         final int forLine = line;
         // start position of this for statement. This is used
         // for sort order for variables declared in the initializer

@@ -1233,10 +1234,11 @@
         Expression init = null;
         JoinPredecessorExpression test = null;
         JoinPredecessorExpression modify = null;
 
         int flags = 0;
+        boolean isForOf = false;
 
         try {
             // FOR tested in caller.
             next();
 

@@ -1290,45 +1292,53 @@
                 if (type != RPAREN) {
                     modify = joinPredecessorExpression();
                 }
                 break;
 
+            case IDENT:
+                if (env._es6 && "of".equals(getValue())) {
+                    isForOf = true;
+                    // fall through
+                } else {
+                    expect(SEMICOLON); // fail with expected message
+                    break;
+                }
             case IN:
-                flags |= ForNode.IS_FOR_IN;
+
+                flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
                 test = new JoinPredecessorExpression();
                 if (vars != null) {
                     // for (var i in obj)
                     if (vars.size() == 1) {
                         init = new IdentNode(vars.get(0).getName());
                     } else {
                         // for (var i, j in obj) is invalid
-                        throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
+                        throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
                     }
-
                 } else {
                     // for (expr in obj)
-                    assert init != null : "for..in init expression can not be null here";
+                    assert init != null : "for..in/of init expression can not be null here";
 
                     // check if initial expression is a valid L-value
                     if (!(init instanceof AccessNode ||
                           init instanceof IndexNode ||
                           init instanceof IdentNode)) {
-                        throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
+                        throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
                     }
 
                     if (init instanceof IdentNode) {
                         if (!checkIdentLValue((IdentNode)init)) {
-                            throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
+                            throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
                         }
-                        verifyStrictIdent((IdentNode)init, "for-in iterator");
+                        verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
                     }
                 }
 
                 next();
 
-                // Get the collection expression.
-                modify = joinPredecessorExpression();
+                // For-of only allows AssignmentExpression.
+                modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
                 break;
 
             default:
                 expect(SEMICOLON);
                 break;
< prev index next >