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-gen.h'
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_cinamespace promise {
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-promise.race
101cb0ef41Sopenharmony_citransitioning javascript builtin
111cb0ef41Sopenharmony_ciPromiseRace(
121cb0ef41Sopenharmony_ci    js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
131cb0ef41Sopenharmony_ci  const receiver = Cast<JSReceiver>(receiver)
141cb0ef41Sopenharmony_ci      otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.race');
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci  // This builtin is attached to JSFunction created by the bootstrapper so
171cb0ef41Sopenharmony_ci  // `context` is the native context.
181cb0ef41Sopenharmony_ci  check(Is<NativeContext>(context));
191cb0ef41Sopenharmony_ci  const nativeContext = UnsafeCast<NativeContext>(context);
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  // Let promiseCapability be ? NewPromiseCapability(C).
221cb0ef41Sopenharmony_ci  // Don't fire debugEvent so that forwarding the rejection through all does
231cb0ef41Sopenharmony_ci  // not trigger redundant ExceptionEvents
241cb0ef41Sopenharmony_ci  const capability = NewPromiseCapability(receiver, False);
251cb0ef41Sopenharmony_ci  const resolve = capability.resolve;
261cb0ef41Sopenharmony_ci  const reject = capability.reject;
271cb0ef41Sopenharmony_ci  const promise = capability.promise;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  // NewPromiseCapability guarantees that receiver is Constructor.
301cb0ef41Sopenharmony_ci  dcheck(Is<Constructor>(receiver));
311cb0ef41Sopenharmony_ci  const constructor = UnsafeCast<Constructor>(receiver);
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  // For catch prediction, don't treat the .then calls as handling it;
341cb0ef41Sopenharmony_ci  // instead, recurse outwards.
351cb0ef41Sopenharmony_ci  if (IsDebugActive()) deferred {
361cb0ef41Sopenharmony_ci      SetPropertyStrict(context, reject, kPromiseForwardingHandlerSymbol, True);
371cb0ef41Sopenharmony_ci    }
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  try {
401cb0ef41Sopenharmony_ci    let promiseResolveFunction: JSAny;
411cb0ef41Sopenharmony_ci    let i: iterator::IteratorRecord;
421cb0ef41Sopenharmony_ci    try {
431cb0ef41Sopenharmony_ci      // Let promiseResolve be GetPromiseResolve(C).
441cb0ef41Sopenharmony_ci      // IfAbruptRejectPromise(promiseResolve, promiseCapability).
451cb0ef41Sopenharmony_ci      promiseResolveFunction = GetPromiseResolve(nativeContext, constructor);
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci      // Let iterator be GetIterator(iterable).
481cb0ef41Sopenharmony_ci      // IfAbruptRejectPromise(iterator, promiseCapability).
491cb0ef41Sopenharmony_ci      i = iterator::GetIterator(iterable);
501cb0ef41Sopenharmony_ci    } catch (e, _message) deferred {
511cb0ef41Sopenharmony_ci      goto Reject(e);
521cb0ef41Sopenharmony_ci    }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    // Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
551cb0ef41Sopenharmony_ci    try {
561cb0ef41Sopenharmony_ci      const fastIteratorResultMap = *NativeContextSlot(
571cb0ef41Sopenharmony_ci          nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX);
581cb0ef41Sopenharmony_ci      while (true) {
591cb0ef41Sopenharmony_ci        let nextValue: JSAny;
601cb0ef41Sopenharmony_ci        try {
611cb0ef41Sopenharmony_ci          // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
621cb0ef41Sopenharmony_ci          // If next is an abrupt completion, set iteratorRecord.[[Done]] to
631cb0ef41Sopenharmony_ci          // true. ReturnIfAbrupt(next).
641cb0ef41Sopenharmony_ci          const next: JSReceiver = iterator::IteratorStep(
651cb0ef41Sopenharmony_ci              i, fastIteratorResultMap) otherwise return promise;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci          // Let nextValue be IteratorValue(next).
681cb0ef41Sopenharmony_ci          // If nextValue is an abrupt completion, set iteratorRecord.[[Done]]
691cb0ef41Sopenharmony_ci          // to true.
701cb0ef41Sopenharmony_ci          // ReturnIfAbrupt(nextValue).
711cb0ef41Sopenharmony_ci          nextValue = iterator::IteratorValue(next, fastIteratorResultMap);
721cb0ef41Sopenharmony_ci        } catch (e, _message) {
731cb0ef41Sopenharmony_ci          goto Reject(e);
741cb0ef41Sopenharmony_ci        }
751cb0ef41Sopenharmony_ci        // Let nextPromise be ? Call(constructor, _promiseResolve_, «
761cb0ef41Sopenharmony_ci        // nextValue »).
771cb0ef41Sopenharmony_ci        const nextPromise =
781cb0ef41Sopenharmony_ci            CallResolve(constructor, promiseResolveFunction, nextValue);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci        // Perform ? Invoke(nextPromise, "then", « resolveElement,
811cb0ef41Sopenharmony_ci        //                  resultCapability.[[Reject]] »).
821cb0ef41Sopenharmony_ci        const then = GetProperty(nextPromise, kThenString);
831cb0ef41Sopenharmony_ci        const thenResult = Call(
841cb0ef41Sopenharmony_ci            context, then, nextPromise, UnsafeCast<JSAny>(resolve),
851cb0ef41Sopenharmony_ci            UnsafeCast<JSAny>(reject));
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci        // For catch prediction, mark that rejections here are semantically
881cb0ef41Sopenharmony_ci        // handled by the combined Promise.
891cb0ef41Sopenharmony_ci        if (IsDebugActive() && !Is<JSPromise>(promise)) deferred {
901cb0ef41Sopenharmony_ci            SetPropertyStrict(
911cb0ef41Sopenharmony_ci                context, thenResult, kPromiseHandledBySymbol, promise);
921cb0ef41Sopenharmony_ci          }
931cb0ef41Sopenharmony_ci      }
941cb0ef41Sopenharmony_ci    } catch (e, _message) deferred {
951cb0ef41Sopenharmony_ci      iterator::IteratorCloseOnException(i);
961cb0ef41Sopenharmony_ci      goto Reject(e);
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci  } label Reject(exception: JSAny) deferred {
991cb0ef41Sopenharmony_ci    Call(context, UnsafeCast<JSAny>(reject), Undefined, exception);
1001cb0ef41Sopenharmony_ci    return promise;
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci  unreachable;
1031cb0ef41Sopenharmony_ci}
1041cb0ef41Sopenharmony_ci}
105