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