11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include 'src/builtins/builtins-promise.h' 61cb0ef41Sopenharmony_ci#include 'src/builtins/builtins-promise-gen.h' 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_cinamespace promise { 91cb0ef41Sopenharmony_ciconst kPromiseBuiltinsPromiseContextLength: constexpr int31 101cb0ef41Sopenharmony_ci generates 'PromiseBuiltins::kPromiseContextLength'; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci// Creates the context used by all Promise.all resolve element closures, 131cb0ef41Sopenharmony_ci// together with the values array. Since all closures for a single Promise.all 141cb0ef41Sopenharmony_ci// call use the same context, we need to store the indices for the individual 151cb0ef41Sopenharmony_ci// closures somewhere else (we put them into the identity hash field of the 161cb0ef41Sopenharmony_ci// closures), and we also need to have a separate marker for when the closure 171cb0ef41Sopenharmony_ci// was called already (we slap the native context onto the closure in that 181cb0ef41Sopenharmony_ci// case to mark it's done). 191cb0ef41Sopenharmony_cimacro CreatePromiseAllResolveElementContext(implicit context: Context)( 201cb0ef41Sopenharmony_ci capability: PromiseCapability, 211cb0ef41Sopenharmony_ci nativeContext: NativeContext): PromiseAllResolveElementContext { 221cb0ef41Sopenharmony_ci const resolveContext = %RawDownCast< 231cb0ef41Sopenharmony_ci PromiseAllResolveElementContext>(AllocateSyntheticFunctionContext( 241cb0ef41Sopenharmony_ci nativeContext, 251cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength)); 261cb0ef41Sopenharmony_ci InitContextSlot( 271cb0ef41Sopenharmony_ci resolveContext, 281cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 291cb0ef41Sopenharmony_ci kPromiseAllResolveElementRemainingSlot, 301cb0ef41Sopenharmony_ci 1); 311cb0ef41Sopenharmony_ci InitContextSlot( 321cb0ef41Sopenharmony_ci resolveContext, 331cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 341cb0ef41Sopenharmony_ci kPromiseAllResolveElementCapabilitySlot, 351cb0ef41Sopenharmony_ci capability); 361cb0ef41Sopenharmony_ci InitContextSlot( 371cb0ef41Sopenharmony_ci resolveContext, 381cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots::kPromiseAllResolveElementValuesSlot, 391cb0ef41Sopenharmony_ci kEmptyFixedArray); 401cb0ef41Sopenharmony_ci return resolveContext; 411cb0ef41Sopenharmony_ci} 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cimacro CreatePromiseAllResolveElementFunction(implicit context: Context)( 441cb0ef41Sopenharmony_ci resolveElementContext: PromiseAllResolveElementContext, index: Smi, 451cb0ef41Sopenharmony_ci nativeContext: NativeContext, 461cb0ef41Sopenharmony_ci resolveFunction: SharedFunctionInfo): JSFunction { 471cb0ef41Sopenharmony_ci dcheck(index > 0); 481cb0ef41Sopenharmony_ci dcheck(index < kPropertyArrayHashFieldMax); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci const map = *ContextSlot( 511cb0ef41Sopenharmony_ci nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); 521cb0ef41Sopenharmony_ci const resolve = AllocateFunctionWithMapAndContext( 531cb0ef41Sopenharmony_ci map, resolveFunction, resolveElementContext); 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci dcheck(kPropertyArrayNoHashSentinel == 0); 561cb0ef41Sopenharmony_ci resolve.properties_or_hash = index; 571cb0ef41Sopenharmony_ci return resolve; 581cb0ef41Sopenharmony_ci} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci@export 611cb0ef41Sopenharmony_cimacro CreatePromiseResolvingFunctionsContext(implicit context: Context)( 621cb0ef41Sopenharmony_ci promise: JSPromise, debugEvent: Boolean, nativeContext: NativeContext): 631cb0ef41Sopenharmony_ci PromiseResolvingFunctionContext { 641cb0ef41Sopenharmony_ci const resolveContext = %RawDownCast<PromiseResolvingFunctionContext>( 651cb0ef41Sopenharmony_ci AllocateSyntheticFunctionContext( 661cb0ef41Sopenharmony_ci nativeContext, 671cb0ef41Sopenharmony_ci PromiseResolvingFunctionContextSlot::kPromiseContextLength)); 681cb0ef41Sopenharmony_ci InitContextSlot( 691cb0ef41Sopenharmony_ci resolveContext, PromiseResolvingFunctionContextSlot::kPromiseSlot, 701cb0ef41Sopenharmony_ci promise); 711cb0ef41Sopenharmony_ci InitContextSlot( 721cb0ef41Sopenharmony_ci resolveContext, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot, 731cb0ef41Sopenharmony_ci False); 741cb0ef41Sopenharmony_ci InitContextSlot( 751cb0ef41Sopenharmony_ci resolveContext, PromiseResolvingFunctionContextSlot::kDebugEventSlot, 761cb0ef41Sopenharmony_ci debugEvent); 771cb0ef41Sopenharmony_ci static_assert( 781cb0ef41Sopenharmony_ci PromiseResolvingFunctionContextSlot::kPromiseContextLength == 791cb0ef41Sopenharmony_ci ContextSlot::MIN_CONTEXT_SLOTS + 3); 801cb0ef41Sopenharmony_ci return resolveContext; 811cb0ef41Sopenharmony_ci} 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_cimacro IsPromiseThenLookupChainIntact(implicit context: Context)( 841cb0ef41Sopenharmony_ci nativeContext: NativeContext, receiverMap: Map): bool { 851cb0ef41Sopenharmony_ci if (IsForceSlowPath()) return false; 861cb0ef41Sopenharmony_ci if (!IsJSPromiseMap(receiverMap)) return false; 871cb0ef41Sopenharmony_ci if (receiverMap.prototype != *NativeContextSlot( 881cb0ef41Sopenharmony_ci nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX)) { 891cb0ef41Sopenharmony_ci return false; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci return !IsPromiseThenProtectorCellInvalid(); 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_cistruct PromiseAllResolveElementFunctor { 951cb0ef41Sopenharmony_ci macro Call(implicit context: Context)( 961cb0ef41Sopenharmony_ci resolveElementContext: PromiseAllResolveElementContext, 971cb0ef41Sopenharmony_ci nativeContext: NativeContext, index: Smi, 981cb0ef41Sopenharmony_ci _capability: PromiseCapability): Callable { 991cb0ef41Sopenharmony_ci return CreatePromiseAllResolveElementFunction( 1001cb0ef41Sopenharmony_ci resolveElementContext, index, nativeContext, 1011cb0ef41Sopenharmony_ci PromiseAllResolveElementSharedFunConstant()); 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci} 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_cistruct PromiseAllRejectElementFunctor { 1061cb0ef41Sopenharmony_ci macro Call(implicit context: Context)( 1071cb0ef41Sopenharmony_ci _resolveElementContext: PromiseAllResolveElementContext, 1081cb0ef41Sopenharmony_ci _nativeContext: NativeContext, _index: Smi, 1091cb0ef41Sopenharmony_ci capability: PromiseCapability): Callable { 1101cb0ef41Sopenharmony_ci return UnsafeCast<Callable>(capability.reject); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_cistruct PromiseAllSettledResolveElementFunctor { 1151cb0ef41Sopenharmony_ci macro Call(implicit context: Context)( 1161cb0ef41Sopenharmony_ci resolveElementContext: PromiseAllResolveElementContext, 1171cb0ef41Sopenharmony_ci nativeContext: NativeContext, index: Smi, 1181cb0ef41Sopenharmony_ci _capability: PromiseCapability): Callable { 1191cb0ef41Sopenharmony_ci return CreatePromiseAllResolveElementFunction( 1201cb0ef41Sopenharmony_ci resolveElementContext, index, nativeContext, 1211cb0ef41Sopenharmony_ci PromiseAllSettledResolveElementSharedFunConstant()); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_cistruct PromiseAllSettledRejectElementFunctor { 1261cb0ef41Sopenharmony_ci macro Call(implicit context: Context)( 1271cb0ef41Sopenharmony_ci resolveElementContext: PromiseAllResolveElementContext, 1281cb0ef41Sopenharmony_ci nativeContext: NativeContext, index: Smi, 1291cb0ef41Sopenharmony_ci _capability: PromiseCapability): Callable { 1301cb0ef41Sopenharmony_ci return CreatePromiseAllResolveElementFunction( 1311cb0ef41Sopenharmony_ci resolveElementContext, index, nativeContext, 1321cb0ef41Sopenharmony_ci PromiseAllSettledRejectElementSharedFunConstant()); 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_citransitioning macro PerformPromiseAll<F1: type, F2: type>( 1371cb0ef41Sopenharmony_ci implicit context: Context)( 1381cb0ef41Sopenharmony_ci nativeContext: NativeContext, iter: iterator::IteratorRecord, 1391cb0ef41Sopenharmony_ci constructor: Constructor, capability: PromiseCapability, 1401cb0ef41Sopenharmony_ci promiseResolveFunction: JSAny, createResolveElementFunctor: F1, 1411cb0ef41Sopenharmony_ci createRejectElementFunctor: F2): JSAny labels 1421cb0ef41Sopenharmony_ciReject(JSAny) { 1431cb0ef41Sopenharmony_ci const promise = capability.promise; 1441cb0ef41Sopenharmony_ci const resolve = capability.resolve; 1451cb0ef41Sopenharmony_ci const reject = capability.reject; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // For catch prediction, don't treat the .then calls as handling it; 1481cb0ef41Sopenharmony_ci // instead, recurse outwards. 1491cb0ef41Sopenharmony_ci if (IsDebugActive()) deferred { 1501cb0ef41Sopenharmony_ci SetPropertyStrict(context, reject, kPromiseForwardingHandlerSymbol, True); 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci const resolveElementContext = 1541cb0ef41Sopenharmony_ci CreatePromiseAllResolveElementContext(capability, nativeContext); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci let index: Smi = 1; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci try { 1591cb0ef41Sopenharmony_ci const fastIteratorResultMap = *NativeContextSlot( 1601cb0ef41Sopenharmony_ci nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX); 1611cb0ef41Sopenharmony_ci while (true) { 1621cb0ef41Sopenharmony_ci let nextValue: JSAny; 1631cb0ef41Sopenharmony_ci try { 1641cb0ef41Sopenharmony_ci // Let next be IteratorStep(iteratorRecord.[[Iterator]]). 1651cb0ef41Sopenharmony_ci // If next is an abrupt completion, set iteratorRecord.[[Done]] to 1661cb0ef41Sopenharmony_ci // true. ReturnIfAbrupt(next). 1671cb0ef41Sopenharmony_ci const next: JSReceiver = iterator::IteratorStep( 1681cb0ef41Sopenharmony_ci iter, fastIteratorResultMap) otherwise goto Done; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci // Let nextValue be IteratorValue(next). 1711cb0ef41Sopenharmony_ci // If nextValue is an abrupt completion, set iteratorRecord.[[Done]] 1721cb0ef41Sopenharmony_ci // to true. 1731cb0ef41Sopenharmony_ci // ReturnIfAbrupt(nextValue). 1741cb0ef41Sopenharmony_ci nextValue = iterator::IteratorValue(next, fastIteratorResultMap); 1751cb0ef41Sopenharmony_ci } catch (e, _message) { 1761cb0ef41Sopenharmony_ci goto Reject(e); 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci // Check if we reached the limit. 1801cb0ef41Sopenharmony_ci if (index == kPropertyArrayHashFieldMax) { 1811cb0ef41Sopenharmony_ci // If there are too many elements (currently more than 2**21-1), 1821cb0ef41Sopenharmony_ci // raise a RangeError here (which is caught below and turned into 1831cb0ef41Sopenharmony_ci // a rejection of the resulting promise). We could gracefully handle 1841cb0ef41Sopenharmony_ci // this case as well and support more than this number of elements 1851cb0ef41Sopenharmony_ci // by going to a separate function and pass the larger indices via a 1861cb0ef41Sopenharmony_ci // separate context, but it doesn't seem likely that we need this, 1871cb0ef41Sopenharmony_ci // and it's unclear how the rest of the system deals with 2**21 live 1881cb0ef41Sopenharmony_ci // Promises anyway. 1891cb0ef41Sopenharmony_ci ThrowRangeError( 1901cb0ef41Sopenharmony_ci MessageTemplate::kTooManyElementsInPromiseCombinator, 'all'); 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci // Set remainingElementsCount.[[Value]] to 1941cb0ef41Sopenharmony_ci // remainingElementsCount.[[Value]] + 1. 1951cb0ef41Sopenharmony_ci *ContextSlot( 1961cb0ef41Sopenharmony_ci resolveElementContext, 1971cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 1981cb0ef41Sopenharmony_ci kPromiseAllResolveElementRemainingSlot) += 1; 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci // Let resolveElement be CreateBuiltinFunction(steps, 2011cb0ef41Sopenharmony_ci // « [[AlreadyCalled]], 2021cb0ef41Sopenharmony_ci // [[Index]], 2031cb0ef41Sopenharmony_ci // [[Values]], 2041cb0ef41Sopenharmony_ci // [[Capability]], 2051cb0ef41Sopenharmony_ci // [[RemainingElements]] 2061cb0ef41Sopenharmony_ci // »). 2071cb0ef41Sopenharmony_ci // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false 2081cb0ef41Sopenharmony_ci // }. Set resolveElement.[[Index]] to index. Set 2091cb0ef41Sopenharmony_ci // resolveElement.[[Values]] to values. Set 2101cb0ef41Sopenharmony_ci // resolveElement.[[Capability]] to resultCapability. Set 2111cb0ef41Sopenharmony_ci // resolveElement.[[RemainingElements]] to remainingElementsCount. 2121cb0ef41Sopenharmony_ci const resolveElementFun = createResolveElementFunctor.Call( 2131cb0ef41Sopenharmony_ci resolveElementContext, nativeContext, index, capability); 2141cb0ef41Sopenharmony_ci const rejectElementFun = createRejectElementFunctor.Call( 2151cb0ef41Sopenharmony_ci resolveElementContext, nativeContext, index, capability); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci // We can skip the "then" lookup on the result of the "resolve" call and 2181cb0ef41Sopenharmony_ci // immediately chain the continuation onto the {next_value} if: 2191cb0ef41Sopenharmony_ci // 2201cb0ef41Sopenharmony_ci // (a) The {constructor} is the intrinsic %Promise% function, and 2211cb0ef41Sopenharmony_ci // looking up "resolve" on {constructor} yields the initial 2221cb0ef41Sopenharmony_ci // Promise.resolve() builtin, and 2231cb0ef41Sopenharmony_ci // (b) the promise @@species protector cell is valid, meaning that 2241cb0ef41Sopenharmony_ci // no one messed with the Symbol.species property on any 2251cb0ef41Sopenharmony_ci // intrinsic promise or on the Promise.prototype, and 2261cb0ef41Sopenharmony_ci // (c) the {next_value} is a JSPromise whose [[Prototype]] field 2271cb0ef41Sopenharmony_ci // contains the intrinsic %PromisePrototype%, and 2281cb0ef41Sopenharmony_ci // (d) we're not running with async_hooks or DevTools enabled. 2291cb0ef41Sopenharmony_ci // 2301cb0ef41Sopenharmony_ci // In that case we also don't need to allocate a chained promise for 2311cb0ef41Sopenharmony_ci // the PromiseReaction (aka we can pass undefined to 2321cb0ef41Sopenharmony_ci // PerformPromiseThen), since this is only necessary for DevTools and 2331cb0ef41Sopenharmony_ci // PromiseHooks. 2341cb0ef41Sopenharmony_ci if (promiseResolveFunction != Undefined || NeedsAnyPromiseHooks() || 2351cb0ef41Sopenharmony_ci IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) || 2361cb0ef41Sopenharmony_ci !IsPromiseThenLookupChainIntact( 2371cb0ef41Sopenharmony_ci nativeContext, UnsafeCast<HeapObject>(nextValue).map)) { 2381cb0ef41Sopenharmony_ci // Let nextPromise be ? Call(constructor, _promiseResolve_, « 2391cb0ef41Sopenharmony_ci // nextValue »). 2401cb0ef41Sopenharmony_ci const nextPromise = 2411cb0ef41Sopenharmony_ci CallResolve(constructor, promiseResolveFunction, nextValue); 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci // Perform ? Invoke(nextPromise, "then", « resolveElement, 2441cb0ef41Sopenharmony_ci // resultCapability.[[Reject]] »). 2451cb0ef41Sopenharmony_ci const then = GetProperty(nextPromise, kThenString); 2461cb0ef41Sopenharmony_ci const thenResult = Call( 2471cb0ef41Sopenharmony_ci nativeContext, then, nextPromise, resolveElementFun, 2481cb0ef41Sopenharmony_ci rejectElementFun); 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci // For catch prediction, mark that rejections here are 2511cb0ef41Sopenharmony_ci // semantically handled by the combined Promise. 2521cb0ef41Sopenharmony_ci if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred { 2531cb0ef41Sopenharmony_ci SetPropertyStrict( 2541cb0ef41Sopenharmony_ci context, thenResult, kPromiseHandledBySymbol, promise); 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci } else { 2571cb0ef41Sopenharmony_ci PerformPromiseThenImpl( 2581cb0ef41Sopenharmony_ci UnsafeCast<JSPromise>(nextValue), resolveElementFun, 2591cb0ef41Sopenharmony_ci rejectElementFun, Undefined); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci // Set index to index + 1. 2631cb0ef41Sopenharmony_ci index += 1; 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci } catch (e, _message) deferred { 2661cb0ef41Sopenharmony_ci iterator::IteratorCloseOnException(iter); 2671cb0ef41Sopenharmony_ci goto Reject(e); 2681cb0ef41Sopenharmony_ci } label Done {} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci // Set iteratorRecord.[[Done]] to true. 2711cb0ef41Sopenharmony_ci // Set remainingElementsCount.[[Value]] to 2721cb0ef41Sopenharmony_ci // remainingElementsCount.[[Value]] - 1. 2731cb0ef41Sopenharmony_ci const remainingElementsCount = -- *ContextSlot( 2741cb0ef41Sopenharmony_ci resolveElementContext, 2751cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 2761cb0ef41Sopenharmony_ci kPromiseAllResolveElementRemainingSlot); 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci check(remainingElementsCount >= 0); 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci if (remainingElementsCount > 0) { 2811cb0ef41Sopenharmony_ci // Pre-allocate the backing store for the {values} to the desired 2821cb0ef41Sopenharmony_ci // capacity. We may already have elements in "values" - this happens 2831cb0ef41Sopenharmony_ci // when the Thenable calls the resolve callback immediately. 2841cb0ef41Sopenharmony_ci const valuesRef:&FixedArray = ContextSlot( 2851cb0ef41Sopenharmony_ci resolveElementContext, 2861cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 2871cb0ef41Sopenharmony_ci kPromiseAllResolveElementValuesSlot); 2881cb0ef41Sopenharmony_ci const values = *valuesRef; 2891cb0ef41Sopenharmony_ci // 'index' is a 1-based index and incremented after every Promise. Later we 2901cb0ef41Sopenharmony_ci // use 'values' as a 0-based array, so capacity 'index - 1' is enough. 2911cb0ef41Sopenharmony_ci const newCapacity = SmiUntag(index) - 1; 2921cb0ef41Sopenharmony_ci 2931cb0ef41Sopenharmony_ci const oldCapacity = values.length_intptr; 2941cb0ef41Sopenharmony_ci if (oldCapacity < newCapacity) { 2951cb0ef41Sopenharmony_ci *valuesRef = ExtractFixedArray(values, 0, oldCapacity, newCapacity); 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci } else 2981cb0ef41Sopenharmony_ci deferred { 2991cb0ef41Sopenharmony_ci // If remainingElementsCount.[[Value]] is 0, then 3001cb0ef41Sopenharmony_ci // Let valuesArray be CreateArrayFromList(values). 3011cb0ef41Sopenharmony_ci // Perform ? Call(resultCapability.[[Resolve]], undefined, 3021cb0ef41Sopenharmony_ci // « valuesArray »). 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci const values: FixedArray = *ContextSlot( 3051cb0ef41Sopenharmony_ci resolveElementContext, 3061cb0ef41Sopenharmony_ci PromiseAllResolveElementContextSlots:: 3071cb0ef41Sopenharmony_ci kPromiseAllResolveElementValuesSlot); 3081cb0ef41Sopenharmony_ci const arrayMap = 3091cb0ef41Sopenharmony_ci *NativeContextSlot( 3101cb0ef41Sopenharmony_ci nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX); 3111cb0ef41Sopenharmony_ci const valuesArray = NewJSArray(arrayMap, values); 3121cb0ef41Sopenharmony_ci Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray); 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci // Return resultCapability.[[Promise]]. 3161cb0ef41Sopenharmony_ci return promise; 3171cb0ef41Sopenharmony_ci} 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_citransitioning macro GeneratePromiseAll<F1: type, F2: type>( 3201cb0ef41Sopenharmony_ci implicit context: Context)( 3211cb0ef41Sopenharmony_ci receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1, 3221cb0ef41Sopenharmony_ci createRejectElementFunctor: F2, message: constexpr string): JSAny { 3231cb0ef41Sopenharmony_ci const nativeContext = LoadNativeContext(context); 3241cb0ef41Sopenharmony_ci // Let C be the this value. 3251cb0ef41Sopenharmony_ci // If Type(C) is not Object, throw a TypeError exception. 3261cb0ef41Sopenharmony_ci const receiver = Cast<JSReceiver>(receiver) 3271cb0ef41Sopenharmony_ci otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, message); 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci // Let promiseCapability be ? NewPromiseCapability(C). 3301cb0ef41Sopenharmony_ci // Don't fire debugEvent so that forwarding the rejection through all does 3311cb0ef41Sopenharmony_ci // not trigger redundant ExceptionEvents 3321cb0ef41Sopenharmony_ci const capability = NewPromiseCapability(receiver, False); 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci // NewPromiseCapability guarantees that receiver is Constructor. 3351cb0ef41Sopenharmony_ci dcheck(Is<Constructor>(receiver)); 3361cb0ef41Sopenharmony_ci const constructor = UnsafeCast<Constructor>(receiver); 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci try { 3391cb0ef41Sopenharmony_ci // Let promiseResolve be GetPromiseResolve(C). 3401cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(promiseResolve, promiseCapability). 3411cb0ef41Sopenharmony_ci const promiseResolveFunction = 3421cb0ef41Sopenharmony_ci GetPromiseResolve(nativeContext, constructor); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci // Let iterator be GetIterator(iterable). 3451cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(iterator, promiseCapability). 3461cb0ef41Sopenharmony_ci let i = iterator::GetIterator(iterable); 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // Let result be PerformPromiseAll(iteratorRecord, C, 3491cb0ef41Sopenharmony_ci // promiseCapability). If result is an abrupt completion, then 3501cb0ef41Sopenharmony_ci // If iteratorRecord.[[Done]] is false, let result be 3511cb0ef41Sopenharmony_ci // IteratorClose(iterator, result). 3521cb0ef41Sopenharmony_ci // IfAbruptRejectPromise(result, promiseCapability). 3531cb0ef41Sopenharmony_ci return PerformPromiseAll( 3541cb0ef41Sopenharmony_ci nativeContext, i, constructor, capability, promiseResolveFunction, 3551cb0ef41Sopenharmony_ci createResolveElementFunctor, createRejectElementFunctor) 3561cb0ef41Sopenharmony_ci otherwise Reject; 3571cb0ef41Sopenharmony_ci } catch (e, _message) deferred { 3581cb0ef41Sopenharmony_ci goto Reject(e); 3591cb0ef41Sopenharmony_ci } label Reject(e: JSAny) deferred { 3601cb0ef41Sopenharmony_ci const reject = UnsafeCast<JSAny>(capability.reject); 3611cb0ef41Sopenharmony_ci Call(context, reject, Undefined, e); 3621cb0ef41Sopenharmony_ci return capability.promise; 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci} 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci// ES#sec-promise.all 3671cb0ef41Sopenharmony_citransitioning javascript builtin PromiseAll( 3681cb0ef41Sopenharmony_ci js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { 3691cb0ef41Sopenharmony_ci return GeneratePromiseAll( 3701cb0ef41Sopenharmony_ci receiver, iterable, PromiseAllResolveElementFunctor{}, 3711cb0ef41Sopenharmony_ci PromiseAllRejectElementFunctor{}, 'Promise.all'); 3721cb0ef41Sopenharmony_ci} 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci// ES#sec-promise.allsettled 3751cb0ef41Sopenharmony_ci// Promise.allSettled ( iterable ) 3761cb0ef41Sopenharmony_citransitioning javascript builtin PromiseAllSettled( 3771cb0ef41Sopenharmony_ci js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny { 3781cb0ef41Sopenharmony_ci return GeneratePromiseAll( 3791cb0ef41Sopenharmony_ci receiver, iterable, PromiseAllSettledResolveElementFunctor{}, 3801cb0ef41Sopenharmony_ci PromiseAllSettledRejectElementFunctor{}, 'Promise.allSettled'); 3811cb0ef41Sopenharmony_ci} 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ciextern macro PromiseAllResolveElementSharedFunConstant(): SharedFunctionInfo; 3841cb0ef41Sopenharmony_ciextern macro PromiseAllSettledRejectElementSharedFunConstant(): 3851cb0ef41Sopenharmony_ci SharedFunctionInfo; 3861cb0ef41Sopenharmony_ciextern macro PromiseAllSettledResolveElementSharedFunConstant(): 3871cb0ef41Sopenharmony_ci SharedFunctionInfo; 3881cb0ef41Sopenharmony_ci} 389