| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 444b20cbf87352cdd4b214938e837c2a7b3b2b52..ad3176433d976431da1ae301a3309d65b249e35c 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -2332,17 +2332,16 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
|
| // is inside an initializer block, it is ignored.
|
|
|
| DeclarationParsingResult parsing_result;
|
| - ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK);
|
| + Block* result =
|
| + ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
|
| ExpectSemicolon(CHECK_OK);
|
| -
|
| - Block* result = parsing_result.BuildInitializationBlock(names, CHECK_OK);
|
| return result;
|
| }
|
|
|
| -
|
| -void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| - DeclarationParsingResult* parsing_result,
|
| - bool* ok) {
|
| +Block* Parser::ParseVariableDeclarations(
|
| + VariableDeclarationContext var_context,
|
| + DeclarationParsingResult* parsing_result,
|
| + ZoneList<const AstRawString*>* names, bool* ok) {
|
| // VariableDeclarations ::
|
| // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
|
| //
|
| @@ -2362,12 +2361,19 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| parsing_result->descriptor.declaration_pos = peek_position();
|
| parsing_result->descriptor.initialization_pos = peek_position();
|
| parsing_result->descriptor.mode = VAR;
|
| +
|
| + Block* init_block = nullptr;
|
| + if (var_context != kForStatement) {
|
| + init_block = factory()->NewBlock(
|
| + NULL, 1, true, parsing_result->descriptor.declaration_pos);
|
| + }
|
| +
|
| if (peek() == Token::VAR) {
|
| if (is_strong(language_mode())) {
|
| Scanner::Location location = scanner()->peek_location();
|
| ReportMessageAt(location, MessageTemplate::kStrongVar);
|
| *ok = false;
|
| - return;
|
| + return nullptr;
|
| }
|
| Consume(Token::VAR);
|
| } else if (peek() == Token::CONST && allow_const()) {
|
| @@ -2405,18 +2411,15 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| {
|
| ExpressionClassifier pattern_classifier;
|
| Token::Value next = peek();
|
| - pattern = ParsePrimaryExpression(&pattern_classifier, ok);
|
| - if (!*ok) return;
|
| - ValidateBindingPattern(&pattern_classifier, ok);
|
| - if (!*ok) return;
|
| + pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
|
| + ValidateBindingPattern(&pattern_classifier, CHECK_OK);
|
| if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
|
| - ValidateLetPattern(&pattern_classifier, ok);
|
| - if (!*ok) return;
|
| + ValidateLetPattern(&pattern_classifier, CHECK_OK);
|
| }
|
| if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) {
|
| ReportUnexpectedToken(next);
|
| *ok = false;
|
| - return;
|
| + return nullptr;
|
| }
|
| }
|
|
|
| @@ -2433,10 +2436,8 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| if (Check(Token::ASSIGN)) {
|
| ExpressionClassifier classifier;
|
| value = ParseAssignmentExpression(var_context != kForStatement,
|
| - &classifier, ok);
|
| - if (!*ok) return;
|
| - value = ParserTraits::RewriteNonPattern(value, &classifier, ok);
|
| - if (!*ok) return;
|
| + &classifier, CHECK_OK);
|
| + value = ParserTraits::RewriteNonPattern(value, &classifier, CHECK_OK);
|
| variable_loc.end_pos = scanner()->location().end_pos;
|
|
|
| if (!parsing_result->first_initializer_loc.IsValid()) {
|
| @@ -2471,7 +2472,7 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| MessageTemplate::kDeclarationMissingInitializer,
|
| !pattern->IsVariableProxy() ? "destructuring" : "const");
|
| *ok = false;
|
| - return;
|
| + return nullptr;
|
| }
|
|
|
| // 'let x' and (legacy) 'const x' initialize 'x' to undefined.
|
| @@ -2485,13 +2486,28 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| initializer_position = position();
|
| }
|
|
|
| - parsing_result->declarations.Add(DeclarationParsingResult::Declaration(
|
| - pattern, initializer_position, value));
|
| + DeclarationParsingResult::Declaration decl(pattern, initializer_position,
|
| + value);
|
| + if (var_context == kForStatement) {
|
| + // Save the declaration for further handling in ParseForStatement.
|
| + parsing_result->declarations.Add(decl);
|
| + } else {
|
| + // Immediately declare the variable otherwise. This avoids O(N^2)
|
| + // behavior (where N is the number of variables in a single
|
| + // declaration) in the PatternRewriter having to do with removing
|
| + // and adding VariableProxies to the Scope (see bug 4699).
|
| + DCHECK_NOT_NULL(init_block);
|
| + PatternRewriter::DeclareAndInitializeVariables(
|
| + init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
|
| + }
|
| first_declaration = false;
|
| } while (peek() == Token::COMMA);
|
|
|
| parsing_result->bindings_loc =
|
| Scanner::Location(bindings_start, scanner()->location().end_pos);
|
| +
|
| + DCHECK(*ok);
|
| + return init_block;
|
| }
|
|
|
|
|
| @@ -3632,7 +3648,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| if (peek() != Token::SEMICOLON) {
|
| if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
|
| (peek() == Token::LET && IsNextLetKeyword())) {
|
| - ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
|
| + ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
|
| + CHECK_OK);
|
|
|
| ForEachStatement::VisitMode mode;
|
| int each_beg_pos = scanner()->location().beg_pos;
|
|
|