| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 77e46685fa96772dea032f88e6ffcb98073f92b5..efba7f2754d877db9a8f3d95ef6208e67d511490 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -1995,6 +1995,138 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
| return stmt;
|
| }
|
|
|
| +// Special case for legacy for
|
| +//
|
| +// for (var x = initializer in enumerable) body
|
| +//
|
| +// An initialization block of the form
|
| +//
|
| +// {
|
| +// x = initializer;
|
| +// }
|
| +//
|
| +// is returned in this case. It has reserved space for two statements,
|
| +// so that (later on during parsing), the equivalent of
|
| +//
|
| +// for (x in enumerable) body
|
| +//
|
| +// is added as a second statement to it.
|
| +Block* Parser::RewriteForVarInLegacy(const ForInfo& for_info) {
|
| + const DeclarationParsingResult::Declaration& decl =
|
| + for_info.parsing_result.declarations[0];
|
| + if (!IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) &&
|
| + decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
|
| + DCHECK(!allow_harmony_for_in());
|
| + ++use_counts_[v8::Isolate::kForInInitializer];
|
| + const AstRawString* name = decl.pattern->AsVariableProxy()->raw_name();
|
| + VariableProxy* single_var = NewUnresolved(name);
|
| + Block* init_block = factory()->NewBlock(
|
| + nullptr, 2, true, for_info.parsing_result.descriptor.declaration_pos);
|
| + init_block->statements()->Add(
|
| + factory()->NewExpressionStatement(
|
| + factory()->NewAssignment(Token::ASSIGN, single_var,
|
| + decl.initializer, kNoSourcePosition),
|
| + kNoSourcePosition),
|
| + zone());
|
| + return init_block;
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| +// Rewrite a for-in/of statement of the form
|
| +//
|
| +// for (let/const/var x in/of e) b
|
| +//
|
| +// into
|
| +//
|
| +// {
|
| +// <let x' be a temporary variable>
|
| +// for (x' in/of e) {
|
| +// let/const/var x;
|
| +// x = x';
|
| +// b;
|
| +// }
|
| +// let x; // for TDZ
|
| +// }
|
| +void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
|
| + Block** body_block,
|
| + Expression** each_variable,
|
| + bool* ok) {
|
| + DeclarationParsingResult::Declaration& decl =
|
| + for_info->parsing_result.declarations[0];
|
| + Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
|
| + auto each_initialization_block =
|
| + factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
|
| + {
|
| + auto descriptor = for_info->parsing_result.descriptor;
|
| + descriptor.declaration_pos = kNoSourcePosition;
|
| + descriptor.initialization_pos = kNoSourcePosition;
|
| + decl.initializer = factory()->NewVariableProxy(temp);
|
| +
|
| + bool is_for_var_of =
|
| + for_info->mode == ForEachStatement::ITERATE &&
|
| + for_info->parsing_result.descriptor.mode == VariableMode::VAR;
|
| +
|
| + PatternRewriter::DeclareAndInitializeVariables(
|
| + this, each_initialization_block, &descriptor, &decl,
|
| + (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
|
| + is_for_var_of)
|
| + ? &for_info->bound_names
|
| + : nullptr,
|
| + CHECK_OK_VOID);
|
| +
|
| + // Annex B.3.5 prohibits the form
|
| + // `try {} catch(e) { for (var e of {}); }`
|
| + // So if we are parsing a statement like `for (var ... of ...)`
|
| + // we need to walk up the scope chain and look for catch scopes
|
| + // which have a simple binding, then compare their binding against
|
| + // all of the names declared in the init of the for-of we're
|
| + // parsing.
|
| + if (is_for_var_of) {
|
| + Scope* catch_scope = scope();
|
| + while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
|
| + if (catch_scope->is_catch_scope()) {
|
| + auto name = catch_scope->catch_variable_name();
|
| + // If it's a simple binding and the name is declared in the for loop.
|
| + if (name != ast_value_factory()->dot_catch_string() &&
|
| + for_info->bound_names.Contains(name)) {
|
| + ReportMessageAt(for_info->parsing_result.bindings_loc,
|
| + MessageTemplate::kVarRedeclaration, name);
|
| + *ok = false;
|
| + return;
|
| + }
|
| + }
|
| + catch_scope = catch_scope->outer_scope();
|
| + }
|
| + }
|
| + }
|
| +
|
| + *body_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
|
| + (*body_block)->statements()->Add(each_initialization_block, zone());
|
| + *each_variable = factory()->NewVariableProxy(temp, for_info->each_loc.beg_pos,
|
| + for_info->each_loc.end_pos);
|
| +}
|
| +
|
| +// Create a TDZ for any lexically-bound names in for in/of statements.
|
| +Block* Parser::CreateForEachStatementTDZ(Block* init_block,
|
| + const ForInfo& for_info, bool* ok) {
|
| + if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
|
| + DCHECK_NULL(init_block);
|
| +
|
| + init_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
|
| +
|
| + for (int i = 0; i < for_info.bound_names.length(); ++i) {
|
| + // TODO(adamk): This needs to be some sort of special
|
| + // INTERNAL variable that's invisible to the debugger
|
| + // but visible to everything else.
|
| + Declaration* tdz_decl = DeclareVariable(for_info.bound_names[i], LET,
|
| + kNoSourcePosition, CHECK_OK);
|
| + tdz_decl->proxy()->var()->set_initializer_position(position());
|
| + }
|
| + }
|
| + return init_block;
|
| +}
|
| +
|
| Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
| Expression* each,
|
| Expression* iterable,
|
| @@ -2119,9 +2251,8 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of,
|
| }
|
|
|
| Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| - Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
|
| ForStatement* loop, Statement* init, Expression* cond, Statement* next,
|
| - Statement* body, bool* ok) {
|
| + Statement* body, Scope* inner_scope, const ForInfo& for_info, bool* ok) {
|
| // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
|
| // copied into a new environment. Moreover, the "next" statement must be
|
| // evaluated not in the environment of the just completed iteration but in
|
| @@ -2159,11 +2290,11 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| // }
|
| // }
|
|
|
| - DCHECK(names->length() > 0);
|
| - ZoneList<Variable*> temps(names->length(), zone());
|
| + DCHECK(for_info.bound_names.length() > 0);
|
| + ZoneList<Variable*> temps(for_info.bound_names.length(), zone());
|
|
|
| - Block* outer_block =
|
| - factory()->NewBlock(NULL, names->length() + 4, false, kNoSourcePosition);
|
| + Block* outer_block = factory()->NewBlock(
|
| + nullptr, for_info.bound_names.length() + 4, false, kNoSourcePosition);
|
|
|
| // Add statement: let/const x = i.
|
| outer_block->statements()->Add(init, zone());
|
| @@ -2172,8 +2303,8 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
|
|
| // For each lexical variable x:
|
| // make statement: temp_x = x.
|
| - for (int i = 0; i < names->length(); i++) {
|
| - VariableProxy* proxy = NewUnresolved(names->at(i));
|
| + for (int i = 0; i < for_info.bound_names.length(); i++) {
|
| + VariableProxy* proxy = NewUnresolved(for_info.bound_names[i]);
|
| Variable* temp = NewTemporary(temp_name);
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
| Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, temp_proxy,
|
| @@ -2217,14 +2348,15 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| {
|
| BlockState block_state(&scope_state_, inner_scope);
|
|
|
| - Block* ignore_completion_block =
|
| - factory()->NewBlock(NULL, names->length() + 3, true, kNoSourcePosition);
|
| - ZoneList<Variable*> inner_vars(names->length(), zone());
|
| + Block* ignore_completion_block = factory()->NewBlock(
|
| + nullptr, for_info.bound_names.length() + 3, true, kNoSourcePosition);
|
| + ZoneList<Variable*> inner_vars(for_info.bound_names.length(), zone());
|
| // For each let variable x:
|
| // make statement: let/const x = temp_x.
|
| - for (int i = 0; i < names->length(); i++) {
|
| - Declaration* decl =
|
| - DeclareVariable(names->at(i), mode, kNoSourcePosition, CHECK_OK);
|
| + for (int i = 0; i < for_info.bound_names.length(); i++) {
|
| + Declaration* decl = DeclareVariable(
|
| + for_info.bound_names[i], for_info.parsing_result.descriptor.mode,
|
| + kNoSourcePosition, CHECK_OK);
|
| inner_vars.Add(decl->proxy()->var(), zone());
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| Assignment* assignment = factory()->NewAssignment(
|
| @@ -2308,7 +2440,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
|
|
| // Make the comma-separated list of temp_x = x assignments.
|
| int inner_var_proxy_pos = scanner()->location().beg_pos;
|
| - for (int i = 0; i < names->length(); i++) {
|
| + for (int i = 0; i < for_info.bound_names.length(); i++) {
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| VariableProxy* proxy =
|
| factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
|
| @@ -2358,365 +2490,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| return outer_block;
|
| }
|
|
|
| -Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| - bool* ok) {
|
| - int stmt_pos = peek_position();
|
| - Statement* init = NULL;
|
| - ZoneList<const AstRawString*> bound_names(1, zone());
|
| - bool bound_names_are_lexical = false;
|
| -
|
| - // Create an in-between scope for let-bound iteration variables.
|
| - BlockState for_state(&scope_state_);
|
| - Expect(Token::FOR, CHECK_OK);
|
| - Expect(Token::LPAREN, CHECK_OK);
|
| - for_state.set_start_position(scanner()->location().beg_pos);
|
| - for_state.set_is_hidden();
|
| - DeclarationParsingResult parsing_result;
|
| - if (peek() != Token::SEMICOLON) {
|
| - if (peek() == Token::VAR || peek() == Token::CONST ||
|
| - (peek() == Token::LET && IsNextLetKeyword())) {
|
| - ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
|
| - CHECK_OK);
|
| -
|
| - ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
|
| - int each_beg_pos = scanner()->location().beg_pos;
|
| - int each_end_pos = scanner()->location().end_pos;
|
| -
|
| - if (CheckInOrOf(&mode)) {
|
| - if (parsing_result.declarations.length() != 1) {
|
| - ReportMessageAt(parsing_result.bindings_loc,
|
| - MessageTemplate::kForInOfLoopMultiBindings,
|
| - ForEachStatement::VisitModeString(mode));
|
| - *ok = false;
|
| - return nullptr;
|
| - }
|
| - DeclarationParsingResult::Declaration& decl =
|
| - parsing_result.declarations[0];
|
| - if (parsing_result.first_initializer_loc.IsValid() &&
|
| - (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
|
| - IsLexicalVariableMode(parsing_result.descriptor.mode) ||
|
| - !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) {
|
| - // Only increment the use count if we would have let this through
|
| - // without the flag.
|
| - if (allow_harmony_for_in()) {
|
| - ++use_counts_[v8::Isolate::kForInInitializer];
|
| - }
|
| - ReportMessageAt(parsing_result.first_initializer_loc,
|
| - MessageTemplate::kForInOfLoopInitializer,
|
| - ForEachStatement::VisitModeString(mode));
|
| - *ok = false;
|
| - return nullptr;
|
| - }
|
| -
|
| - Block* init_block = nullptr;
|
| - bound_names_are_lexical =
|
| - IsLexicalVariableMode(parsing_result.descriptor.mode);
|
| -
|
| - // special case for legacy for (var ... = ... in ...)
|
| - if (!bound_names_are_lexical && decl.pattern->IsVariableProxy() &&
|
| - decl.initializer != nullptr) {
|
| - DCHECK(!allow_harmony_for_in());
|
| - ++use_counts_[v8::Isolate::kForInInitializer];
|
| - const AstRawString* name =
|
| - decl.pattern->AsVariableProxy()->raw_name();
|
| - VariableProxy* single_var = NewUnresolved(name);
|
| - init_block = factory()->NewBlock(
|
| - nullptr, 2, true, parsing_result.descriptor.declaration_pos);
|
| - init_block->statements()->Add(
|
| - factory()->NewExpressionStatement(
|
| - factory()->NewAssignment(Token::ASSIGN, single_var,
|
| - decl.initializer, kNoSourcePosition),
|
| - kNoSourcePosition),
|
| - zone());
|
| - }
|
| -
|
| - // Rewrite a for-in/of statement of the form
|
| - //
|
| - // for (let/const/var x in/of e) b
|
| - //
|
| - // into
|
| - //
|
| - // {
|
| - // <let x' be a temporary variable>
|
| - // for (x' in/of e) {
|
| - // let/const/var x;
|
| - // x = x';
|
| - // b;
|
| - // }
|
| - // let x; // for TDZ
|
| - // }
|
| -
|
| - Variable* temp = NewTemporary(ast_value_factory()->dot_for_string());
|
| - ForEachStatement* loop =
|
| - factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| - ParserTarget target(this, loop);
|
| -
|
| - int each_keyword_position = scanner()->location().beg_pos;
|
| -
|
| - Expression* enumerable;
|
| - if (mode == ForEachStatement::ITERATE) {
|
| - ExpressionClassifier classifier(this);
|
| - enumerable = ParseAssignmentExpression(true, CHECK_OK);
|
| - RewriteNonPattern(CHECK_OK);
|
| - } else {
|
| - enumerable = ParseExpression(true, CHECK_OK);
|
| - }
|
| -
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| -
|
| -
|
| - Block* body_block =
|
| - factory()->NewBlock(NULL, 3, false, kNoSourcePosition);
|
| -
|
| - Statement* final_loop;
|
| - {
|
| - ReturnExprScope no_tail_calls(function_state_,
|
| - ReturnExprContext::kInsideForInOfBody);
|
| - BlockState block_state(&scope_state_);
|
| - block_state.set_start_position(scanner()->location().beg_pos);
|
| -
|
| - Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
|
| -
|
| - auto each_initialization_block =
|
| - factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
|
| - {
|
| - auto descriptor = parsing_result.descriptor;
|
| - descriptor.declaration_pos = kNoSourcePosition;
|
| - descriptor.initialization_pos = kNoSourcePosition;
|
| - decl.initializer = factory()->NewVariableProxy(temp);
|
| -
|
| - bool is_for_var_of =
|
| - mode == ForEachStatement::ITERATE &&
|
| - parsing_result.descriptor.mode == VariableMode::VAR;
|
| -
|
| - PatternRewriter::DeclareAndInitializeVariables(
|
| - this, each_initialization_block, &descriptor, &decl,
|
| - bound_names_are_lexical || is_for_var_of ? &bound_names
|
| - : nullptr,
|
| - CHECK_OK);
|
| -
|
| - // Annex B.3.5 prohibits the form
|
| - // `try {} catch(e) { for (var e of {}); }`
|
| - // So if we are parsing a statement like `for (var ... of ...)`
|
| - // we need to walk up the scope chain and look for catch scopes
|
| - // which have a simple binding, then compare their binding against
|
| - // all of the names declared in the init of the for-of we're
|
| - // parsing.
|
| - if (is_for_var_of) {
|
| - Scope* catch_scope = scope();
|
| - while (catch_scope != nullptr &&
|
| - !catch_scope->is_declaration_scope()) {
|
| - if (catch_scope->is_catch_scope()) {
|
| - auto name = catch_scope->catch_variable_name();
|
| - if (name !=
|
| - ast_value_factory()
|
| - ->dot_catch_string()) { // i.e. is a simple binding
|
| - if (bound_names.Contains(name)) {
|
| - ReportMessageAt(parsing_result.bindings_loc,
|
| - MessageTemplate::kVarRedeclaration, name);
|
| - *ok = false;
|
| - return nullptr;
|
| - }
|
| - }
|
| - }
|
| - catch_scope = catch_scope->outer_scope();
|
| - }
|
| - }
|
| - }
|
| -
|
| - body_block->statements()->Add(each_initialization_block, zone());
|
| - body_block->statements()->Add(body, zone());
|
| - VariableProxy* temp_proxy =
|
| - factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| - final_loop = InitializeForEachStatement(
|
| - loop, temp_proxy, enumerable, body_block, each_keyword_position);
|
| - block_state.set_end_position(scanner()->location().end_pos);
|
| - body_block->set_scope(block_state.FinalizedBlockScope());
|
| - }
|
| -
|
| - // Create a TDZ for any lexically-bound names.
|
| - if (bound_names_are_lexical) {
|
| - DCHECK_NULL(init_block);
|
| -
|
| - init_block =
|
| - factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
|
| -
|
| - for (int i = 0; i < bound_names.length(); ++i) {
|
| - // TODO(adamk): This needs to be some sort of special
|
| - // INTERNAL variable that's invisible to the debugger
|
| - // but visible to everything else.
|
| - Declaration* tdz_decl = DeclareVariable(
|
| - bound_names[i], LET, kNoSourcePosition, CHECK_OK);
|
| - tdz_decl->proxy()->var()->set_initializer_position(position());
|
| - }
|
| - }
|
| -
|
| - for_state.set_end_position(scanner()->location().end_pos);
|
| - Scope* for_scope = for_state.FinalizedBlockScope();
|
| - // Parsed for-in loop w/ variable declarations.
|
| - if (init_block != nullptr) {
|
| - init_block->statements()->Add(final_loop, zone());
|
| - init_block->set_scope(for_scope);
|
| - return init_block;
|
| - } else {
|
| - DCHECK_NULL(for_scope);
|
| - return final_loop;
|
| - }
|
| - } else {
|
| - bound_names_are_lexical =
|
| - IsLexicalVariableMode(parsing_result.descriptor.mode);
|
| - init = BuildInitializationBlock(
|
| - &parsing_result, bound_names_are_lexical ? &bound_names : nullptr,
|
| - CHECK_OK);
|
| - }
|
| - } else {
|
| - int lhs_beg_pos = peek_position();
|
| - ExpressionClassifier classifier(this);
|
| - Expression* expression = ParseExpressionCoverGrammar(false, CHECK_OK);
|
| - int lhs_end_pos = scanner()->location().end_pos;
|
| - ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
|
| -
|
| - bool is_for_each = CheckInOrOf(&mode);
|
| - bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
|
| - expression->IsObjectLiteral());
|
| -
|
| - if (is_destructuring) {
|
| - ValidateAssignmentPattern(CHECK_OK);
|
| - } else {
|
| - RewriteNonPattern(CHECK_OK);
|
| - }
|
| -
|
| - if (is_for_each) {
|
| - if (!is_destructuring) {
|
| - expression = CheckAndRewriteReferenceExpression(
|
| - expression, lhs_beg_pos, lhs_end_pos,
|
| - MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
|
| - }
|
| -
|
| - ForEachStatement* loop =
|
| - factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| - ParserTarget target(this, loop);
|
| -
|
| - int each_keyword_position = scanner()->location().beg_pos;
|
| -
|
| - Expression* enumerable;
|
| - if (mode == ForEachStatement::ITERATE) {
|
| - ExpressionClassifier classifier(this);
|
| - enumerable = ParseAssignmentExpression(true, CHECK_OK);
|
| - RewriteNonPattern(CHECK_OK);
|
| - } else {
|
| - enumerable = ParseExpression(true, CHECK_OK);
|
| - }
|
| -
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| -
|
| - {
|
| - ReturnExprScope no_tail_calls(function_state_,
|
| - ReturnExprContext::kInsideForInOfBody);
|
| - BlockState block_state(&scope_state_);
|
| - block_state.set_start_position(scanner()->location().beg_pos);
|
| -
|
| - // For legacy compat reasons, give for loops similar treatment to
|
| - // if statements in allowing a function declaration for a body
|
| - Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
|
| - block_state.set_end_position(scanner()->location().end_pos);
|
| - Statement* final_loop = InitializeForEachStatement(
|
| - loop, expression, enumerable, body, each_keyword_position);
|
| -
|
| - Scope* for_scope = for_state.FinalizedBlockScope();
|
| - DCHECK_NULL(for_scope);
|
| - USE(for_scope);
|
| - Scope* block_scope = block_state.FinalizedBlockScope();
|
| - DCHECK_NULL(block_scope);
|
| - USE(block_scope);
|
| - return final_loop;
|
| - }
|
| - } else {
|
| - init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Standard 'for' loop
|
| - ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
|
| - ParserTarget target(this, loop);
|
| -
|
| - // Parsed initializer at this point.
|
| - Expect(Token::SEMICOLON, CHECK_OK);
|
| -
|
| - Expression* cond = NULL;
|
| - Statement* next = NULL;
|
| - Statement* body = NULL;
|
| -
|
| - // If there are let bindings, then condition and the next statement of the
|
| - // for loop must be parsed in a new scope.
|
| - Scope* inner_scope = scope();
|
| - // TODO(verwaest): Allocate this through a ScopeState as well.
|
| - if (bound_names_are_lexical && bound_names.length() > 0) {
|
| - inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE);
|
| - inner_scope->set_start_position(scanner()->location().beg_pos);
|
| - }
|
| - {
|
| - BlockState block_state(&scope_state_, inner_scope);
|
| -
|
| - if (peek() != Token::SEMICOLON) {
|
| - cond = ParseExpression(true, CHECK_OK);
|
| - }
|
| - Expect(Token::SEMICOLON, CHECK_OK);
|
| -
|
| - if (peek() != Token::RPAREN) {
|
| - Expression* exp = ParseExpression(true, CHECK_OK);
|
| - next = factory()->NewExpressionStatement(exp, exp->position());
|
| - }
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| -
|
| - body = ParseScopedStatement(NULL, true, CHECK_OK);
|
| - }
|
| -
|
| - Statement* result = NULL;
|
| - if (bound_names_are_lexical && bound_names.length() > 0) {
|
| - result = DesugarLexicalBindingsInForStatement(
|
| - inner_scope, parsing_result.descriptor.mode, &bound_names, loop, init,
|
| - cond, next, body, CHECK_OK);
|
| - for_state.set_end_position(scanner()->location().end_pos);
|
| - } else {
|
| - for_state.set_end_position(scanner()->location().end_pos);
|
| - Scope* for_scope = for_state.FinalizedBlockScope();
|
| - if (for_scope) {
|
| - // Rewrite a for statement of the form
|
| - // for (const x = i; c; n) b
|
| - //
|
| - // into
|
| - //
|
| - // {
|
| - // const x = i;
|
| - // for (; c; n) b
|
| - // }
|
| - //
|
| - // or, desugar
|
| - // for (; c; n) b
|
| - // into
|
| - // {
|
| - // for (; c; n) b
|
| - // }
|
| - // just in case b introduces a lexical binding some other way, e.g., if b
|
| - // is a FunctionDeclaration.
|
| - Block* block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition);
|
| - if (init != nullptr) {
|
| - block->statements()->Add(init, zone());
|
| - }
|
| - block->statements()->Add(loop, zone());
|
| - block->set_scope(for_scope);
|
| - loop->Initialize(NULL, cond, next, body);
|
| - result = block;
|
| - } else {
|
| - loop->Initialize(init, cond, next, body);
|
| - result = loop;
|
| - }
|
| - }
|
| - return result;
|
| -}
|
| -
|
| void Parser::ParseArrowFunctionFormalParameters(
|
| ParserFormalParameters* parameters, Expression* expr, int end_pos,
|
| bool* ok) {
|
|
|