| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index b9dcbfd84d11baf66e5b9f51e3f822510e0ed1d1..fea0d0a8a2d0fec5f055f64cb61ab81ba408960d 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -3555,11 +3555,14 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| //
|
| // into
|
| //
|
| - // <let x' be a temporary variable>
|
| - // for (x' in/of e) {
|
| - // let/const/var x;
|
| - // x = x';
|
| - // b;
|
| + // {
|
| + // <let x' be a temporary variable>
|
| + // for (x' in/of e) {
|
| + // let/const/var x;
|
| + // x = x';
|
| + // b;
|
| + // }
|
| + // let x; // for TDZ
|
| // }
|
|
|
| Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
| @@ -3568,12 +3571,14 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| factory()->NewForEachStatement(mode, labels, stmt_pos);
|
| Target target(&this->target_stack_, loop);
|
|
|
| - // 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);
|
|
|
| + Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
|
| + body_scope->set_start_position(scanner()->location().beg_pos);
|
| + scope_ = body_scope;
|
| +
|
| Statement* body = ParseSubStatement(NULL, CHECK_OK);
|
|
|
| Block* body_block =
|
| @@ -3601,17 +3606,46 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
| VariableProxy* temp_proxy =
|
| factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
|
| InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
|
| + scope_ = for_scope;
|
| + body_scope->set_end_position(scanner()->location().end_pos);
|
| + body_scope = body_scope->FinalizeBlockScope();
|
| + if (body_scope != nullptr) {
|
| + body_block->set_scope(body_scope);
|
| + }
|
| +
|
| + // Create a TDZ for any lexically-bound names.
|
| + if (is_strict(language_mode()) &&
|
| + IsLexicalVariableMode(parsing_result.descriptor.mode)) {
|
| + DCHECK_NULL(init_block);
|
| +
|
| + init_block =
|
| + factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
|
| +
|
| + for (int i = 0; i < lexical_bindings.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.
|
| + VariableProxy* tdz_proxy = NewUnresolved(lexical_bindings[i], LET);
|
| + Declaration* tdz_decl = factory()->NewVariableDeclaration(
|
| + tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
|
| + Variable* tdz_var = Declare(tdz_decl, DeclarationDescriptor::NORMAL,
|
| + true, CHECK_OK);
|
| + tdz_var->set_initializer_position(position());
|
| + }
|
| + }
|
| +
|
| scope_ = saved_scope;
|
| for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| - 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());
|
| + if (for_scope != nullptr) {
|
| + init_block->set_scope(for_scope);
|
| + }
|
| return init_block;
|
| } else {
|
| + DCHECK_NULL(for_scope);
|
| return loop;
|
| }
|
| } else {
|
|
|