| Index: src/isolate.cc
|
| diff --git a/src/isolate.cc b/src/isolate.cc
|
| index 1b96583cb093cd44eb2022945e59b2a6bc185322..d6b41ec2b125182ad2d00ee4014306eca1574dd8 100644
|
| --- a/src/isolate.cc
|
| +++ b/src/isolate.cc
|
| @@ -1703,6 +1703,19 @@ void Isolate::PopPromise() {
|
| global_handles()->Destroy(global_promise.location());
|
| }
|
|
|
| +bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) {
|
| + Handle<JSFunction> fun = promise_has_user_defined_reject_handler();
|
| + Handle<Object> has_reject_handler;
|
| + if (Execution::TryCall(this, fun, promise, 0, NULL)
|
| + .ToHandle(&has_reject_handler)) {
|
| + return has_reject_handler->IsTrue(this);
|
| + }
|
| + // If an exception is thrown in the course of execution of this built-in
|
| + // function, it indicates either a bug, or a synthetic uncatchable
|
| + // exception in the shutdown path. In either case, it's OK to predict either
|
| + // way in DevTools.
|
| + return false;
|
| +}
|
|
|
| Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
|
| Handle<Object> undefined = factory()->undefined_value();
|
| @@ -1713,19 +1726,46 @@ Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
|
| if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) {
|
| return undefined;
|
| }
|
| + Handle<Object> retval = undefined;
|
| + PromiseOnStack* promise_on_stack = tltop->promise_on_stack_;
|
| for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
|
| switch (PredictException(it.frame())) {
|
| case HandlerTable::UNCAUGHT:
|
| - case HandlerTable::ASYNC_AWAIT:
|
| - break;
|
| + continue;
|
| case HandlerTable::CAUGHT:
|
| case HandlerTable::DESUGARING:
|
| - return undefined;
|
| + if (retval->IsJSObject()) {
|
| + // Caught the result of an inner async/await invocation.
|
| + // Mark the inner promise as caught in the "synchronous case" so
|
| + // that Debug::OnException will see. In the synchronous case,
|
| + // namely in the code in an async function before the first
|
| + // await, the function which has this exception event has not yet
|
| + // returned, so the generated Promise has not yet been marked
|
| + // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol.
|
| + Handle<Symbol> key = factory()->promise_handled_hint_symbol();
|
| + JSObject::SetProperty(Handle<JSObject>::cast(retval), key,
|
| + factory()->true_value(), STRICT)
|
| + .Assert();
|
| + }
|
| + return retval;
|
| case HandlerTable::PROMISE:
|
| - return tltop->promise_on_stack_->promise();
|
| + return promise_on_stack->promise();
|
| + case HandlerTable::ASYNC_AWAIT: {
|
| + // If in the initial portion of async/await, continue the loop to 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.
|
| + retval = promise_on_stack->promise();
|
| + if (PromiseHasUserDefinedRejectHandler(retval)) {
|
| + return retval;
|
| + }
|
| + promise_on_stack = promise_on_stack->prev();
|
| + continue;
|
| + }
|
| }
|
| }
|
| - return undefined;
|
| + return retval;
|
| }
|
|
|
|
|
|
|