Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index a23547ee3462d18754509c520f614e30e1c0ba3c..0aca8cd3a35a4d05bae04d836ada32f1b6ee3828 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -2217,8 +2217,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| // VariableDeclarations ';' |
| const AstRawString* ignore; |
| - Block* result = |
| - ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK); |
| + Block* result = ParseVariableDeclarations(var_context, nullptr, names, |
| + &ignore, nullptr, CHECK_OK); |
| ExpectSemicolon(CHECK_OK); |
| return result; |
| } |
| @@ -2232,9 +2232,8 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context, |
| Block* Parser::ParseVariableDeclarations( |
| VariableDeclarationContext var_context, |
| VariableDeclarationProperties* decl_props, |
|
marja
2015/04/07 08:30:34
Isn't decl_props now unnecessary? If not, why not?
caitp (gmail)
2015/04/07 11:56:20
Yes, it can be removed
|
| - 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)?)+[','] |
| // |
| @@ -2248,7 +2247,6 @@ Block* Parser::ParseVariableDeclarations( |
| // TODO(ES6): |
| // ConstBinding :: |
| // BindingPattern '=' AssignmentExpression |
| - |
|
marja
2015/04/07 08:30:34
Nit: this was probably an accidental deletion.
|
| int pos = peek_position(); |
| VariableMode mode = VAR; |
| // True if the binding needs initialization. 'let' and 'const' declared |
| @@ -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 && |
| @@ -3364,16 +3369,28 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| (peek() == Token::CONST && is_sloppy(language_mode()))) { |
| const AstRawString* name = NULL; |
| VariableDeclarationProperties decl_props = kHasNoInitializers; |
| + Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
| Block* variable_statement = |
| - ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, |
| - CHECK_OK); |
| - bool accept_OF = decl_props == kHasNoInitializers; |
| + ParseVariableDeclarations(kForStatement, &decl_props, 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); |
| @@ -3403,18 +3420,28 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| is_const = peek() == Token::CONST; |
| const AstRawString* name = NULL; |
| VariableDeclarationProperties decl_props = kHasNoInitializers; |
| - 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; |
| + Scanner::Location first_initializer_loc = Scanner::Location::invalid(); |
| + Block* variable_statement = ParseVariableDeclarations( |
| + kForStatement, &decl_props, &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 |