| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include 'src/builtins/builtins-promise-gen.h' |
| |
| namespace promise { |
| |
| transitioning |
| macro RejectPromiseReactionJob( |
| context: Context, |
| promiseOrCapability: JSPromise|PromiseCapability|Undefined, reason: JSAny, |
| reactionType: constexpr PromiseReactionType): JSAny { |
| if constexpr (reactionType == kPromiseReactionReject) { |
| typeswitch (promiseOrCapability) { |
| case (promise: JSPromise): { |
| // For fast native promises we can skip the indirection via the |
| // promiseCapability.[[Reject]] function and run the resolve logic |
| // directly from here. |
| return RejectPromise(promise, reason, False); |
| } |
| case (Undefined): { |
| return Undefined; |
| } |
| case (capability: PromiseCapability): { |
| // In the general case we need to call the (user provided) |
| // promiseCapability.[[Reject]] function. |
| const reject = UnsafeCast<Callable>(capability.reject); |
| return Call(context, reject, Undefined, reason); |
| } |
| } |
| } else { |
| static_assert(reactionType == kPromiseReactionFulfill); |
| // We have to call out to the dedicated PromiseRejectReactionJob |
| // builtin here, instead of just doing the work inline, as otherwise |
| // the catch predictions in the debugger will be wrong, which just |
| // walks the stack and checks for certain builtins. |
| return PromiseRejectReactionJob(reason, Undefined, promiseOrCapability); |
| } |
| } |
| |
| transitioning |
| macro FuflfillPromiseReactionJob( |
| context: Context, |
| promiseOrCapability: JSPromise|PromiseCapability|Undefined, result: JSAny, |
| reactionType: constexpr PromiseReactionType): JSAny { |
| typeswitch (promiseOrCapability) { |
| case (promise: JSPromise): { |
| // For fast native promises we can skip the indirection via the |
| // promiseCapability.[[Resolve]] function and run the resolve logic |
| // directly from here. |
| return ResolvePromise(context, promise, result); |
| } |
| case (Undefined): { |
| return Undefined; |
| } |
| case (capability: PromiseCapability): { |
| // In the general case we need to call the (user provided) |
| // promiseCapability.[[Resolve]] function. |
| const resolve = UnsafeCast<Callable>(capability.resolve); |
| try { |
| return Call(context, resolve, Undefined, result); |
| } catch (e) { |
| return RejectPromiseReactionJob( |
| context, promiseOrCapability, e, reactionType); |
| } |
| } |
| } |
| } |
| |
| // https://tc39.es/ecma262/#sec-promisereactionjob |
| transitioning |
| macro PromiseReactionJob( |
| context: Context, argument: JSAny, handler: Callable|Undefined, |
| promiseOrCapability: JSPromise|PromiseCapability|Undefined, |
| reactionType: constexpr PromiseReactionType): JSAny { |
| if (handler == Undefined) { |
| if constexpr (reactionType == kPromiseReactionFulfill) { |
| return FuflfillPromiseReactionJob( |
| context, promiseOrCapability, argument, reactionType); |
| } else { |
| static_assert(reactionType == kPromiseReactionReject); |
| return RejectPromiseReactionJob( |
| context, promiseOrCapability, argument, reactionType); |
| } |
| } else { |
| try { |
| const result = |
| Call(context, UnsafeCast<Callable>(handler), Undefined, argument); |
| if (promiseOrCapability == Undefined) { |
| // There's no [[Capability]] for this promise reaction job, which |
| // means that this is a specification-internal operation (aka |
| // await) where the result does not matter (see the specification |
| // change in https://github.com/tc39/ecma262/pull/1146 for |
| // details). |
| return Undefined; |
| } else { |
| return FuflfillPromiseReactionJob( |
| context, promiseOrCapability, result, reactionType); |
| } |
| } catch (e) { |
| return RejectPromiseReactionJob( |
| context, promiseOrCapability, e, reactionType); |
| } |
| } |
| } |
| |
| transitioning builtin |
| PromiseFulfillReactionJob(implicit context: Context)( |
| value: JSAny, handler: Callable|Undefined, |
| promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny { |
| return PromiseReactionJob( |
| context, value, handler, promiseOrCapability, kPromiseReactionFulfill); |
| } |
| |
| transitioning builtin |
| PromiseRejectReactionJob(implicit context: Context)( |
| reason: JSAny, handler: Callable|Undefined, |
| promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny { |
| return PromiseReactionJob( |
| context, reason, handler, promiseOrCapability, kPromiseReactionReject); |
| } |
| } |