| Index: src/parsing/parser.cc
 | 
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
 | 
| index f804a84368bd69da3548103d4bea113c108fd455..76eaf2f4a6f856ea0466313f9b46ed6519e3bfc8 100644
 | 
| --- a/src/parsing/parser.cc
 | 
| +++ b/src/parsing/parser.cc
 | 
| @@ -1110,6 +1110,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
 | 
|          // NewUnresolved references in current scope. Entrer arrow function
 | 
|          // scope for formal parameter parsing.
 | 
|          BlockState block_state(&scope_, scope);
 | 
| +        function_state.set_parse_phase(FunctionParsePhase::FormalParameters);
 | 
|          if (Check(Token::LPAREN)) {
 | 
|            // '(' StrictFormalParameters ')'
 | 
|            ParseFormalParameterList(&formals, &formals_classifier, &ok);
 | 
| @@ -1125,6 +1126,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
 | 
|        }
 | 
|  
 | 
|        if (ok) {
 | 
| +        function_state.set_parse_phase(FunctionParsePhase::FunctionBody);
 | 
|          checkpoint.Restore(&formals.materialized_literals_count);
 | 
|          // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
 | 
|          // not be observable, or else the preparser would have failed.
 | 
| @@ -2720,6 +2722,8 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
 | 
|  
 | 
|    if (is_generator()) {
 | 
|      return_value = BuildIteratorResult(return_value, true);
 | 
| +  } else if (is_async_function()) {
 | 
| +    return_value = EmitPromiseResolve(return_value, return_value->position());
 | 
|    }
 | 
|  
 | 
|    result = factory()->NewReturnStatement(return_value, loc.beg_pos);
 | 
| @@ -3960,6 +3964,66 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
 | 
|    AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
 | 
|  }
 | 
|  
 | 
| +void ParserTraits::ParseAsyncArrowSingleExpressionBody(
 | 
| +    ZoneList<Statement*>* body, bool accept_IN,
 | 
| +    Type::ExpressionClassifier* classifier, int pos, bool* ok) {
 | 
| +  parser_->DesugarAsyncFunctionBody(
 | 
| +      parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
 | 
| +      classifier, kAsyncArrowFunction, FunctionBody::ArrowConcise, accept_IN,
 | 
| +      pos, ok);
 | 
| +}
 | 
| +
 | 
| +void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
 | 
| +                                      Scope* scope, ZoneList<Statement*>* body,
 | 
| +                                      ExpressionClassifier* classifier,
 | 
| +                                      FunctionKind kind, FunctionBody body_type,
 | 
| +                                      bool accept_IN, int pos, bool* ok) {
 | 
| +  scope->ForceContextAllocation();
 | 
| +  // Calling a generator returns a generator object.  That object is
 | 
| +  // stored
 | 
| +  // in a temporary variable, a definition that is used by "yield"
 | 
| +  // expressions. This also marks the FunctionState as a generator.
 | 
| +  Variable* temp =
 | 
| +      scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
 | 
| +  function_state_->set_generator_object_variable(temp);
 | 
| +
 | 
| +  // Create generator, but do not yield.
 | 
| +  Expression* allocation = EmitCreateJSGeneratorObject(pos);
 | 
| +  Expression* assign_yield =
 | 
| +      factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(temp),
 | 
| +                               allocation, RelocInfo::kNoPosition);
 | 
| +
 | 
| +  body->Add(
 | 
| +      factory()->NewExpressionStatement(assign_yield, RelocInfo::kNoPosition),
 | 
| +      zone());
 | 
| +
 | 
| +  Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
 | 
| +
 | 
| +  ZoneList<Statement*>* inner_body = try_block->statements();
 | 
| +
 | 
| +  Expression* return_value = nullptr;
 | 
| +  if (body_type == FunctionBody::Normal) {
 | 
| +    ParseStatementList(inner_body, Token::RBRACE, ok);
 | 
| +    if (!*ok) return;
 | 
| +    return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
 | 
| +  } else {
 | 
| +    return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
 | 
| +    if (!*ok) return;
 | 
| +    ParserTraits::RewriteNonPattern(classifier, ok);
 | 
| +    if (!*ok) return;
 | 
| +  }
 | 
| +
 | 
| +  return_value = EmitPromiseResolve(return_value, return_value->position());
 | 
| +  inner_body->Add(
 | 
| +      factory()->NewReturnStatement(return_value, return_value->position()),
 | 
| +      zone());
 | 
| +
 | 
| +  Block* catch_block = BuildRejectPromiseOnException(try_block);
 | 
| +
 | 
| +  body->Add(catch_block, zone());
 | 
| +
 | 
| +  scope->set_end_position(scanner()->location().end_pos);
 | 
| +}
 | 
|  
 | 
|  DoExpression* Parser::ParseDoExpression(bool* ok) {
 | 
|    // AssignmentExpression ::
 | 
| @@ -4096,6 +4160,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
 | 
|      int start_position = scanner()->location().beg_pos;
 | 
|      scope_->set_start_position(start_position);
 | 
|      ParserFormalParameters formals(scope);
 | 
| +    function_state.set_parse_phase(FunctionParsePhase::FormalParameters);
 | 
|      ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
 | 
|      arity = formals.Arity();
 | 
|      Expect(Token::RPAREN, CHECK_OK);
 | 
| @@ -4104,7 +4169,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
 | 
|      CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
 | 
|                             formals_end_position, CHECK_OK);
 | 
