| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index 7e4086283f91e0873a92d1a21e2762f2c7bf4858..cd34d35423e66085ffa64ccd1cd826d4fdeeee63 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -4549,21 +4549,46 @@ Expression* Parser::ExpressionListToExpression(ZoneList<Expression*>* args) {
|
|
|
| Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
|
| // yield do {
|
| + // promise_tmp = .promise;
|
| // tmp = <operand>;
|
| - // tmp = %AsyncFunctionAwait(.generator_object, tmp);
|
| + // %AsyncFunctionAwait(.generator_object, tmp);
|
| + // promise_tmp
|
| // }
|
| + // The value of the expression is returned to the caller of the async
|
| + // function for the first yield statement; for this, .promise is the
|
| + // appropriate return value, being a Promise that will be fulfilled or
|
| + // rejected with the appropriate value by the desugaring. Subsequent yield
|
| + // occurrences will return to the AsyncFunctionNext call within the
|
| + // implemementation of the intermediate throwaway Promise's then handler.
|
| + // This handler has nothing useful to do with the value, as the Promise is
|
| + // ignored. If we yielded the value of the throwawayPromise that
|
| + // AsyncFunctionAwait creates as an intermediate, it would create a memory
|
| + // leak; we must return .promise instead;
|
| + // The operand needs to be evaluated on a separate statement in order to get
|
| + // a break location, and the .promise needs to be read earlier so that it
|
| + // doesn't insert a false location.
|
| + // TODO(littledan): investigate why this ordering is needed in more detail.
|
| Variable* generator_object_variable =
|
| function_state_->generator_object_variable();
|
|
|
| // If generator_object_variable is null,
|
| + // TODO(littledan): Is this necessary?
|
| if (!generator_object_variable) return value;
|
|
|
| const int nopos = kNoSourcePosition;
|
|
|
| - Variable* temp_var = NewTemporary(ast_value_factory()->empty_string());
|
| - Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
|
| + Block* do_block = factory()->NewBlock(nullptr, 3, false, nopos);
|
| +
|
| + Variable* promise_temp_var =
|
| + NewTemporary(ast_value_factory()->empty_string());
|
| + Expression* promise_assignment = factory()->NewAssignment(
|
| + Token::ASSIGN, factory()->NewVariableProxy(promise_temp_var),
|
| + BuildDotPromise(), nopos);
|
| + do_block->statements()->Add(
|
| + factory()->NewExpressionStatement(promise_assignment, nopos), zone());
|
|
|
| // Wrap value evaluation to provide a break location.
|
| + Variable* temp_var = NewTemporary(ast_value_factory()->empty_string());
|
| Expression* value_assignment = factory()->NewAssignment(
|
| Token::ASSIGN, factory()->NewVariableProxy(temp_var), value, nopos);
|
| do_block->statements()->Add(
|
| @@ -4583,14 +4608,13 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
|
| Expression* async_function_await =
|
| factory()->NewCallRuntime(Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX,
|
| async_function_await_args, nopos);
|
| + do_block->statements()->Add(
|
| + factory()->NewExpressionStatement(async_function_await, await_pos),
|
| + zone());
|
|
|
| // Wrap await to provide a break location between value evaluation and yield.
|
| - Expression* await_assignment = factory()->NewAssignment(
|
| - Token::ASSIGN, factory()->NewVariableProxy(temp_var),
|
| - async_function_await, nopos);
|
| - do_block->statements()->Add(
|
| - factory()->NewExpressionStatement(await_assignment, await_pos), zone());
|
| - Expression* do_expr = factory()->NewDoExpression(do_block, temp_var, nopos);
|
| + Expression* do_expr =
|
| + factory()->NewDoExpression(do_block, promise_temp_var, nopos);
|
|
|
| generator_object = factory()->NewVariableProxy(generator_object_variable);
|
| return factory()->NewYield(generator_object, do_expr, nopos,
|
|
|