| Index: src/parsing/parser.cc
 | 
| diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
 | 
| index 1d19e42c9e7ccb6810fdda788cd1d17d9dbc3232..91ee4acb17580e56d3bc218b9f4ccc3cce0a2c5b 100644
 | 
| --- a/src/parsing/parser.cc
 | 
| +++ b/src/parsing/parser.cc
 | 
| @@ -2786,7 +2786,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
 | 
|    if (is_generator()) {
 | 
|      return_value = BuildIteratorResult(return_value, true);
 | 
|    } else if (is_async_function()) {
 | 
| -    return_value = BuildPromiseResolve(return_value, return_value->position());
 | 
| +    return_value = BuildResolvePromise(return_value, return_value->position());
 | 
|    }
 | 
|  
 | 
|    result = factory()->NewReturnStatement(return_value, loc.beg_pos);
 | 
| @@ -4130,12 +4130,11 @@ void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
 | 
|                                        FunctionKind kind, FunctionBody body_type,
 | 
|                                        bool accept_IN, int pos, bool* ok) {
 | 
|    // function async_function() {
 | 
| -  //   try {
 | 
| +  //   BuildRejectPromiseOnException({
 | 
|    //     .generator_object = %CreateGeneratorObject();
 | 
|    //     ... function body ...
 | 
| -  //   } catch (e) {
 | 
| -  //     return Promise.reject(e);
 | 
| -  //   }
 | 
| +  //     return %ResolvePromise(.promise, expr), .promise;
 | 
| +  //   })
 | 
|    // }
 | 
|    scope->ForceContextAllocation();
 | 
|    Variable* temp =
 | 
| @@ -4163,11 +4162,12 @@ void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
 | 
|      ParserTraits::RewriteNonPattern(classifier, CHECK_OK_VOID);
 | 
|    }
 | 
|  
 | 
| -  return_value = BuildPromiseResolve(return_value, return_value->position());
 | 
| +  return_value = BuildResolvePromise(return_value, return_value->position());
 | 
|    inner_body->Add(
 | 
|        factory()->NewReturnStatement(return_value, return_value->position()),
 | 
|        zone());
 | 
| -  body->Add(BuildRejectPromiseOnException(try_block), zone());
 | 
| +  Statement* block = BuildRejectPromiseOnException(try_block, CHECK_OK_VOID);
 | 
| +  body->Add(block, zone());
 | 
|    scope->set_end_position(scanner()->location().end_pos);
 | 
|  }
 | 
|  
 | 
| @@ -4734,9 +4734,73 @@ Block* Parser::BuildParameterInitializationBlock(
 | 
|    return init_block;
 | 
|  }
 | 
|  
 | 
