| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 110f614e1b7f80afe660e910b48be74c488b59ae..7203c55d5a301ca2c2a139b3d6380fcd6d249172 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -1311,6 +1311,8 @@ Isolate::CatchType Isolate::PredictExceptionCatcher() {
|
| JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
|
| HandlerTable::CatchPrediction prediction = PredictException(js_frame);
|
| if (prediction == HandlerTable::DESUGARING) return CAUGHT_BY_DESUGARING;
|
| + if (prediction == HandlerTable::ASYNC_AWAIT) return CAUGHT_BY_ASYNC_AWAIT;
|
| + if (prediction == HandlerTable::PROMISE) return CAUGHT_BY_PROMISE;
|
| if (prediction != HandlerTable::UNCAUGHT) return CAUGHT_BY_JAVASCRIPT;
|
| }
|
|
|
| @@ -1701,6 +1703,14 @@ void Isolate::PopPromise() {
|
| global_handles()->Destroy(global_promise.location());
|
| }
|
|
|
| +bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<JSObject> promise) {
|
| + Handle<JSFunction> fun = promise_has_user_defined_reject_handler();
|
| + Handle<Object> has_reject_handler;
|
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE(this, has_reject_handler,
|
| + Execution::Call(this, fun, promise, 0, NULL),
|
| + false);
|
| + return has_reject_handler->IsTrue(this);
|
| +}
|
|
|
| Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
|
| Handle<Object> undefined = factory()->undefined_value();
|
| @@ -1720,6 +1730,47 @@ Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
|
| return undefined;
|
| case HandlerTable::PROMISE:
|
| return tltop->promise_on_stack_->promise();
|
| + case HandlerTable::ASYNC_AWAIT: {
|
| + // If in an async/await, pop up successive async/await stack frames
|
| + // until an asynchronous one with dependents is found, or a non-async
|
| + // stack frame is encountered, in order to handle the synchronous
|
| + // async/await catch prediction case: assume that async function calls
|
| + // are awaited.
|
| + PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
|
| + for (it.Advance(); !it.done(); it.Advance()) {
|
| + if (PromiseHasUserDefinedRejectHandler(promise_on_stack->promise())) {
|
| + break;
|
| + }
|
| + JavaScriptFrame* frame = it.frame();
|
| + if (!frame->function()->shared()->is_async()) {
|
| + // Keep searching up the stack until an async function stack frame
|
| + // is found, heuristically assuming that that will ultimately await
|
| + // whatever is going on here.
|
| + continue;
|
| + }
|
| + PromiseOnStack* next_promise_on_stack = promise_on_stack->prev();
|
| + if (next_promise_on_stack == nullptr) break;
|
| + switch (PredictException(it.frame())) {
|
| + case HandlerTable::CAUGHT:
|
| + case HandlerTable::DESUGARING: {
|
| + // Mark the inner promise as caught in the "synchronous case" so
|
| + // that Debug::OnException will see.
|
| + Handle<Symbol> key = factory()->promise_handled_hint_symbol();
|
| + JSObject::SetProperty(promise_on_stack->promise(), key, key,
|
| + STRICT)
|
| + .Assert();
|
| + return promise_on_stack->promise();
|
| + }
|
| + case HandlerTable::ASYNC_AWAIT:
|
| + promise_on_stack = next_promise_on_stack;
|
| + continue;
|
| + case HandlerTable::PROMISE:
|
| + case HandlerTable::UNCAUGHT:
|
| + UNREACHABLE();
|
| + }
|
| + }
|
| + return promise_on_stack->promise();
|
| + }
|
| }
|
| }
|
| return undefined;
|
|
|