Commit 054989bd authored by rossberg's avatar rossberg Committed by Commit bot

[es6] Fix for-const loops

R=dslomov@chromium.org
BUG=3983
LOG=Y

Review URL: https://codereview.chromium.org/977543002

Cr-Commit-Position: refs/heads/master@{#26971}
parent b1d2097d
...@@ -3009,8 +3009,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, ...@@ -3009,8 +3009,8 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
} }
Statement* Parser::DesugarLetBindingsInForStatement( Statement* Parser::DesugarLexicalBindingsInForStatement(
Scope* inner_scope, ZoneList<const AstRawString*>* names, Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
ForStatement* loop, Statement* init, Expression* cond, Statement* next, ForStatement* loop, Statement* init, Expression* cond, Statement* next,
Statement* body, bool* ok) { Statement* body, bool* ok) {
// ES6 13.6.3.4 specifies that on each loop iteration the let variables are // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
...@@ -3020,16 +3020,16 @@ Statement* Parser::DesugarLetBindingsInForStatement( ...@@ -3020,16 +3020,16 @@ Statement* Parser::DesugarLetBindingsInForStatement(
// //
// We rewrite a for statement of the form // 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 // into
// //
// { // {
// let x = i; // let/const x = i;
// temp_x = x; // temp_x = x;
// first = 1; // first = 1;
// outer: for (;;) { // outer: for (;;) {
// let x = temp_x; // let/const x = temp_x;
// if (first == 1) { // if (first == 1) {
// first = 0; // first = 0;
// } else { // } else {
...@@ -3056,12 +3056,12 @@ Statement* Parser::DesugarLetBindingsInForStatement( ...@@ -3056,12 +3056,12 @@ Statement* Parser::DesugarLetBindingsInForStatement(
Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
RelocInfo::kNoPosition); RelocInfo::kNoPosition);
// Add statement: let x = i. // Add statement: let/const x = i.
outer_block->AddStatement(init, zone()); outer_block->AddStatement(init, zone());
const AstRawString* temp_name = ast_value_factory()->dot_for_string(); 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. // make statement: temp_x = x.
for (int i = 0; i < names->length(); i++) { for (int i = 0; i < names->length(); i++) {
VariableProxy* proxy = NewUnresolved(names->at(i), LET); VariableProxy* proxy = NewUnresolved(names->at(i), LET);
...@@ -3106,16 +3106,17 @@ Statement* Parser::DesugarLetBindingsInForStatement( ...@@ -3106,16 +3106,17 @@ Statement* Parser::DesugarLetBindingsInForStatement(
ZoneList<Variable*> inner_vars(names->length(), zone()); ZoneList<Variable*> inner_vars(names->length(), zone());
// For each let variable x: // 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++) { 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( Declaration* declaration = factory()->NewVariableDeclaration(
proxy, LET, scope_, RelocInfo::kNoPosition); proxy, mode, scope_, RelocInfo::kNoPosition);
Declare(declaration, true, CHECK_OK); Declare(declaration, true, CHECK_OK);
inner_vars.Add(declaration->proxy()->var(), zone()); inner_vars.Add(declaration->proxy()->var(), zone());
VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
Assignment* assignment = factory()->NewAssignment( 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 = Statement* assignment_statement =
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
proxy->var()->set_initializer_position(init->position()); proxy->var()->set_initializer_position(init->position());
...@@ -3244,8 +3245,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3244,8 +3245,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
int stmt_pos = peek_position(); int stmt_pos = peek_position();
bool is_const = false;
Statement* init = NULL; 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. // Create an in-between scope for let-bound iteration variables.
Scope* saved_scope = scope_; Scope* saved_scope = scope_;
...@@ -3297,12 +3299,12 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3297,12 +3299,12 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
} }
} else if ((peek() == Token::LET || peek() == Token::CONST) && } else if ((peek() == Token::LET || peek() == Token::CONST) &&
is_strict(language_mode())) { is_strict(language_mode())) {
bool is_const = peek() == Token::CONST; is_const = peek() == Token::CONST;
const AstRawString* name = NULL; const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers; VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement = Block* variable_statement =
ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, ParseVariableDeclarations(kForStatement, &decl_props,
&name, CHECK_OK); &lexical_bindings, &name, CHECK_OK);
bool accept_IN = name != NULL && decl_props != kHasInitializers; bool accept_IN = name != NULL && decl_props != kHasInitializers;
bool accept_OF = decl_props == kHasNoInitializers; bool accept_OF = decl_props == kHasNoInitializers;
ForEachStatement::VisitMode mode; ForEachStatement::VisitMode mode;
...@@ -3419,7 +3421,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3419,7 +3421,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
// If there are let bindings, then condition and the next statement of the // If there are let bindings, then condition and the next statement of the
// for loop must be parsed in a new scope. // for loop must be parsed in a new scope.
Scope* inner_scope = NULL; Scope* inner_scope = NULL;
if (let_bindings.length() > 0) { if (lexical_bindings.length() > 0) {
inner_scope = NewScope(for_scope, BLOCK_SCOPE); inner_scope = NewScope(for_scope, BLOCK_SCOPE);
inner_scope->set_start_position(scanner()->location().beg_pos); inner_scope->set_start_position(scanner()->location().beg_pos);
scope_ = inner_scope; scope_ = inner_scope;
...@@ -3442,10 +3444,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3442,10 +3444,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
Statement* body = ParseSubStatement(NULL, CHECK_OK); Statement* body = ParseSubStatement(NULL, CHECK_OK);
Statement* result = NULL; Statement* result = NULL;
if (let_bindings.length() > 0) { if (lexical_bindings.length() > 0) {
scope_ = for_scope; scope_ = for_scope;
result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, result = DesugarLexicalBindingsInForStatement(
init, cond, next, body, CHECK_OK); inner_scope, is_const, &lexical_bindings, loop, init, cond,
next, body, CHECK_OK);
scope_ = saved_scope; scope_ = saved_scope;
for_scope->set_end_position(scanner()->location().end_pos); for_scope->set_end_position(scanner()->location().end_pos);
} else { } else {
......
...@@ -763,8 +763,8 @@ class Parser : public ParserBase<ParserTraits> { ...@@ -763,8 +763,8 @@ class Parser : public ParserBase<ParserTraits> {
Expression* each, Expression* each,
Expression* subject, Expression* subject,
Statement* body); Statement* body);
Statement* DesugarLetBindingsInForStatement( Statement* DesugarLexicalBindingsInForStatement(
Scope* inner_scope, ZoneList<const AstRawString*>* names, Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names,
ForStatement* loop, Statement* init, Expression* cond, Statement* next, ForStatement* loop, Statement* init, Expression* cond, Statement* next,
Statement* body, bool* ok); Statement* body, bool* ok);
......
// 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.
'use strict';
assertThrows(function() { for (const i = 0; ; i++) {} }, TypeError);
assertThrows("'use strict'; for (const i = 0; ; i++) {}", TypeError);
...@@ -93,6 +93,22 @@ function constDecl9(use) { ...@@ -93,6 +93,22 @@ function constDecl9(use) {
return "(function constvar() { " + 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, let decls = [ constDecl0,
constDecl1, constDecl1,
constDecl2, constDecl2,
...@@ -102,7 +118,10 @@ let decls = [ constDecl0, ...@@ -102,7 +118,10 @@ let decls = [ constDecl0,
constDecl6, constDecl6,
constDecl7, constDecl7,
constDecl8, constDecl8,
constDecl9 constDecl9,
constDecl10,
constDecl11,
constDecl12
]; ];
let declsForTDZ = new Set([constDecl1, constDecl3, constDecl5, constDecl7]); let declsForTDZ = new Set([constDecl1, constDecl3, constDecl5, constDecl7]);
let uses = [ 'constvar = 1;', let uses = [ 'constvar = 1;',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment