diff options
Diffstat (limited to 'deps/v8/src/builtins/promise-all.tq')
-rw-r--r-- | deps/v8/src/builtins/promise-all.tq | 659 |
1 files changed, 326 insertions, 333 deletions
diff --git a/deps/v8/src/builtins/promise-all.tq b/deps/v8/src/builtins/promise-all.tq index 19a16d8da85..b7fad88f6fc 100644 --- a/deps/v8/src/builtins/promise-all.tq +++ b/deps/v8/src/builtins/promise-all.tq @@ -6,165 +6,160 @@ #include 'src/builtins/builtins-promise-gen.h' namespace promise { - const kPromiseBuiltinsPromiseContextLength: constexpr int31 - generates 'PromiseBuiltins::kPromiseContextLength'; - - // Creates the context used by all Promise.all resolve element closures, - // together with the values array. Since all closures for a single Promise.all - // call use the same context, we need to store the indices for the individual - // closures somewhere else (we put them into the identity hash field of the - // closures), and we also need to have a separate marker for when the closure - // was called already (we slap the native context onto the closure in that - // case to mark it's done). - macro CreatePromiseAllResolveElementContext(implicit context: Context)( - capability: PromiseCapability, nativeContext: NativeContext): Context { - // TODO(bmeurer): Manually fold this into a single allocation. - const arrayMap = UnsafeCast<Map>( - nativeContext[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]); - const valuesArray = AllocateJSArray( - ElementsKind::PACKED_ELEMENTS, arrayMap, IntPtrConstant(0), - SmiConstant(0)); - const resolveContext = AllocateSyntheticFunctionContext( - nativeContext, - PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength); - resolveContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementRemainingSlot] = SmiConstant(1); - resolveContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementCapabilitySlot] = capability; - resolveContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementValuesArraySlot] = valuesArray; - return resolveContext; - } +const kPromiseBuiltinsPromiseContextLength: constexpr int31 + generates 'PromiseBuiltins::kPromiseContextLength'; + +// Creates the context used by all Promise.all resolve element closures, +// together with the values array. Since all closures for a single Promise.all +// call use the same context, we need to store the indices for the individual +// closures somewhere else (we put them into the identity hash field of the +// closures), and we also need to have a separate marker for when the closure +// was called already (we slap the native context onto the closure in that +// case to mark it's done). +macro CreatePromiseAllResolveElementContext(implicit context: Context)( + capability: PromiseCapability, nativeContext: NativeContext): Context { + // TODO(bmeurer): Manually fold this into a single allocation. + const arrayMap = UnsafeCast<Map>( + nativeContext[NativeContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX]); + const valuesArray = AllocateJSArray( + ElementsKind::PACKED_ELEMENTS, arrayMap, IntPtrConstant(0), + SmiConstant(0)); + const resolveContext = AllocateSyntheticFunctionContext( + nativeContext, + PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength); + resolveContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementRemainingSlot] = SmiConstant(1); + resolveContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementCapabilitySlot] = capability; + resolveContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementValuesArraySlot] = valuesArray; + return resolveContext; +} - macro CreatePromiseAllResolveElementFunction(implicit context: Context)( - resolveElementContext: Context, index: Smi, nativeContext: NativeContext, - slotIndex: constexpr NativeContextSlot): JSFunction { - assert(index > 0); - assert(index < kPropertyArrayHashFieldMax); - - const map = UnsafeCast<Map>( - nativeContext - [NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]); - const resolveInfo = - UnsafeCast<SharedFunctionInfo>(nativeContext[slotIndex]); - const resolve = AllocateFunctionWithMapAndContext( - map, resolveInfo, resolveElementContext); - - assert(kPropertyArrayNoHashSentinel == 0); - resolve.properties_or_hash = index; - return resolve; - } +macro CreatePromiseAllResolveElementFunction(implicit context: Context)( + resolveElementContext: Context, index: Smi, nativeContext: NativeContext, + resolveFunction: SharedFunctionInfo): JSFunction { + assert(index > 0); + assert(index < kPropertyArrayHashFieldMax); + + const map = UnsafeCast<Map>( + nativeContext + [NativeContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX]); + const resolve = AllocateFunctionWithMapAndContext( + map, resolveFunction, resolveElementContext); + + assert(kPropertyArrayNoHashSentinel == 0); + resolve.properties_or_hash = index; + return resolve; +} - @export - macro CreatePromiseResolvingFunctionsContext(implicit context: Context)( - promise: JSPromise, debugEvent: Object, nativeContext: NativeContext): - Context { - const resolveContext = AllocateSyntheticFunctionContext( - nativeContext, kPromiseBuiltinsPromiseContextLength); - resolveContext[kPromiseBuiltinsPromiseSlot] = promise; - resolveContext[kPromiseBuiltinsAlreadyResolvedSlot] = False; - resolveContext[kPromiseBuiltinsDebugEventSlot] = debugEvent; - return resolveContext; - } +@export +macro CreatePromiseResolvingFunctionsContext(implicit context: Context)( + promise: JSPromise, debugEvent: Object, nativeContext: NativeContext): + Context { + const resolveContext = AllocateSyntheticFunctionContext( + nativeContext, kPromiseBuiltinsPromiseContextLength); + resolveContext[kPromiseBuiltinsPromiseSlot] = promise; + resolveContext[kPromiseBuiltinsAlreadyResolvedSlot] = False; + resolveContext[kPromiseBuiltinsDebugEventSlot] = debugEvent; + return resolveContext; +} - macro IsPromiseThenLookupChainIntact(implicit context: Context)( - nativeContext: NativeContext, receiverMap: Map): bool { - if (IsForceSlowPath()) return false; - if (!IsJSPromiseMap(receiverMap)) return false; - if (receiverMap.prototype != - nativeContext[NativeContextSlot::PROMISE_PROTOTYPE_INDEX]) - return false; - return !IsPromiseThenProtectorCellInvalid(); - } +macro IsPromiseThenLookupChainIntact(implicit context: Context)( + nativeContext: NativeContext, receiverMap: Map): bool { + if (IsForceSlowPath()) return false; + if (!IsJSPromiseMap(receiverMap)) return false; + if (receiverMap.prototype != + nativeContext[NativeContextSlot::PROMISE_PROTOTYPE_INDEX]) + return false; + return !IsPromiseThenProtectorCellInvalid(); +} - struct PromiseAllResolveElementFunctor { - macro Call(implicit context: Context)( - resolveElementContext: Context, nativeContext: NativeContext, - index: Smi, _capability: PromiseCapability): Callable { - return CreatePromiseAllResolveElementFunction( - resolveElementContext, index, nativeContext, - NativeContextSlot::PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN); - } +struct PromiseAllResolveElementFunctor { + macro Call(implicit context: Context)( + resolveElementContext: Context, nativeContext: NativeContext, index: Smi, + _capability: PromiseCapability): Callable { + return CreatePromiseAllResolveElementFunction( + resolveElementContext, index, nativeContext, + PromiseAllResolveElementSharedFunConstant()); } +} - struct PromiseAllRejectElementFunctor { - macro Call(implicit context: Context)( - _resolveElementContext: Context, _nativeContext: NativeContext, - _index: Smi, capability: PromiseCapability): Callable { - return UnsafeCast<Callable>(capability.reject); - } +struct PromiseAllRejectElementFunctor { + macro Call(implicit context: Context)( + _resolveElementContext: Context, _nativeContext: NativeContext, + _index: Smi, capability: PromiseCapability): Callable { + return UnsafeCast<Callable>(capability.reject); } +} - struct PromiseAllSettledResolveElementFunctor { - macro Call(implicit context: Context)( - resolveElementContext: Context, nativeContext: NativeContext, - index: Smi, _capability: PromiseCapability): Callable { - return CreatePromiseAllResolveElementFunction( - resolveElementContext, index, nativeContext, - NativeContextSlot::PROMISE_ALL_SETTLED_RESOLVE_ELEMENT_SHARED_FUN); - } +struct PromiseAllSettledResolveElementFunctor { + macro Call(implicit context: Context)( + resolveElementContext: Context, nativeContext: NativeContext, index: Smi, + _capability: PromiseCapability): Callable { + return CreatePromiseAllResolveElementFunction( + resolveElementContext, index, nativeContext, + PromiseAllSettledResolveElementSharedFunConstant()); } +} - struct PromiseAllSettledRejectElementFunctor { - macro Call(implicit context: Context)( - resolveElementContext: Context, nativeContext: NativeContext, - index: Smi, _capability: PromiseCapability): Callable { - return CreatePromiseAllResolveElementFunction( - resolveElementContext, index, nativeContext, - NativeContextSlot::PROMISE_ALL_SETTLED_REJECT_ELEMENT_SHARED_FUN); - } +struct PromiseAllSettledRejectElementFunctor { + macro Call(implicit context: Context)( + resolveElementContext: Context, nativeContext: NativeContext, index: Smi, + _capability: PromiseCapability): Callable { + return CreatePromiseAllResolveElementFunction( + resolveElementContext, index, nativeContext, + PromiseAllSettledRejectElementSharedFunConstant()); } +} - transitioning macro PerformPromiseAll<F1: type, F2: type>(implicit context: - Context)( - constructor: JSReceiver, capability: PromiseCapability, - iter: iterator::IteratorRecord, createResolveElementFunctor: F1, - createRejectElementFunctor: F2): JSAny labels Reject(Object) { - const nativeContext = LoadNativeContext(context); - const promise = capability.promise; - const resolve = capability.resolve; - const reject = capability.reject; - - // For catch prediction, don't treat the .then calls as handling it; - // instead, recurse outwards. - if (IsDebugActive()) deferred { - SetPropertyStrict( - context, reject, kPromiseForwardingHandlerSymbol, True); - } +transitioning macro PerformPromiseAll<F1: type, F2: type>( + implicit context: Context)( + constructor: JSReceiver, capability: PromiseCapability, + iter: iterator::IteratorRecord, createResolveElementFunctor: F1, + createRejectElementFunctor: F2): JSAny labels +Reject(Object) { + const nativeContext = LoadNativeContext(context); + const promise = capability.promise; + const resolve = capability.resolve; + const reject = capability.reject; + + // For catch prediction, don't treat the .then calls as handling it; + // instead, recurse outwards. + if (IsDebugActive()) deferred { + SetPropertyStrict(context, reject, kPromiseForwardingHandlerSymbol, True); + } - const resolveElementContext = - CreatePromiseAllResolveElementContext(capability, nativeContext); + const resolveElementContext = + CreatePromiseAllResolveElementContext(capability, nativeContext); - let index: Smi = 1; + let index: Smi = 1; - // We can skip the "resolve" lookup on {constructor} if it's the - // Promise constructor and the Promise.resolve protector is intact, - // as that guards the lookup path for the "resolve" property on the - // Promise constructor. - let promiseResolveFunction: JSAny = Undefined; + // We can skip the "resolve" lookup on {constructor} if it's the + // Promise constructor and the Promise.resolve protector is intact, + // as that guards the lookup path for the "resolve" property on the + // Promise constructor. + let promiseResolveFunction: JSAny = Undefined; + try { try { - try { - if (!IsPromiseResolveLookupChainIntact(nativeContext, constructor)) { - // 5. Let _promiseResolve_ be ? Get(_constructor_, `"resolve"`). - let promiseResolve: JSAny; - try { - promiseResolve = GetProperty(constructor, kResolveString); - } catch (e) deferred { - iterator::IteratorCloseOnException(iter, e) otherwise Reject; - } - - // 6. If IsCallable(_promiseResolve_) is *false*, throw a *TypeError* - // exception. - promiseResolveFunction = Cast<Callable>(promiseResolve) - otherwise ThrowTypeError( - MessageTemplate::kCalledNonCallable, 'resolve'); - } + if (!IsPromiseResolveLookupChainIntact(nativeContext, constructor)) { + let promiseResolve: JSAny; + + // 5. Let _promiseResolve_ be ? Get(_constructor_, `"resolve"`). + promiseResolve = GetProperty(constructor, kResolveString); - const fastIteratorResultMap = UnsafeCast<Map>( - nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]); - while (true) { - let nextValue: JSAny; + // 6. If IsCallable(_promiseResolve_) is *false*, throw a *TypeError* + // exception. + promiseResolveFunction = + Cast<Callable>(promiseResolve) otherwise ThrowTypeError( + MessageTemplate::kCalledNonCallable, 'resolve'); + } + const fastIteratorResultMap = UnsafeCast<Map>( + nativeContext[NativeContextSlot::ITERATOR_RESULT_MAP_INDEX]); + while (true) { + let nextValue: JSAny; + try { // Let next be IteratorStep(iteratorRecord.[[Iterator]]). // If next is an abrupt completion, set iteratorRecord.[[Done]] to // true. ReturnIfAbrupt(next). @@ -176,209 +171,207 @@ namespace promise { // to true. // ReturnIfAbrupt(nextValue). nextValue = iterator::IteratorValue(next, fastIteratorResultMap); + } catch (e) { + goto Reject(e); + } - // Check if we reached the limit. - if (index == kPropertyArrayHashFieldMax) { - // If there are too many elements (currently more than 2**21-1), - // raise a RangeError here (which is caught directly and turned into - // a rejection) of the resulting promise. We could gracefully handle - // this case as well and support more than this number of elements - // by going to a separate function and pass the larger indices via a - // separate context, but it doesn't seem likely that we need this, - // and it's unclear how the rest of the system deals with 2**21 live - // Promises anyways. - try { - ThrowRangeError(MessageTemplate::kTooManyElementsInPromiseAll); - } catch (e) deferred { - iterator::IteratorCloseOnException(iter, e) otherwise Reject; - } - } - - // Set remainingElementsCount.[[Value]] to - // remainingElementsCount.[[Value]] + 1. - const remainingElementsCount = - UnsafeCast<Smi>(resolveElementContext - [PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementRemainingSlot]); - resolveElementContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementRemainingSlot] = - remainingElementsCount + 1; - - // Let resolveElement be CreateBuiltinFunction(steps, - // « [[AlreadyCalled]], - // [[Index]], - // [[Values]], - // [[Capability]], - // [[RemainingElements]] - // »). - // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false - // }. Set resolveElement.[[Index]] to index. Set - // resolveElement.[[Values]] to values. Set - // resolveElement.[[Capability]] to resultCapability. Set - // resolveElement.[[RemainingElements]] to remainingElementsCount. - const resolveElementFun = createResolveElementFunctor.Call( - resolveElementContext, nativeContext, index, capability); - const rejectElementFun = createRejectElementFunctor.Call( - resolveElementContext, nativeContext, index, capability); - - // We can skip the "resolve" lookup on the {constructor} as well as - // the "then" lookup on the result of the "resolve" call, and - // immediately chain continuation onto the {next_value} if: - // - // (a) The {constructor} is the intrinsic %Promise% function, and - // looking up "resolve" on {constructor} yields the initial - // Promise.resolve() builtin, and - // (b) the promise @@species protector cell is valid, meaning that - // no one messed with the Symbol.species property on any - // intrinsic promise or on the Promise.prototype, and - // (c) the {next_value} is a JSPromise whose [[Prototype]] field - // contains the intrinsic %PromisePrototype%, and - // (d) we're not running with async_hooks or DevTools enabled. - // - // In that case we also don't need to allocate a chained promise for - // the PromiseReaction (aka we can pass undefined to - // PerformPromiseThen), since this is only necessary for DevTools and - // PromiseHooks. - if (promiseResolveFunction != Undefined || - IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() || - IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) || - !IsPromiseThenLookupChainIntact( - nativeContext, UnsafeCast<HeapObject>(nextValue).map)) { - try { - // Let nextPromise be ? Call(constructor, _promiseResolve_, « - // nextValue »). - const nextPromise = CallResolve( - UnsafeCast<Constructor>(constructor), promiseResolveFunction, - nextValue); - - // Perform ? Invoke(nextPromise, "then", « resolveElement, - // resultCapability.[[Reject]] »). - const then = GetProperty(nextPromise, kThenString); - const thenResult = Call( - nativeContext, then, nextPromise, resolveElementFun, - rejectElementFun); - - // For catch prediction, mark that rejections here are - // semantically handled by the combined Promise. - if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred { - SetPropertyStrict( - context, thenResult, kPromiseHandledBySymbol, promise); - } - } catch (e) deferred { - iterator::IteratorCloseOnException(iter, e) otherwise Reject; + // Check if we reached the limit. + if (index == kPropertyArrayHashFieldMax) { + // If there are too many elements (currently more than 2**21-1), + // raise a RangeError here (which is caught below and turned into + // a rejection of the resulting promise). We could gracefully handle + // this case as well and support more than this number of elements + // by going to a separate function and pass the larger indices via a + // separate context, but it doesn't seem likely that we need this, + // and it's unclear how the rest of the system deals with 2**21 live + // Promises anyway. + ThrowRangeError( + MessageTemplate::kTooManyElementsInPromiseCombinator, 'all'); + } + + // Set remainingElementsCount.[[Value]] to + // remainingElementsCount.[[Value]] + 1. + const remainingElementsCount = UnsafeCast<Smi>( + resolveElementContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementRemainingSlot]); + resolveElementContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementRemainingSlot] = + remainingElementsCount + 1; + + // Let resolveElement be CreateBuiltinFunction(steps, + // « [[AlreadyCalled]], + // [[Index]], + // [[Values]], + // [[Capability]], + // [[RemainingElements]] + // »). + // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false + // }. Set resolveElement.[[Index]] to index. Set + // resolveElement.[[Values]] to values. Set + // resolveElement.[[Capability]] to resultCapability. Set + // resolveElement.[[RemainingElements]] to remainingElementsCount. + const resolveElementFun = createResolveElementFunctor.Call( + resolveElementContext, nativeContext, index, capability); + const rejectElementFun = createRejectElementFunctor.Call( + resolveElementContext, nativeContext, index, capability); + + // We can skip the "resolve" lookup on the {constructor} as well as + // the "then" lookup on the result of the "resolve" call, and + // immediately chain continuation onto the {next_value} if: + // + // (a) The {constructor} is the intrinsic %Promise% function, and + // looking up "resolve" on {constructor} yields the initial + // Promise.resolve() builtin, and + // (b) the promise @@species protector cell is valid, meaning that + // no one messed with the Symbol.species property on any + // intrinsic promise or on the Promise.prototype, and + // (c) the {next_value} is a JSPromise whose [[Prototype]] field + // contains the intrinsic %PromisePrototype%, and + // (d) we're not running with async_hooks or DevTools enabled. + // + // In that case we also don't need to allocate a chained promise for + // the PromiseReaction (aka we can pass undefined to + // PerformPromiseThen), since this is only necessary for DevTools and + // PromiseHooks. + if (promiseResolveFunction != Undefined || + IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() || + IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) || + !IsPromiseThenLookupChainIntact( + nativeContext, UnsafeCast<HeapObject>(nextValue).map)) { + // Let nextPromise be ? Call(constructor, _promiseResolve_, « + // nextValue »). + const nextPromise = CallResolve( + UnsafeCast<Constructor>(constructor), promiseResolveFunction, + nextValue); + + // Perform ? Invoke(nextPromise, "then", « resolveElement, + // resultCapability.[[Reject]] »). + const then = GetProperty(nextPromise, kThenString); + const thenResult = Call( + nativeContext, then, nextPromise, resolveElementFun, + rejectElementFun); + + // For catch prediction, mark that rejections here are + // semantically handled by the combined Promise. + if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred { + SetPropertyStrict( + context, thenResult, kPromiseHandledBySymbol, promise); } - } else { - PerformPromiseThenImpl( - UnsafeCast<JSPromise>(nextValue), resolveElementFun, - rejectElementFun, Undefined); - } - - // Set index to index + 1. - index += 1; + } else { + PerformPromiseThenImpl( + UnsafeCast<JSPromise>(nextValue), resolveElementFun, + rejectElementFun, Undefined); } + + // Set index to index + 1. + index += 1; } + } catch (e) deferred { + iterator::IteratorCloseOnException(iter); + goto Reject(e); } - label Done {} - - // Set iteratorRecord.[[Done]] to true. - // Set remainingElementsCount.[[Value]] to - // remainingElementsCount.[[Value]] - 1. - let remainingElementsCount = UnsafeCast<Smi>( + } label Done {} + + // Set iteratorRecord.[[Done]] to true. + // Set remainingElementsCount.[[Value]] to + // remainingElementsCount.[[Value]] - 1. + let remainingElementsCount = UnsafeCast<Smi>( + resolveElementContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementRemainingSlot]); + remainingElementsCount -= 1; + resolveElementContext[PromiseAllResolveElementContextSlots:: + kPromiseAllResolveElementRemainingSlot] = + remainingElementsCount; + if (remainingElementsCount > 0) { + // Pre-allocate the backing store for the {values_array} to the desired + // capacity here. We may already have elements here in case of some + // fancy Thenable that calls the resolve callback immediately, so we need + // to handle that correctly here. + const valuesArray = UnsafeCast<JSArray>( resolveElementContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementRemainingSlot]); - remainingElementsCount -= 1; - resolveElementContext[PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementRemainingSlot] = - remainingElementsCount; - if (remainingElementsCount > 0) { - // Pre-allocate the backing store for the {values_array} to the desired - // capacity here. We may already have elements here in case of some - // fancy Thenable that calls the resolve callback immediately, so we need - // to handle that correctly here. - const valuesArray = UnsafeCast<JSArray>( + kPromiseAllResolveElementValuesArraySlot]); + const oldElements = UnsafeCast<FixedArray>(valuesArray.elements); + const oldCapacity = oldElements.length_intptr; + const newCapacity = SmiUntag(index); + if (oldCapacity < newCapacity) { + valuesArray.elements = + ExtractFixedArray(oldElements, 0, oldCapacity, newCapacity); + } + } else + deferred { + // If remainingElementsCount.[[Value]] is 0, then + // Let valuesArray be CreateArrayFromList(values). + // Perform ? Call(resultCapability.[[Resolve]], undefined, + // « valuesArray »). + assert(remainingElementsCount == 0); + const valuesArray = UnsafeCast<JSAny>( resolveElementContext[PromiseAllResolveElementContextSlots:: kPromiseAllResolveElementValuesArraySlot]); - const oldElements = UnsafeCast<FixedArray>(valuesArray.elements); - const oldCapacity = oldElements.length_intptr; - const newCapacity = SmiUntag(index); - if (oldCapacity < newCapacity) { - valuesArray.elements = - ExtractFixedArray(oldElements, 0, oldCapacity, newCapacity); - } - } else - deferred { - // If remainingElementsCount.[[Value]] is 0, then - // Let valuesArray be CreateArrayFromList(values). - // Perform ? Call(resultCapability.[[Resolve]], undefined, - // « valuesArray »). - assert(remainingElementsCount == 0); - const valuesArray = UnsafeCast<JSAny>( - resolveElementContext - [PromiseAllResolveElementContextSlots:: - kPromiseAllResolveElementValuesArraySlot]); - Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray); - } - - // Return resultCapability.[[Promise]]. - return promise; - } + Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray); + } - transitioning macro GeneratePromiseAll<F1: type, F2: type>(implicit context: - Context)( - receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1, - createRejectElementFunctor: F2): JSAny { - // Let C be the this value. - // If Type(C) is not Object, throw a TypeError exception. - const receiver = Cast<JSReceiver>(receiver) - otherwise ThrowTypeError( - MessageTemplate::kCalledOnNonObject, 'Promise.all'); - - // Let promiseCapability be ? NewPromiseCapability(C). - // Don't fire debugEvent so that forwarding the rejection through all does - // not trigger redundant ExceptionEvents - const capability = NewPromiseCapability(receiver, False); + // Return resultCapability.[[Promise]]. + return promise; +} - try { - try { - // Let iterator be GetIterator(iterable). - // IfAbruptRejectPromise(iterator, promiseCapability). - let i = iterator::GetIterator(iterable); - - // Let result be PerformPromiseAll(iteratorRecord, C, - // promiseCapability). If result is an abrupt completion, then - // If iteratorRecord.[[Done]] is false, let result be - // IteratorClose(iterator, result). - // IfAbruptRejectPromise(result, promiseCapability). - return PerformPromiseAll( - receiver, capability, i, createResolveElementFunctor, - createRejectElementFunctor) otherwise Reject; - } catch (e) deferred { - goto Reject(e); - } - } - label Reject(e: Object) deferred { - // Exception must be bound to a JS value. - const e = UnsafeCast<JSAny>(e); - const reject = UnsafeCast<JSAny>(capability.reject); - Call(context, reject, Undefined, e); - return capability.promise; - } +transitioning macro GeneratePromiseAll<F1: type, F2: type>( + implicit context: Context)( + receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1, + createRejectElementFunctor: F2): JSAny { + // Let C be the this value. + // If Type(C) is not Object, throw a TypeError exception. + const receiver = Cast<JSReceiver>(receiver) + otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.all'); + + // Let promiseCapability be ? NewPromiseCapability(C). + // Don't fire debugEvent so that forwarding the rejection through all does + // not trigger redundant ExceptionEvents + const capability = NewPromiseCapability(receiver, False); + + try { + // Let iterator be GetIterator(iterable). + // IfAbruptRejectPromise(iterator, promiseCapability). + let i = iterator::GetIterator(iterable); + + // Let result be PerformPromiseAll(iteratorRecord, C, + // promiseCapability). If result is an abrupt completion, then + // If iteratorRecord.[[Done]] is false, let result be + // IteratorClose(iterator, result). + // IfAbruptRejectPromise(result, promiseCapability). + return PerformPromiseAll( + receiver, capability, i, createResolveElementFunctor, + createRejectElementFunctor) otherwise Reject; + } catch (e) deferred { + goto Reject(e); + } label Reject(e: Object) deferred { + // Exception must be bound to a JS value. + const e = UnsafeCast<JSAny>(e); + const reject = UnsafeCast<JSAny>(capability.reject); + Call(context, reject, Undefined, e); + return capability.promise; } +} - // ES#sec-promise.all - transitioning javascript builtin PromiseAll( - js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { - return GeneratePromiseAll( - receiver, iterable, PromiseAllResolveElementFunctor{}, - PromiseAllRejectElementFunctor{}); - } +// ES#sec-promise.all +transitioning javascript builtin PromiseAll( + js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { + return GeneratePromiseAll( + receiver, iterable, PromiseAllResolveElementFunctor{}, + PromiseAllRejectElementFunctor{}); +} - // ES#sec-promise.allsettled - // Promise.allSettled ( iterable ) - transitioning javascript builtin PromiseAllSettled( - js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { - return GeneratePromiseAll( - receiver, iterable, PromiseAllSettledResolveElementFunctor{}, - PromiseAllSettledRejectElementFunctor{}); - } +// ES#sec-promise.allsettled +// Promise.allSettled ( iterable ) +transitioning javascript builtin PromiseAllSettled( + js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { + return GeneratePromiseAll( + receiver, iterable, PromiseAllSettledResolveElementFunctor{}, + PromiseAllSettledRejectElementFunctor{}); +} + +extern macro PromiseAllResolveElementSharedFunConstant(): SharedFunctionInfo; +extern macro PromiseAllSettledRejectElementSharedFunConstant(): + SharedFunctionInfo; +extern macro PromiseAllSettledResolveElementSharedFunConstant(): + SharedFunctionInfo; } |