Reviewers: Dmitry Lomov (chromium),

Description:
[es6] Fix for-const loops

[email protected]
BUG=3983
LOG=Y

Please review this at https://codereview.chromium.org/977543002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+47, -27 lines):
  M src/parser.h
  M src/parser.cc
  A + test/mjsunit/es6/regress/regress-3938.js
  M test/mjsunit/harmony/block-const-assign.js


Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index aa6ee8ccb6c67a3d210a39b18e97a31f9808ea32..7f9e466fa810756dcb555729f92334d3f69d9cb9 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3005,8 +3005,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
 }


-Statement* Parser::DesugarLetBindingsInForStatement(
-    Scope* inner_scope, ZoneList<const AstRawString*>* names,
+Statement* Parser::DesugarLexicalBindingsInForStatement(
+ Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
     ForStatement* loop, Statement* init, Expression* cond, Statement* next,
     Statement* body, bool* ok) {
// ES6 13.6.3.4 specifies that on each loop iteration the let variables are
@@ -3016,16 +3016,16 @@ Statement* Parser::DesugarLetBindingsInForStatement(
   //
   // We rewrite a for statement of the form
   //
-  //  labels: for (let x = i; cond; next) body
+  //  labels: for (let/const x = i; cond; next) body
   //
   // into
   //
   //  {
-  //    let x = i;
+  //    let/const x = i;
   //    temp_x = x;
   //    first = 1;
   //    outer: for (;;) {
-  //      let x = temp_x;
+  //      let/const x = temp_x;
   //      if (first == 1) {
   //        first = 0;
   //      } else {
@@ -3052,12 +3052,12 @@ Statement* Parser::DesugarLetBindingsInForStatement(
Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
                                            RelocInfo::kNoPosition);

-  // Add statement: let x = i.
+  // Add statement: let/const x = i.
   outer_block->AddStatement(init, zone());

   const AstRawString* temp_name = ast_value_factory()->dot_for_string();

-  // For each let variable x:
+  // For each lexical variable x:
   //   make statement: temp_x = x.
   for (int i = 0; i < names->length(); i++) {
     VariableProxy* proxy = NewUnresolved(names->at(i), LET);
@@ -3102,16 +3102,17 @@ Statement* Parser::DesugarLetBindingsInForStatement(
   ZoneList<Variable*> inner_vars(names->length(), zone());

   // For each let variable x:
-  //    make statement: let x = temp_x.
+  //    make statement: let/const x = temp_x.
+  VariableMode mode = is_const ? CONST : LET;
   for (int i = 0; i < names->length(); i++) {
-    VariableProxy* proxy = NewUnresolved(names->at(i), LET);
+    VariableProxy* proxy = NewUnresolved(names->at(i), mode);
     Declaration* declaration = factory()->NewVariableDeclaration(
-        proxy, LET, scope_, RelocInfo::kNoPosition);
+        proxy, mode, scope_, RelocInfo::kNoPosition);
     Declare(declaration, true, CHECK_OK);
     inner_vars.Add(declaration->proxy()->var(), zone());
     VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
     Assignment* assignment = factory()->NewAssignment(
-        Token::INIT_LET, proxy, temp_proxy, pos);
+ is_const ? Token::INIT_CONST : Token::INIT_LET, proxy, temp_proxy, pos);
     Statement* assignment_statement =
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
     proxy->var()->set_initializer_position(init->position());
@@ -3240,8 +3241,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement

   int stmt_pos = peek_position();
+  bool is_const = false;
   Statement* init = NULL;
-  ZoneList<const AstRawString*> let_bindings(1, zone());
+  ZoneList<const AstRawString*> lexical_bindings(1, zone());

   // Create an in-between scope for let-bound iteration variables.
   Scope* saved_scope = scope_;
@@ -3293,12 +3295,12 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
       }
     } else if ((peek() == Token::LET || peek() == Token::CONST) &&
                is_strict(language_mode())) {
-      bool is_const = peek() == Token::CONST;
+      is_const = peek() == Token::CONST;
       const AstRawString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
- ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
-                                    &name, CHECK_OK);
+          ParseVariableDeclarations(kForStatement, &decl_props,
+                                    &lexical_bindings, &name, CHECK_OK);
       bool accept_IN = name != NULL && decl_props != kHasInitializers;
       bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
@@ -3415,7 +3417,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, // If there are let bindings, then condition and the next statement of the
   // for loop must be parsed in a new scope.
   Scope* inner_scope = NULL;
-  if (let_bindings.length() > 0) {
+  if (lexical_bindings.length() > 0) {
     inner_scope = NewScope(for_scope, BLOCK_SCOPE);
     inner_scope->set_start_position(scanner()->location().beg_pos);
     scope_ = inner_scope;
@@ -3438,10 +3440,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
   Statement* body = ParseSubStatement(NULL, CHECK_OK);

   Statement* result = NULL;
-  if (let_bindings.length() > 0) {
+  if (lexical_bindings.length() > 0) {
     scope_ = for_scope;
- result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, - init, cond, next, body, CHECK_OK);
+    result = DesugarLexicalBindingsInForStatement(
+ inner_scope, is_const, &lexical_bindings, loop, init, cond,
+                 next, body, CHECK_OK);
     scope_ = saved_scope;
     for_scope->set_end_position(scanner()->location().end_pos);
   } else {
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index 882e2ac5f81a74a83bb902d2cc48e115c8e37731..8f13916fde82bfafbc3dddb720afda4a8a27b046 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -763,8 +763,8 @@ class Parser : public ParserBase<ParserTraits> {
                                   Expression* each,
                                   Expression* subject,
                                   Statement* body);
-  Statement* DesugarLetBindingsInForStatement(
-      Scope* inner_scope, ZoneList<const AstRawString*>* names,
+  Statement* DesugarLexicalBindingsInForStatement(
+ Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, ForStatement* loop, Statement* init, Expression* cond, Statement* next,
       Statement* body, bool* ok);

Index: test/mjsunit/es6/regress/regress-3938.js
diff --git a/test/message/super-in-function.js b/test/mjsunit/es6/regress/regress-3938.js
similarity index 56%
copy from test/message/super-in-function.js
copy to test/mjsunit/es6/regress/regress-3938.js
index edaa0e4eadc7befdb7ed28a3e06eaa827c4388f0..bd7d1befa13b19f2284161f50c4b53ab40c4ee3a 100644
--- a/test/message/super-in-function.js
+++ b/test/mjsunit/es6/regress/regress-3938.js
@@ -1,10 +1,8 @@
 // Copyright 2015 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// Flags: --harmony-classes
+
 'use strict';

-function f() {
-  super.x();
-}
+assertThrows(function() { for (const i = 0; ; i++) {} }, TypeError);
+assertThrows("'use strict'; for (const i = 0; ; i++) {}", TypeError);
Index: test/mjsunit/harmony/block-const-assign.js
diff --git a/test/mjsunit/harmony/block-const-assign.js b/test/mjsunit/harmony/block-const-assign.js index c21a0a34803a686e677a5ce6a8b10cdeecf1d8ac..397695f86aecd1e2a5b8637e6c74147269e10d89 100644
--- a/test/mjsunit/harmony/block-const-assign.js
+++ b/test/mjsunit/harmony/block-const-assign.js
@@ -93,6 +93,22 @@ function constDecl9(use) {
   return "(function constvar() { " + use + "; })();";
 }

+// For loop variable.
+function constDecl10(use) {
+ return "(function() { for (const constvar = 0; ;) { " + use + "; } })();";
+}
+
+// For-in loop variable.
+function constDecl11(use) {
+ return "(function() { for (const constvar in {a: 1}) { " + use + "; } })();";
+}
+
+// For-of loop variable.
+function constDecl12(use) {
+ return "(function() { for (const constvar of [1]) { " + use + "; } })();";
+}
+
+
 let decls = [ constDecl0,
               constDecl1,
               constDecl2,
@@ -102,7 +118,10 @@ let decls = [ constDecl0,
               constDecl6,
               constDecl7,
               constDecl8,
-              constDecl9
+              constDecl9,
+              constDecl10,
+              constDecl11,
+              constDecl12
               ];
let declsForTDZ = new Set([constDecl1, constDecl3, constDecl5, constDecl7]);
 let uses = [ 'constvar = 1;',


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to