| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index b9d2c2f9e7df66c6e5e0feebf727001aac2915be..ee0f7dc6804848109197ed9878835d791e3d77f4 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -2295,8 +2295,8 @@ const AstRawString* Parser::DeclarationParsingResult::SingleName() const {
|
|
|
| Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
|
| ZoneList<const AstRawString*>* names, bool* ok) {
|
| - Block* result =
|
| - descriptor.parser->factory()->NewBlock(NULL, 1, true, descriptor.pos);
|
| + Block* result = descriptor.parser->factory()->NewBlock(
|
| + NULL, 1, true, descriptor.declaration_pos);
|
| for (auto declaration : declarations) {
|
| PatternRewriter::DeclareAndInitializeVariables(
|
| result, &descriptor, &declaration, names, CHECK_OK);
|
| @@ -2350,7 +2350,8 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| // BindingPattern '=' AssignmentExpression
|
|
|
| parsing_result->descriptor.parser = this;
|
| - parsing_result->descriptor.pos = peek_position();
|
| + parsing_result->descriptor.declaration_pos = peek_position();
|
| + parsing_result->descriptor.initialization_pos = peek_position();
|
| parsing_result->descriptor.mode = VAR;
|
| // True if the binding needs initialization. 'let' and 'const' declared
|
| // bindings are created uninitialized by their declaration nodes and
|
| @@ -3417,11 +3418,10 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| bool is_let_identifier_expression = false;
|
| DeclarationParsingResult parsing_result;
|
| if (peek() != Token::SEMICOLON) {
|
| - if (peek() == Token::VAR ||
|
| - (peek() == Token::CONST && is_sloppy(language_mode()))) {
|
| + if (peek() == Token::VAR || peek() == Token::CONST ||
|
| + (peek() == Token::LET && is_strict(language_mode()))) {
|
| ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
|
| - Block* variable_statement =
|
| - parsing_result.BuildInitializationBlock(nullptr, CHECK_OK);
|
| + is_const = parsing_result.descriptor.mode == CONST;
|
|
|
| int num_decl = parsing_result.declarations.length();
|
| bool accept_IN = num_decl >= 1;
|
| @@ -3454,124 +3454,100 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| *ok = false;
|
| return nullptr;
|
| }
|
| - ForEachStatement* loop =
|
| - factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| - Target target(&this->target_stack_, loop);
|
|
|
| - Expression* enumerable = ParseExpression(true, CHECK_OK);
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| -
|
| - VariableProxy* each =
|
| - scope_->NewUnresolved(factory(), parsing_result.SingleName(),
|
| - Variable::NORMAL, each_beg_pos, each_end_pos);
|
| - Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
| - InitializeForEachStatement(loop, each, enumerable, body);
|
| - Block* result =
|
| - factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
|
| - result->AddStatement(variable_statement, zone());
|
| - result->AddStatement(loop, zone());
|
| - scope_ = saved_scope;
|
| - for_scope->set_end_position(scanner()->location().end_pos);
|
| - for_scope = for_scope->FinalizeBlockScope();
|
| - DCHECK(for_scope == NULL);
|
| - // Parsed for-in loop w/ variable/const declaration.
|
| - return result;
|
| - } else {
|
| - init = variable_statement;
|
| - }
|
| - } else if ((peek() == Token::LET || peek() == Token::CONST) &&
|
| - is_strict(language_mode())) {
|
| - is_const = peek() == Token::CONST;
|
| - ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
|
| - DCHECK(parsing_result.descriptor.pos != RelocInfo::kNoPosition);
|
| -
|
| - int num_decl = parsing_result.declarations.length();
|
| - bool accept_IN = num_decl >= 1;
|
| - 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 (num_decl != 1) {
|
| - const char* loop_type =
|
| - mode == ForEachStatement::ITERATE ? "for-of" : "for-in";
|
| - ParserTraits::ReportMessageAt(
|
| - parsing_result.bindings_loc,
|
| - MessageTemplate::kForInOfLoopMultiBindings, loop_type);
|
| - *ok = false;
|
| - return nullptr;
|
| - }
|
| - if (parsing_result.first_initializer_loc.IsValid() &&
|
| - (is_strict(language_mode()) || mode == ForEachStatement::ITERATE)) {
|
| - if (mode == ForEachStatement::ITERATE) {
|
| - ReportMessageAt(parsing_result.first_initializer_loc,
|
| - MessageTemplate::kForOfLoopInitializer);
|
| - } else {
|
| - ReportMessageAt(parsing_result.first_initializer_loc,
|
| - MessageTemplate::kForInLoopInitializer);
|
| - }
|
| - *ok = false;
|
| - return nullptr;
|
| + DCHECK(parsing_result.declarations.length() == 1);
|
| + Block* init_block = nullptr;
|
| +
|
| + // special case for legacy for (var/const x =.... in)
|
| + if (is_sloppy(language_mode()) &&
|
| + !IsLexicalVariableMode(parsing_result.descriptor.mode) &&
|
| + parsing_result.declarations[0].initializer != nullptr) {
|
| + VariableProxy* single_var = scope_->NewUnresolved(
|
| + factory(), parsing_result.SingleName(), Variable::NORMAL,
|
| + each_beg_pos, each_end_pos);
|
| + init_block = factory()->NewBlock(
|
| + nullptr, 2, true, parsing_result.descriptor.declaration_pos);
|
| + init_block->AddStatement(
|
| + factory()->NewExpressionStatement(
|
| + factory()->NewAssignment(
|
| + Token::ASSIGN, single_var,
|
| + parsing_result.declarations[0].initializer,
|
| + RelocInfo::kNoPosition),
|
| + RelocInfo::kNoPosition),
|
| + zone());
|
| }
|
| - // Rewrite a for-in statement of the form
|
| +
|
| + // Rewrite a for-in/of statement of the form
|
| //
|
| - // for (let/const x in e) b
|
| + // for (let/const/var x in/of e) b
|
| //
|
| // into
|
| //
|
| // <let x' be a temporary variable>
|
| - // for (x' in e) {
|
| - // let/const x;
|
| + // for (x' in/of e) {
|
| + // let/const/var x;
|
| // x = x';
|
| // b;
|
| // }
|
|
|
| - // TODO(keuchel): Move the temporary variable to the block scope, after
|
| - // implementing stack allocated block scoped variables.
|
| Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
| ast_value_factory()->dot_for_string());
|
| - VariableProxy* temp_proxy =
|
| - factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| ForEachStatement* loop =
|
| factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| Target target(&this->target_stack_, loop);
|
|
|
| - // The expression does not see the loop variable.
|
| + // The expression does not see the lexical loop variables.
|
| scope_ = saved_scope;
|
| Expression* enumerable = ParseExpression(true, CHECK_OK);
|
| scope_ = for_scope;
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
| +
|
| Block* body_block =
|
| factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
|
|
| - auto each_initialization_block = factory()->NewBlock(
|
| - nullptr, 1, true, parsing_result.descriptor.pos);
|
| + auto each_initialization_block =
|
| + factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
|
| {
|
| DCHECK(parsing_result.declarations.length() == 1);
|
| DeclarationParsingResult::Declaration decl =
|
| parsing_result.declarations[0];
|
| - decl.initializer = temp_proxy;
|
| + auto descriptor = parsing_result.descriptor;
|
| + descriptor.declaration_pos = RelocInfo::kNoPosition;
|
| + decl.initializer = factory()->NewVariableProxy(temp);
|
| +
|
| PatternRewriter::DeclareAndInitializeVariables(
|
| - each_initialization_block, &parsing_result.descriptor, &decl,
|
| - &lexical_bindings, CHECK_OK);
|
| + each_initialization_block, &descriptor, &decl,
|
| + IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
|
| + : nullptr,
|
| + CHECK_OK);
|
| }
|
|
|
| body_block->AddStatement(each_initialization_block, zone());
|
| body_block->AddStatement(body, zone());
|
| + VariableProxy* temp_proxy =
|
| + factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
|
| scope_ = saved_scope;
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| - body_block->set_scope(for_scope);
|
| - // Parsed for-in loop w/ let declaration.
|
| - return loop;
|
| + if (for_scope != nullptr) {
|
| + body_block->set_scope(for_scope);
|
| + }
|
| + // Parsed for-in loop w/ variable declarations.
|
| + if (init_block != nullptr) {
|
| + init_block->AddStatement(loop, zone());
|
| + return init_block;
|
| + } else {
|
| + return loop;
|
| + }
|
| } else {
|
| - init = parsing_result.BuildInitializationBlock(&lexical_bindings,
|
| - CHECK_OK);
|
| + init = parsing_result.BuildInitializationBlock(
|
| + IsLexicalVariableMode(parsing_result.descriptor.mode)
|
| + ? &lexical_bindings
|
| + : nullptr,
|
| + CHECK_OK);
|
| }
|
| } else {
|
| Scanner::Location lhs_location = scanner()->peek_location();
|
| @@ -3579,9 +3555,9 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| ForEachStatement::VisitMode mode;
|
| bool accept_OF = expression->IsVariableProxy();
|
| is_let_identifier_expression =
|
| - expression->IsVariableProxy() &&
|
| - expression->AsVariableProxy()->raw_name() ==
|
| - ast_value_factory()->let_string();
|
| + expression->IsVariableProxy() &&
|
| + expression->AsVariableProxy()->raw_name() ==
|
| + ast_value_factory()->let_string();
|
|
|
| if (CheckInOrOf(accept_OF, &mode, ok)) {
|
| if (!*ok) return nullptr;
|
|
|