Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index bec0a4bd571e29dda80149b669062641c40b81e1..5c85b97ba655848215c623222509fc4528ea1b31 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -2156,6 +2156,7 @@ Block* Parser::ParseVariableDeclarations( |
Block* block = factory()->NewBlock(NULL, 1, true, pos); |
int nvars = 0; // the number of variables declared |
const AstRawString* name = NULL; |
+ bool is_for_iteration_variable; |
do { |
if (fni_ != NULL) fni_->Enter(); |
@@ -2179,6 +2180,13 @@ Block* Parser::ParseVariableDeclarations( |
// For let/const declarations in harmony mode, we can also immediately |
// pre-resolve the proxy because it resides in the same scope as the |
// declaration. |
+ is_for_iteration_variable = |
+ var_context == kForStatement && |
+ (peek() == Token::IN || PeekContextualKeyword(CStrVector("of"))); |
+ if (is_for_iteration_variable && mode == CONST) { |
+ needs_init = false; |
+ } |
+ |
Interface* interface = |
is_const ? Interface::NewConst() : Interface::NewValue(); |
VariableProxy* proxy = NewUnresolved(name, mode, interface); |
@@ -2224,7 +2232,8 @@ Block* Parser::ParseVariableDeclarations( |
Expression* value = NULL; |
int pos = -1; |
// Harmony consts have non-optional initializers. |
- if (peek() == Token::ASSIGN || mode == CONST) { |
+ if (peek() == Token::ASSIGN || |
+ (mode == CONST && !is_for_iteration_variable)) { |
Expect(Token::ASSIGN, CHECK_OK); |
pos = position(); |
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
@@ -2357,7 +2366,7 @@ Block* Parser::ParseVariableDeclarations( |
// If there was a single non-const declaration, return it in the output |
// parameter for possible use by for/in. |
- if (nvars == 1 && !is_const) { |
+ if (nvars == 1 && (!is_const || is_for_iteration_variable)) { |
*out = name; |
} |
@@ -3094,7 +3103,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
Expect(Token::LPAREN, CHECK_OK); |
for_scope->set_start_position(scanner()->location().beg_pos); |
if (peek() != Token::SEMICOLON) { |
- if (peek() == Token::VAR || peek() == Token::CONST) { |
+ if (peek() == Token::VAR || |
+ (peek() == Token::CONST && strict_mode() == SLOPPY)) { |
bool is_const = peek() == Token::CONST; |
const AstRawString* name = NULL; |
VariableDeclarationProperties decl_props = kHasNoInitializers; |
@@ -3131,8 +3141,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
} else { |
init = variable_statement; |
} |
- } else if (peek() == Token::LET && strict_mode() == STRICT) { |
- DCHECK(allow_harmony_scoping()); |
+ } else if ((peek() == Token::LET || peek() == Token::CONST) && |
+ strict_mode() == STRICT) { |
+ bool is_const = peek() == Token::CONST; |
const AstRawString* name = NULL; |
VariableDeclarationProperties decl_props = kHasNoInitializers; |
Block* variable_statement = |
@@ -3145,13 +3156,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
if (accept_IN && CheckInOrOf(accept_OF, &mode)) { |
// Rewrite a for-in statement of the form |
// |
- // for (let x in e) b |
+ // for (let/const x in e) b |
// |
// into |
// |
// <let x' be a temporary variable> |
// for (x' in e) { |
- // let x; |
+ // let/const x; |
// x = x'; |
// b; |
// } |
@@ -3171,13 +3182,13 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
scope_ = for_scope; |
Expect(Token::RPAREN, CHECK_OK); |
- VariableProxy* each = |
- scope_->NewUnresolved(factory(), name, Interface::NewValue()); |
+ VariableProxy* each = scope_->NewUnresolved(factory(), name); |
Statement* body = ParseStatement(NULL, CHECK_OK); |
Block* body_block = |
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
+ Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; |
Assignment* assignment = factory()->NewAssignment( |
- Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition); |
+ init_op, each, temp_proxy, RelocInfo::kNoPosition); |
Statement* assignment_statement = factory()->NewExpressionStatement( |
assignment, RelocInfo::kNoPosition); |
body_block->AddStatement(variable_statement, zone()); |