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.