| -Block* Parser::BuildRejectPromiseOnException(Block* block) {
 | 
| -  // try { <block> } catch (error) { return Promise.reject(error); }
 | 
| -  Block* try_block = block;
 | 
| +Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
 | 
| +  // var .promise = %CreatePromise();
 | 
| +  // var .debug_is_active = %_DebugIsActive() !== 0;
 | 
| +  // try {
 | 
| +  //   if (.debug_is_active) %DebugPushPromise(.promise);
 | 
| +  //   <block>
 | 
| +  // } catch (.catch) {
 | 
| +  //   %RejectPromise(.promise, .catch);
 | 
| +  //   return .promise;
 | 
| +  // } finally {
 | 
| +  //   if (.debug_is_active) %DebugPopPromise();
 | 
| +  // }
 | 
| +  Block* block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
 | 
| +
 | 
| +  // var .promise = %CreatePromise();
 | 
| +  Statement* set_promise;
 | 
| +  {
 | 
| +    DeclareVariable(ast_value_factory()->dot_promise_string(), VAR,
 | 
| +                    kNoSourcePosition, CHECK_OK);
 | 
| +    Expression* create_promise = factory()->NewCallRuntime(
 | 
| +        Context::PROMISE_CREATE_INDEX,
 | 
| +        new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
 | 
| +    Assignment* assign_promise = factory()->NewAssignment(
 | 
| +        Token::INIT, BuildDotPromise(), create_promise, kNoSourcePosition);
 | 
| +    set_promise =
 | 
| +        factory()->NewExpressionStatement(assign_promise, kNoSourcePosition);
 | 
| +  }
 | 
| +  block->statements()->Add(set_promise, zone());
 | 
| +
 | 
| +  // var .debug_is_active = %_DebugIsActive() != 0;
 | 
| +  Statement* set_debug_is_active;
 | 
| +  {
 | 
| +    DeclareVariable(ast_value_factory()->dot_debug_is_active_string(), VAR,
 | 
| +                    kNoSourcePosition, CHECK_OK);
 | 
| +    Expression* debug_is_active_num = factory()->NewCallRuntime(
 | 
| +        Runtime::kInlineDebugIsActive,
 | 
| +        new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition);
 | 
| +    Expression* debug_is_active = factory()->NewCompareOperation(
 | 
| +        Token::EQ_STRICT, debug_is_active_num,
 | 
| +        factory()->NewSmiLiteral(0, kNoSourcePosition), kNoSourcePosition);
 | 
| +    debug_is_active = factory()->NewUnaryOperation(Token::NOT, debug_is_active,
 | 
| +                                                   kNoSourcePosition);
 | 
| +    Assignment* assign_debug_is_active = factory()->NewAssignment(
 | 
| +        Token::INIT, BuildDebugIsActive(), debug_is_active, kNoSourcePosition);
 | 
| +    set_debug_is_active = factory()->NewExpressionStatement(
 | 
| +        assign_debug_is_active, kNoSourcePosition);
 | 
| +  }
 | 
| +  block->statements()->Add(set_debug_is_active, zone());
 | 
| +
 | 
| +  Block* try_block = factory()->NewBlock(nullptr, 2, true, kNoSourcePosition);
 | 
| +  //   if (.debug_is_active) %DebugPushPromise(.promise);
 | 
| +  Statement* conditionally_debug_push_promise;
 | 
| +  {
 | 
| +    ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
 | 
| +    args->Add(BuildDotPromise(), zone());
 | 
| +    Expression* call_push_promise = factory()->NewCallRuntime(
 | 
| +        Runtime::kDebugPushPromise, args, kNoSourcePosition);
 | 
| +    Statement* debug_push_promise =
 | 
| +        factory()->NewExpressionStatement(call_push_promise, kNoSourcePosition);
 | 
| +    conditionally_debug_push_promise = factory()->NewIfStatement(
 | 
| +        BuildDebugIsActive(), debug_push_promise,
 | 
| +        factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
 | 
| +  }
 | 
| +  try_block->statements()->Add(conditionally_debug_push_promise, zone());
 | 
| +  try_block->statements()->Add(inner_block, zone());
 | 
| +
 | 
| +  // catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
 | 
|    Scope* catch_scope = NewScope(CATCH_SCOPE);
 | 
|    catch_scope->set_is_hidden();
 | 
|    Variable* catch_variable =
 | 
| @@ -4744,17 +4808,39 @@ Block* Parser::BuildRejectPromiseOnException(Block* block) {
 | 
|                                  kCreatedInitialized, Variable::NORMAL);
 | 
|    Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
 | 
|  
 | 
| -  Expression* promise_reject = BuildPromiseReject(
 | 
| +  Expression* promise_reject = BuildRejectPromise(
 | 
|        factory()->NewVariableProxy(catch_variable), kNoSourcePosition);
 | 
| -
 | 
|    ReturnStatement* return_promise_reject =
 | 
|        factory()->NewReturnStatement(promise_reject, kNoSourcePosition);
 | 
|    catch_block->statements()->Add(return_promise_reject, zone());
 | 
| +
 | 
|    TryStatement* try_catch_statement = factory()->NewTryCatchStatement(
 | 
|        try_block, catch_scope, catch_variable, catch_block, kNoSourcePosition);
 | 
|  
 | 
| -  block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
 | 
| -  block->statements()->Add(try_catch_statement, zone());
 | 
| +  // There is no TryCatchFinally node, so wrap it in an outer try/finally
 | 
| +  Block* outer_try_block =
 | 
| +      factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
 | 
| +  outer_try_block->statements()->Add(try_catch_statement, zone());
 | 
| +
 | 
| +  // finally { if (.debug_is_active) %DebugPopPromise(); }
 | 
| +  Block* finally_block =
 | 
| +      factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
 | 
| +  {
 | 
| +    ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone());
 | 
| +    Expression* call_pop_promise = factory()->NewCallRuntime(
 | 
| +        Runtime::kDebugPopPromise, args, kNoSourcePosition);
 | 
| +    Statement* debug_pop_promise =
 | 
| +        factory()->NewExpressionStatement(call_pop_promise, kNoSourcePosition);
 | 
| +    Statement* conditionally_debug_pop_promise = factory()->NewIfStatement(
 | 
| +        BuildDebugIsActive(), debug_pop_promise,
 | 
| +        factory()->NewEmptyStatement(kNoSourcePosition), kNoSourcePosition);
 | 
| +    finally_block->statements()->Add(conditionally_debug_pop_promise, zone());
 | 
| +  }
 | 
| +
 | 
| +  Statement* try_finally_statement = factory()->NewTryFinallyStatement(
 | 
| +      outer_try_block, finally_block, kNoSourcePosition);
 | 
| +
 | 
| +  block->statements()->Add(try_finally_statement, zone());
 | 
|    return block;
 | 
|  }
 | 
|  
 | 
| @@ -4770,18 +4856,37 @@ Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
 | 
|                                     pos);
 | 
|  }
 | 
