1// Copyright 2019 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include 'src/builtins/builtins-promise-gen.h' 6 7namespace promise { 8 9transitioning 10macro RejectPromiseReactionJob( 11 context: Context, 12 promiseOrCapability: JSPromise|PromiseCapability|Undefined, reason: JSAny, 13 reactionType: constexpr PromiseReactionType): JSAny { 14 if constexpr (reactionType == kPromiseReactionReject) { 15 typeswitch (promiseOrCapability) { 16 case (promise: JSPromise): { 17 // For fast native promises we can skip the indirection via the 18 // promiseCapability.[[Reject]] function and run the resolve logic 19 // directly from here. 20 return RejectPromise(promise, reason, False); 21 } 22 case (Undefined): { 23 return Undefined; 24 } 25 case (capability: PromiseCapability): { 26 // In the general case we need to call the (user provided) 27 // promiseCapability.[[Reject]] function. 28 const reject = UnsafeCast<Callable>(capability.reject); 29 return Call(context, reject, Undefined, reason); 30 } 31 } 32 } else { 33 static_assert(reactionType == kPromiseReactionFulfill); 34 // We have to call out to the dedicated PromiseRejectReactionJob 35 // builtin here, instead of just doing the work inline, as otherwise 36 // the catch predictions in the debugger will be wrong, which just 37 // walks the stack and checks for certain builtins. 38 return PromiseRejectReactionJob(reason, Undefined, promiseOrCapability); 39 } 40} 41 42transitioning 43macro FuflfillPromiseReactionJob( 44 context: Context, 45 promiseOrCapability: JSPromise|PromiseCapability|Undefined, result: JSAny, 46 reactionType: constexpr PromiseReactionType): JSAny { 47 typeswitch (promiseOrCapability) { 48 case (promise: JSPromise): { 49 // For fast native promises we can skip the indirection via the 50 // promiseCapability.[[Resolve]] function and run the resolve logic 51 // directly from here. 52 return ResolvePromise(context, promise, result); 53 } 54 case (Undefined): { 55 return Undefined; 56 } 57 case (capability: PromiseCapability): { 58 // In the general case we need to call the (user provided) 59 // promiseCapability.[[Resolve]] function. 60 const resolve = UnsafeCast<Callable>(capability.resolve); 61 try { 62 return Call(context, resolve, Undefined, result); 63 } catch (e) { 64 return RejectPromiseReactionJob( 65 context, promiseOrCapability, e, reactionType); 66 } 67 } 68 } 69} 70 71// https://tc39.es/ecma262/#sec-promisereactionjob 72transitioning 73macro PromiseReactionJob( 74 context: Context, argument: JSAny, handler: Callable|Undefined, 75 promiseOrCapability: JSPromise|PromiseCapability|Undefined, 76 reactionType: constexpr PromiseReactionType): JSAny { 77 if (handler == Undefined) { 78 if constexpr (reactionType == kPromiseReactionFulfill) { 79 return FuflfillPromiseReactionJob( 80 context, promiseOrCapability, argument, reactionType); 81 } else { 82 static_assert(reactionType == kPromiseReactionReject); 83 return RejectPromiseReactionJob( 84 context, promiseOrCapability, argument, reactionType); 85 } 86 } else { 87 try { 88 const result = 89 Call(context, UnsafeCast<Callable>(handler), Undefined, argument); 90 if (promiseOrCapability == Undefined) { 91 // There's no [[Capability]] for this promise reaction job, which 92 // means that this is a specification-internal operation (aka 93 // await) where the result does not matter (see the specification 94 // change in https://github.com/tc39/ecma262/pull/1146 for 95 // details). 96 return Undefined; 97 } else { 98 return FuflfillPromiseReactionJob( 99 context, promiseOrCapability, result, reactionType); 100 } 101 } catch (e) { 102 return RejectPromiseReactionJob( 103 context, promiseOrCapability, e, reactionType); 104 } 105 } 106} 107 108transitioning builtin 109PromiseFulfillReactionJob(implicit context: Context)( 110 value: JSAny, handler: Callable|Undefined, 111 promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny { 112 return PromiseReactionJob( 113 context, value, handler, promiseOrCapability, kPromiseReactionFulfill); 114} 115 116transitioning builtin 117PromiseRejectReactionJob(implicit context: Context)( 118 reason: JSAny, handler: Callable|Undefined, 119 promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny { 120 return PromiseReactionJob( 121 context, reason, handler, promiseOrCapability, kPromiseReactionReject); 122} 123} 124