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; |