| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index dd9744e7f6314d72f1b3b91ad4b28218da7d1225..5e88b58fefce96eecbd887e82005aee15decc139 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -4655,35 +4655,72 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| {
|
| BlockState block_state(&scope_, inner_scope);
|
|
|
| - // For generators, allocate and yield an iterator on function entry.
|
| if (IsGeneratorFunction(kind)) {
|
| - ZoneList<Expression*>* arguments =
|
| - new(zone()) ZoneList<Expression*>(0, zone());
|
| - CallRuntime* allocation = factory()->NewCallRuntime(
|
| - Runtime::kCreateJSGeneratorObject, arguments, pos);
|
| - VariableProxy* init_proxy = factory()->NewVariableProxy(
|
| - function_state_->generator_object_variable());
|
| - Assignment* assignment = factory()->NewAssignment(
|
| - Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
|
| - VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| - function_state_->generator_object_variable());
|
| - Yield* yield = factory()->NewYield(
|
| - get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
|
| - body->Add(factory()->NewExpressionStatement(
|
| - yield, RelocInfo::kNoPosition), zone());
|
| - }
|
| + // We produce:
|
| + //
|
| + // try { InitialYield; ...body...; FinalYield }
|
| + // finally { %GeneratorClose(generator) }
|
| + //
|
| + // - InitialYield yields the actual generator object.
|
| + // - FinalYield yields {value: foo, done: true} where foo is the
|
| + // completion value of body. (This is needed here in case the body
|
| + // falls through without an explicit return.)
|
| + // - Any return statement inside the body will be converted into a similar
|
| + // FinalYield.
|
| + // - If the generator terminates for whatever reason, we must close it.
|
| + // Hence the finally clause.
|
| +
|
| + Block* try_block =
|
| + factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
|
|
|
| - ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
| + {
|
| + ZoneList<Expression*>* arguments =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| + CallRuntime* allocation = factory()->NewCallRuntime(
|
| + Runtime::kCreateJSGeneratorObject, arguments, pos);
|
| + VariableProxy* init_proxy = factory()->NewVariableProxy(
|
| + function_state_->generator_object_variable());
|
| + Assignment* assignment = factory()->NewAssignment(
|
| + Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
|
| + VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| + function_state_->generator_object_variable());
|
| + Yield* yield = factory()->NewYield(
|
| + get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
|
| + try_block->statements()->Add(
|
| + factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
|
| + zone());
|
| + }
|
| +
|
| + ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
|
|
|
| - if (IsGeneratorFunction(kind)) {
|
| VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| function_state_->generator_object_variable());
|
| Expression* undefined =
|
| factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
|
| Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
|
| RelocInfo::kNoPosition);
|
| - body->Add(factory()->NewExpressionStatement(
|
| - yield, RelocInfo::kNoPosition), zone());
|
| + try_block->statements()->Add(
|
| + factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
|
| + zone());
|
| +
|
| + Block* finally_block =
|
| + factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
|
| + ZoneList<Expression*>* args =
|
| + new (zone()) ZoneList<Expression*>(1, zone());
|
| + VariableProxy* call_proxy = factory()->NewVariableProxy(
|
| + function_state_->generator_object_variable());
|
| + args->Add(call_proxy, zone());
|
| + Expression* call = factory()->NewCallRuntime(
|
| + Runtime::kGeneratorClose, args, RelocInfo::kNoPosition);
|
| + finally_block->statements()->Add(
|
| + factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
|
| + zone());
|
| +
|
| + body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
|
| + RelocInfo::kNoPosition),
|
| + zone());
|
| + } else {
|
| + ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
| }
|
|
|
| if (IsSubclassConstructor(kind)) {
|
|
|