|  
 | 
| -Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
 | 
| -  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
 | 
| +Expression* Parser::BuildResolvePromise(Expression* value, int pos) {
 | 
| +  // %ResolvePromise(.promise, value), .promise
 | 
| +  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
 | 
| +  args->Add(BuildDotPromise(), zone());
 | 
|    args->Add(value, zone());
 | 
| -  return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
 | 
| -                                   pos);
 | 
| +  Expression* call_runtime =
 | 
| +      factory()->NewCallRuntime(Context::PROMISE_RESOLVE_INDEX, args, pos);
 | 
| +  return factory()->NewBinaryOperation(Token::COMMA, call_runtime,
 | 
| +                                       BuildDotPromise(), pos);
 | 
| +}
 | 
| +
 | 
| +Expression* Parser::BuildRejectPromise(Expression* value, int pos) {
 | 
| +  // %RejectPromise(.promise, value, true), .promise
 | 
| +  // The 'true' flag disables the additional debug event for the rejection
 | 
| +  // since a debug event already happened for the exception that got us here.
 | 
| +  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone());
 | 
| +  args->Add(BuildDotPromise(), zone());
 | 
| +  args->Add(value, zone());
 | 
| +  args->Add(factory()->NewBooleanLiteral(true, pos), zone());
 | 
| +  Expression* call_runtime =
 | 
| +      factory()->NewCallRuntime(Context::PROMISE_REJECT_INDEX, args, pos);
 | 
| +  return factory()->NewBinaryOperation(Token::COMMA, call_runtime,
 | 
| +                                       BuildDotPromise(), pos);
 | 
|  }
 | 
|  
 | 
| -Expression* Parser::BuildPromiseReject(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);
 | 
| +VariableProxy* Parser::BuildDotPromise() {
 | 
| +  return NewUnresolved(ast_value_factory()->dot_promise_string(), VAR);
 | 
| +}
 | 
| +
 | 
| +VariableProxy* Parser::BuildDebugIsActive() {
 | 
| +  return NewUnresolved(ast_value_factory()->dot_debug_is_active_string(), VAR);
 | 
|  }
 | 
|  
 | 
|  ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
| @@ -4907,8 +5012,9 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
 | 
|                                             CHECK_OK);
 | 
|      }
 | 
|  
 | 
| +    // TODO(littledan): Merge the two rejection blocks into one
 | 
|      if (IsAsyncFunction(kind)) {
 | 
| -      init_block = BuildRejectPromiseOnException(init_block);
 | 
| +      init_block = BuildRejectPromiseOnException(init_block, CHECK_OK);
 | 
|      }
 | 
|  
 | 
|      DCHECK_NOT_NULL(init_block);
 | 
| 
 |