Commit f9733fd3 authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[parser] Reduce for-of desugaring dependency on Scope structure

This removes brittle Scope walking in FinalizeForOfStatement()
by making ParserBase call InitializeForEachStatement() while
in the proper Scope.

Bug: v8:6724
Change-Id: I6e828ccb3a5e4d98633a95a2bfb8d255ad0fc0eb
Reviewed-on: https://chromium-review.googlesource.com/614654Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47376}
parent aac6997b
......@@ -5640,7 +5640,8 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
Expect(Token::RPAREN, CHECK_OK);
StatementT final_loop = impl()->NullStatement();
ExpressionT each_variable = impl()->EmptyExpression();
BlockT body_block = impl()->NullBlock();
{
BlockState block_state(&scope_, inner_block_scope);
scope()->set_start_position(scanner()->location().beg_pos);
......@@ -5651,18 +5652,17 @@ ParserBase<Impl>::ParseForEachStatementWithDeclarations(
StatementT body = ParseStatement(nullptr, CHECK_OK);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
BlockT body_block = impl()->NullBlock();
ExpressionT each_variable = impl()->EmptyExpression();
impl()->DesugarBindingInForEachStatement(for_info, &body_block,
&each_variable, CHECK_OK);
body_block->statements()->Add(body, zone());
final_loop = impl()->InitializeForEachStatement(loop, each_variable,
enumerable, body_block);
scope()->set_end_position(scanner()->location().end_pos);
body_block->set_scope(scope()->FinalizeBlockScope());
}
StatementT final_loop = impl()->InitializeForEachStatement(
loop, each_variable, enumerable, body_block);
init_block = impl()->CreateForEachStatementTDZ(init_block, *for_info, ok);
scope()->set_end_position(scanner()->location().end_pos);
......@@ -5704,8 +5704,8 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
}
Expect(Token::RPAREN, CHECK_OK);
Scope* for_scope = scope();
StatementT body = impl()->NullStatement();
{
BlockState block_state(zone(), &scope_);
scope()->set_start_position(scanner()->location().beg_pos);
......@@ -5713,20 +5713,20 @@ ParserBase<Impl>::ParseForEachStatementWithoutDeclarations(
SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
StatementT body = ParseStatement(nullptr, CHECK_OK);
body = ParseStatement(nullptr, CHECK_OK);
scope()->set_end_position(scanner()->location().end_pos);
StatementT final_loop =
impl()->InitializeForEachStatement(loop, expression, enumerable, body);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
for_scope = for_scope->FinalizeBlockScope();
USE(for_scope);
DCHECK_NULL(for_scope);
Scope* block_scope = scope()->FinalizeBlockScope();
USE(block_scope);
DCHECK_NULL(block_scope);
return final_loop;
}
StatementT final_loop =
impl()->InitializeForEachStatement(loop, expression, enumerable, body);
Scope* for_scope = scope()->FinalizeBlockScope();
USE(for_scope);
DCHECK_NULL(for_scope);
return final_loop;
}
template <typename Impl>
......@@ -5921,8 +5921,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
Expect(Token::RPAREN, CHECK_OK);
StatementT final_loop = impl()->NullStatement();
Scope* for_scope = scope();
StatementT body = impl()->NullStatement();
{
BlockState block_state(&scope_, inner_block_scope);
scope()->set_start_position(scanner()->location().beg_pos);
......@@ -5930,7 +5929,7 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
SourceRange body_range;
SourceRangeScope range_scope(scanner(), &body_range);
StatementT body = ParseStatement(nullptr, CHECK_OK);
body = ParseStatement(nullptr, CHECK_OK);
scope()->set_end_position(scanner()->location().end_pos);
impl()->RecordIterationStatementSourceRange(loop, range_scope.Finalize());
......@@ -5940,33 +5939,30 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
&each_variable, CHECK_OK);
body_block->statements()->Add(body, zone());
body_block->set_scope(scope()->FinalizeBlockScope());
const bool finalize = true;
final_loop = impl()->InitializeForOfStatement(
loop, each_variable, iterable, body_block, finalize,
IteratorType::kAsync, each_keyword_pos);
body = body_block;
} else {
Scope* block_scope = scope()->FinalizeBlockScope();
DCHECK_NULL(block_scope);
USE(block_scope);
}
}
const bool finalize = true;
final_loop = impl()->InitializeForOfStatement(
StatementT final_loop = impl()->InitializeForOfStatement(
loop, each_variable, iterable, body, finalize, IteratorType::kAsync,
each_keyword_pos);
for_scope = for_scope->FinalizeBlockScope();
if (!has_declarations) {
Scope* for_scope = scope()->FinalizeBlockScope();
DCHECK_NULL(for_scope);
USE(for_scope);
Scope* block_scope = scope()->FinalizeBlockScope();
DCHECK_NULL(block_scope);
USE(block_scope);
return final_loop;
}
}
DCHECK(has_declarations);
BlockT init_block =
impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok);
for_scope->set_end_position(scanner()->location().end_pos);
for_scope = for_scope->FinalizeBlockScope();
scope()->set_end_position(scanner()->location().end_pos);
Scope* for_scope = scope()->FinalizeBlockScope();
// Parsed for-in loop w/ variable declarations.
if (!impl()->IsNullStatement(init_block)) {
init_block->statements()->Add(final_loop, zone());
......
......@@ -4981,12 +4981,7 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop,
Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos);
try_block->statements()->Add(loop, zone());
// The scope in which the parser creates this loop.
Scope* loop_scope = scope()->outer_scope();
DCHECK_EQ(loop_scope->scope_type(), BLOCK_SCOPE);
DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE);
FinalizeIteratorUse(loop_scope, var_completion, closing_condition,
FinalizeIteratorUse(scope(), var_completion, closing_condition,
loop->iterator(), try_block, final_loop, type);
}
......
......@@ -3538,6 +3538,7 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module,
var = scope->Lookup(var_name);
}
CHECK_NOT_NULL(var);
CHECK(var->is_used());
STATIC_ASSERT(true == i::kMaybeAssigned);
CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
......@@ -3626,41 +3627,41 @@ TEST(MaybeAssignedInsideLoop) {
{1, "for (j of x) { [foo] = [j] }", top},
{1, "for (j of x) { var foo = j }", top},
{1, "for (j of x) { var [foo] = [j] }", top},
{0, "for (j of x) { let foo = j }", {0}},
{0, "for (j of x) { let [foo] = [j] }", {0}},
{0, "for (j of x) { const foo = j }", {0}},
{0, "for (j of x) { const [foo] = [j] }", {0}},
{0, "for (j of x) { function foo() {return j} }", {0}},
{0, "for (j of x) { let foo = j }", {2}},
{0, "for (j of x) { let [foo] = [j] }", {2}},
{0, "for (j of x) { const foo = j }", {2}},
{0, "for (j of x) { const [foo] = [j] }", {2}},
{0, "for (j of x) { function foo() {return j} }", {2}},
{1, "for ({j} of x) { foo = j }", top},
{1, "for ({j} of x) { [foo] = [j] }", top},
{1, "for ({j} of x) { var foo = j }", top},
{1, "for ({j} of x) { var [foo] = [j] }", top},
{0, "for ({j} of x) { let foo = j }", {0}},
{0, "for ({j} of x) { let [foo] = [j] }", {0}},
{0, "for ({j} of x) { const foo = j }", {0}},
{0, "for ({j} of x) { const [foo] = [j] }", {0}},
{0, "for ({j} of x) { function foo() {return j} }", {0}},
{0, "for ({j} of x) { let foo = j }", {2}},
{0, "for ({j} of x) { let [foo] = [j] }", {2}},
{0, "for ({j} of x) { const foo = j }", {2}},
{0, "for ({j} of x) { const [foo] = [j] }", {2}},
{0, "for ({j} of x) { function foo() {return j} }", {2}},
{1, "for (var j of x) { foo = j }", top},
{1, "for (var j of x) { [foo] = [j] }", top},
{1, "for (var j of x) { var foo = j }", top},
{1, "for (var j of x) { var [foo] = [j] }", top},
{0, "for (var j of x) { let foo = j }", {0}},
{0, "for (var j of x) { let [foo] = [j] }", {0}},
{0, "for (var j of x) { const foo = j }", {0}},
{0, "for (var j of x) { const [foo] = [j] }", {0}},
{0, "for (var j of x) { function foo() {return j} }", {0}},
{0, "for (var j of x) { let foo = j }", {2}},
{0, "for (var j of x) { let [foo] = [j] }", {2}},
{0, "for (var j of x) { const foo = j }", {2}},
{0, "for (var j of x) { const [foo] = [j] }", {2}},
{0, "for (var j of x) { function foo() {return j} }", {2}},
{1, "for (var {j} of x) { foo = j }", top},
{1, "for (var {j} of x) { [foo] = [j] }", top},
{1, "for (var {j} of x) { var foo = j }", top},
{1, "for (var {j} of x) { var [foo] = [j] }", top},
{0, "for (var {j} of x) { let foo = j }", {0}},
{0, "for (var {j} of x) { let [foo] = [j] }", {0}},
{0, "for (var {j} of x) { const foo = j }", {0}},
{0, "for (var {j} of x) { const [foo] = [j] }", {0}},
{0, "for (var {j} of x) { function foo() {return j} }", {0}},
{0, "for (var {j} of x) { let foo = j }", {2}},
{0, "for (var {j} of x) { let [foo] = [j] }", {2}},
{0, "for (var {j} of x) { const foo = j }", {2}},
{0, "for (var {j} of x) { const [foo] = [j] }", {2}},
{0, "for (var {j} of x) { function foo() {return j} }", {2}},
{1, "for (let j of x) { foo = j }", top},
{1, "for (let j of x) { [foo] = [j] }", top},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment