| Index: src/parsing/parser.cc
|
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
|
| index ed63b543b46cae98d24debebc9334fcfa1f6f6ec..8be0720e88c3b8d573fda77acee71e15fdfea5f0 100644
|
| --- a/src/parsing/parser.cc
|
| +++ b/src/parsing/parser.cc
|
| @@ -2681,7 +2681,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
|
|
| - if (is_generator()) {
|
| + if (is_generator() || is_async_function()) {
|
| return_value = BuildIteratorResult(return_value, true);
|
| }
|
|
|
| @@ -4026,6 +4026,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| ? peek_position() : function_token_pos;
|
|
|
| bool is_generator = IsGeneratorFunction(kind);
|
| + bool is_async = IsAsyncFunction(kind);
|
|
|
| // Anonymous functions were passed either the empty symbol or a null
|
| // handle as the function name. Remember if we were passed a non-empty
|
| @@ -4057,7 +4058,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| scope_->SetScopeName(function_name);
|
| ExpressionClassifier formals_classifier(this, &duplicate_finder);
|
|
|
| - if (is_generator) {
|
| + if (is_generator || is_async) {
|
| // For generators, allocating variables in contexts is currently a win
|
| // because it minimizes the work needed to suspend and resume an
|
| // activation. The machine code produced for generators (by full-codegen)
|
| @@ -4585,6 +4586,41 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
|
| RelocInfo::kNoPosition),
|
| zone());
|
| + } else if (IsAsyncFunction(kind)) {
|
| + ZoneList<Expression*>* arguments =
|
| + new (zone()) ZoneList<Expression*>(2, zone());
|
| + arguments->Add(factory()->NewThisFunction(pos), zone());
|
| + arguments->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
|
| + 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());
|
| +
|
| + ZoneList<Expression*>* async_function_start_args =
|
| + new (zone()) ZoneList<Expression*>(1, zone());
|
| + async_function_start_args->Add(get_proxy, zone());
|
| + CallRuntime* async_function_start = factory()->NewCallRuntime(
|
| + Context::ASYNC_FUNCTION_START_INDEX, async_function_start_args,
|
| + RelocInfo::kNoPosition);
|
| + Yield* yield = factory()->NewAsyncFunctionStart(
|
| + assignment, async_function_start, RelocInfo::kNoPosition);
|
| +
|
| + body->Add(
|
| + factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
|
| + zone());
|
| +
|
| + ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
| +
|
| + Statement* final_return = factory()->NewReturnStatement(
|
| + BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
|
| + body->Add(final_return, zone());
|
| } else {
|
| ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
| }
|
| @@ -4606,6 +4642,39 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| DCHECK_EQ(body, inner_block->statements());
|
| SetLanguageMode(scope_, inner_scope->language_mode());
|
| Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
|
| +
|
| + if (IsAsyncFunction(kind)) {
|
| + // If an exception occurs during parameter initialization, return a
|
| + // rejected promise.
|
| + //
|
| + // try { <init_block> } catch (error) { return Promise.reject(error); }
|
| + Block* try_block = init_block;
|
| + Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
|
| + Variable* catch_variable =
|
| + catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(),
|
| + VAR, kCreatedInitialized, Variable::NORMAL);
|
| + Block* catch_block =
|
| + factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
|
| +
|
| + ZoneList<Expression*>* promise_reject_arguments =
|
| + new (zone()) ZoneList<Expression*>(1, zone());
|
| + promise_reject_arguments->Add(factory()->NewVariableProxy(catch_variable),
|
| + zone());
|
| + CallRuntime* promise_reject = factory()->NewCallRuntime(
|
| + Context::PROMISE_CREATE_REJECTED_INDEX, promise_reject_arguments,
|
| + RelocInfo::kNoPosition);
|
| + ReturnStatement* return_promise_reject =
|
| + factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
|
| + catch_block->statements()->Add(return_promise_reject, zone());
|
| + TryStatement* try_catch_statement = factory()->NewTryCatchStatement(
|
| + try_block, catch_scope, catch_variable, catch_block,
|
| + RelocInfo::kNoPosition);
|
| +
|
| + init_block =
|
| + factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
|
| + init_block->statements()->Add(try_catch_statement, zone());
|
| + }
|
| +
|
| DCHECK_NOT_NULL(init_block);
|
|
|
| inner_scope->set_end_position(scanner()->location().end_pos);
|
| @@ -5396,7 +5465,10 @@ void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
|
| Expression* ParserTraits::RewriteAwaitExpression(Expression* value, int pos) {
|
| // TODO(caitp): Implement AsyncFunctionAwait()
|
| // per tc39.github.io/ecmascript-asyncawait/#abstract-ops-async-function-await
|
| - return value;
|
| + Expression* generator_object = parser_->factory()->NewVariableProxy(
|
| + parser_->function_state_->generator_object_variable());
|
| + value = BuildIteratorResult(value, false);
|
| + return parser_->factory()->NewYield(generator_object, value, pos);
|
| }
|
|
|
| Zone* ParserTraits::zone() const {
|
|
|