|      Expect(Token::LBRACE, CHECK_OK);
 | 
| -
 | 
| +    function_state.set_parse_phase(FunctionParsePhase::FunctionBody);
 | 
|      // Don't include the rest parameter into the function's formal parameter
 | 
|      // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
 | 
|      // which says whether we need to create an arguments adaptor frame).
 | 
| @@ -4508,6 +4573,54 @@ Block* Parser::BuildParameterInitializationBlock(
 | 
|    return init_block;
 | 
|  }
 | 
|  
 | 
| +Block* Parser::BuildRejectPromiseOnException(Block* block) {
 | 
| +  // try { <block> } catch (error) { return Promise.reject(error); }
 | 
| +  Block* try_block = block;
 | 
| +  Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
 | 
| +  catch_scope->set_is_hidden();
 | 
| +  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);
 | 
| +
 | 
| +  Expression* promise_reject = EmitPromiseReject(
 | 
| +      factory()->NewVariableProxy(catch_variable), 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);
 | 
| +
 | 
| +  block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
 | 
| +  block->statements()->Add(try_catch_statement, zone());
 | 
| +  return block;
 | 
| +}
 | 
| +
 | 
| +Expression* Parser::EmitCreateJSGeneratorObject(int pos) {
 | 
| +  DCHECK_NOT_NULL(function_state_->generator_object_variable());
 | 
| +  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
 | 
| +  args->Add(factory()->NewThisFunction(pos), zone());
 | 
| +  args->Add(ThisExpression(scope_, factory(), RelocInfo::kNoPosition), zone());
 | 
| +  return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
 | 
| +                                   pos);
 | 
| +}
 | 
| +
 | 
| +Expression* Parser::EmitPromiseResolve(Expression* value, int pos) {
 | 
| +  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
 | 
| +  args->Add(value, zone());
 | 
| +  return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
 | 
| +                                   pos);
 | 
| +}
 | 
| +
 | 
| +Expression* Parser::EmitPromiseReject(Expression* value, int pos) {
 | 
| +  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
 | 
| +  args->Add(value, zone());
 | 
| +  return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
 | 
| +                                   pos);
 | 
| +}
 | 
|  
 | 
|  ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|      const AstRawString* function_name, int pos,
 | 
| @@ -4561,14 +4674,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|            factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);
 | 
|  
 | 
|        {
 | 
| -        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);
 | 
| -
 | 
| +        Expression* allocation = EmitCreateJSGeneratorObject(pos);
 | 
|          VariableProxy* init_proxy = factory()->NewVariableProxy(
 | 
|              function_state_->generator_object_variable());
 | 
|          Assignment* assignment = factory()->NewAssignment(
 | 
| @@ -4604,6 +4710,10 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|        body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
 | 
|                                                    RelocInfo::kNoPosition),
 | 
|                  zone());
 | 
| +    } else if (IsAsyncFunction(kind)) {
 | 
| +      const bool accept_IN = true;
 | 
| +      DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
 | 
| +                               FunctionBody::Normal, accept_IN, pos, CHECK_OK);
 | 
|      } else {
 | 
|        ParseStatementList(body, Token::RBRACE, CHECK_OK);
 | 
|      }
 | 
| @@ -4625,6 +4735,11 @@ 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)) {
 | 
| +      init_block = BuildRejectPromiseOnException(init_block);
 | 
| +    }
 | 
| +
 | 
|      DCHECK_NOT_NULL(init_block);
 | 
|  
 | 
|      inner_scope->set_end_position(scanner()->location().end_pos);
 | 
| @@ -5430,9 +5545,26 @@ 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;
 | 
| +  Variable* generator_object_variable =
 | 
| +      parser_->function_state_->generator_object_variable();
 | 
| +
 | 
| +  DCHECK_NOT_NULL(generator_object_variable);
 | 
| +
 | 
| +  Expression* generator_object =
 | 
| +      parser_->factory()->NewVariableProxy(generator_object_variable);
 | 
| +
 | 
| +  ZoneList<Expression*>* async_function_await_args =
 | 
| +      new (zone()) ZoneList<Expression*>(2, zone());
 | 
| +  async_function_await_args->Add(generator_object, zone());
 | 
| +  async_function_await_args->Add(value, zone());
 | 
| +  Expression* async_function_await = parser_->factory()->NewCallRuntime(
 | 
| +      Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args,
 | 
| +      RelocInfo::kNoPosition);
 | 
| +
 | 
| +  generator_object =
 | 
| +      parser_->factory()->NewVariableProxy(generator_object_variable);
 | 
| +  return parser_->factory()->NewYield(generator_object, async_function_await,
 | 
| +                                      pos);
 | 
|  }
 | 
|  
 | 
|  Zone* ParserTraits::zone() const {
 | 
| 
 |