Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index a23547ee3462d18754509c520f614e30e1c0ba3c..608a6bdaf0435aebb24edeac1bd9a21160a120f7 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -2218,7 +2218,7 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
const AstRawString* ignore; |
Block* result = |
- ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); |
+ ParseVariableDeclarations(var_context, names, &ignore, nullptr, CHECK_OK); |
ExpectSemicolon(CHECK_OK); |
return result; |
} |
@@ -2231,10 +2231,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
// of 'for-in' loops. |
Block* Parser::ParseVariableDeclarations( |
VariableDeclarationContext var_context, |
- VariableDeclarationProperties* decl_props, |
- ZoneList<const AstRawString*>* names, |
- const AstRawString** out, |
- bool* ok) { |
+ ZoneList<const AstRawString*>* names, const AstRawString** out, |
+ Scanner::Location* first_initializer_loc, bool* ok) { |
// VariableDeclarations :: |
// ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] |
// |
@@ -2314,6 +2312,7 @@ Block* Parser::ParseVariableDeclarations( |
// Parse variable name. |
if (nvars > 0) Consume(Token::COMMA); |
name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
+ Scanner::Location variable_loc = scanner()->location(); |
if (fni_ != NULL) fni_->PushVariableName(name); |
// Declare variable. |
@@ -2388,6 +2387,12 @@ Block* Parser::ParseVariableDeclarations( |
Expect(Token::ASSIGN, CHECK_OK); |
pos = position(); |
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); |
+ variable_loc.end_pos = scanner()->location().end_pos; |
+ |
+ if (first_initializer_loc && !first_initializer_loc->IsValid()) { |
+ *first_initializer_loc = variable_loc; |
+ } |
+ |
// Don't infer if it is "a = function(){...}();"-like expression. |
if (fni_ != NULL && |
value->AsCall() == NULL && |
@@ -2396,7 +2401,6 @@ Block* Parser::ParseVariableDeclarations( |
} else { |
fni_->RemoveLastFunction(); |
} |
- if (decl_props != NULL) *decl_props = kHasInitializers; |
// End position of the initializer is after the assignment expression. |
var->set_initializer_position(scanner()->location().end_pos); |
} else { |
@@ -3363,17 +3367,27 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
if (peek() == Token::VAR || |
(peek() == Token::CONST && is_sloppy(language_mode()))) { |
const AstRawString* name = NULL; |
- VariableDeclarationProperties decl_props = kHasNoInitializers; |
- Block* variable_statement = |
- ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
- CHECK_OK); |
- bool accept_OF = decl_props == kHasNoInitializers; |
+ Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
+ Block* variable_statement = ParseVariableDeclarations( |
+ kForStatement, nullptr, &name, &first_initializer_loc, CHECK_OK); |
+ bool accept_OF = true; |
ForEachStatement::VisitMode mode; |
int each_beg_pos = scanner()->location().beg_pos; |
int each_end_pos = scanner()->location().end_pos; |
if (name != NULL && CheckInOrOf(accept_OF, &mode, ok)) { |
if (!*ok) return nullptr; |
+ if (first_initializer_loc.IsValid() && |
+ (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { |
+ if (mode == ForEachStatement::ITERATE) { |
+ ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); |
+ } else { |
+ // TODO(caitp): This should be an error in sloppy mode too. |
+ ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); |
+ } |
+ *ok = false; |
+ return nullptr; |
+ } |
ForEachStatement* loop = |
factory()->NewForEachStatement(mode, labels, stmt_pos); |
Target target(&this->target_stack_, loop); |
@@ -3402,19 +3416,28 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
is_strict(language_mode())) { |
is_const = peek() == Token::CONST; |
const AstRawString* name = NULL; |
- VariableDeclarationProperties decl_props = kHasNoInitializers; |
+ Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
Block* variable_statement = |
- ParseVariableDeclarations(kForStatement, &decl_props, |
- &lexical_bindings, &name, CHECK_OK); |
- bool accept_IN = name != NULL && decl_props != kHasInitializers; |
- bool accept_OF = decl_props == kHasNoInitializers; |
+ ParseVariableDeclarations(kForStatement, &lexical_bindings, &name, |
+ &first_initializer_loc, CHECK_OK); |
+ bool accept_IN = name != NULL; |
+ bool accept_OF = true; |
ForEachStatement::VisitMode mode; |
int each_beg_pos = scanner()->location().beg_pos; |
int each_end_pos = scanner()->location().end_pos; |
if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
if (!*ok) return nullptr; |
- |
+ if (first_initializer_loc.IsValid() && |
+ (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) { |
+ if (mode == ForEachStatement::ITERATE) { |
+ ReportMessageAt(first_initializer_loc, "for_of_loop_initializer"); |
+ } else { |
+ ReportMessageAt(first_initializer_loc, "for_in_loop_initializer"); |
+ } |
+ *ok = false; |
+ return nullptr; |
+ } |
// Rewrite a for-in statement of the form |
// |
// for (let/const x in e) b |