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_citransitioning
101cb0ef41Sopenharmony_cimacro RejectPromiseReactionJob(
111cb0ef41Sopenharmony_ci    context: Context,
121cb0ef41Sopenharmony_ci    promiseOrCapability: JSPromise|PromiseCapability|Undefined, reason: JSAny,
131cb0ef41Sopenharmony_ci    reactionType: constexpr PromiseReactionType): JSAny {
141cb0ef41Sopenharmony_ci  if constexpr (reactionType == kPromiseReactionReject) {
151cb0ef41Sopenharmony_ci    typeswitch (promiseOrCapability) {
161cb0ef41Sopenharmony_ci      case (promise: JSPromise): {
171cb0ef41Sopenharmony_ci        // For fast native promises we can skip the indirection via the
181cb0ef41Sopenharmony_ci        // promiseCapability.[[Reject]] function and run the resolve logic
191cb0ef41Sopenharmony_ci        // directly from here.
201cb0ef41Sopenharmony_ci        return RejectPromise(promise, reason, False);
211cb0ef41Sopenharmony_ci      }
221cb0ef41Sopenharmony_ci      case (Undefined): {
231cb0ef41Sopenharmony_ci        return Undefined;
241cb0ef41Sopenharmony_ci      }
251cb0ef41Sopenharmony_ci      case (capability: PromiseCapability): {
261cb0ef41Sopenharmony_ci        // In the general case we need to call the (user provided)
271cb0ef41Sopenharmony_ci        // promiseCapability.[[Reject]] function.
281cb0ef41Sopenharmony_ci        const reject = UnsafeCast<Callable>(capability.reject);
291cb0ef41Sopenharmony_ci        return Call(context, reject, Undefined, reason);
301cb0ef41Sopenharmony_ci      }
311cb0ef41Sopenharmony_ci    }
321cb0ef41Sopenharmony_ci  } else {
331cb0ef41Sopenharmony_ci    static_assert(reactionType == kPromiseReactionFulfill);
341cb0ef41Sopenharmony_ci    // We have to call out to the dedicated PromiseRejectReactionJob
351cb0ef41Sopenharmony_ci    // builtin here, instead of just doing the work inline, as otherwise
361cb0ef41Sopenharmony_ci    // the catch predictions in the debugger will be wrong, which just
371cb0ef41Sopenharmony_ci    // walks the stack and checks for certain builtins.
381cb0ef41Sopenharmony_ci    return PromiseRejectReactionJob(reason, Undefined, promiseOrCapability);
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_citransitioning
431cb0ef41Sopenharmony_cimacro FuflfillPromiseReactionJob(
441cb0ef41Sopenharmony_ci    context: Context,
451cb0ef41Sopenharmony_ci    promiseOrCapability: JSPromise|PromiseCapability|Undefined, result: JSAny,
461cb0ef41Sopenharmony_ci    reactionType: constexpr PromiseReactionType): JSAny {
471cb0ef41Sopenharmony_ci  typeswitch (promiseOrCapability) {
481cb0ef41Sopenharmony_ci    case (promise: JSPromise): {
491cb0ef41Sopenharmony_ci      // For fast native promises we can skip the indirection via the
501cb0ef41Sopenharmony_ci      // promiseCapability.[[Resolve]] function and run the resolve logic
511cb0ef41Sopenharmony_ci      // directly from here.
521cb0ef41Sopenharmony_ci      return ResolvePromise(context, promise, result);
531cb0ef41Sopenharmony_ci    }
541cb0ef41Sopenharmony_ci    case (Undefined): {
551cb0ef41Sopenharmony_ci      return Undefined;
561cb0ef41Sopenharmony_ci    }
571cb0ef41Sopenharmony_ci    case (capability: PromiseCapability): {
581cb0ef41Sopenharmony_ci      // In the general case we need to call the (user provided)
591cb0ef41Sopenharmony_ci      // promiseCapability.[[Resolve]] function.
601cb0ef41Sopenharmony_ci      const resolve = UnsafeCast<Callable>(capability.resolve);
611cb0ef41Sopenharmony_ci      try {
621cb0ef41Sopenharmony_ci        return Call(context, resolve, Undefined, result);
631cb0ef41Sopenharmony_ci      } catch (e, _message) {
641cb0ef41Sopenharmony_ci        return RejectPromiseReactionJob(
651cb0ef41Sopenharmony_ci            context, promiseOrCapability, e, reactionType);
661cb0ef41Sopenharmony_ci      }
671cb0ef41Sopenharmony_ci    }
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci}
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-promisereactionjob
721cb0ef41Sopenharmony_citransitioning
731cb0ef41Sopenharmony_cimacro PromiseReactionJob(
741cb0ef41Sopenharmony_ci    context: Context, argument: JSAny, handler: Callable|Undefined,
751cb0ef41Sopenharmony_ci    promiseOrCapability: JSPromise|PromiseCapability|Undefined,
761cb0ef41Sopenharmony_ci    reactionType: constexpr PromiseReactionType): JSAny {
771cb0ef41Sopenharmony_ci  if (handler == Undefined) {
781cb0ef41Sopenharmony_ci    if constexpr (reactionType == kPromiseReactionFulfill) {
791cb0ef41Sopenharmony_ci      return FuflfillPromiseReactionJob(
801cb0ef41Sopenharmony_ci          context, promiseOrCapability, argument, reactionType);
811cb0ef41Sopenharmony_ci    } else {
821cb0ef41Sopenharmony_ci      static_assert(reactionType == kPromiseReactionReject);
831cb0ef41Sopenharmony_ci      return RejectPromiseReactionJob(
841cb0ef41Sopenharmony_ci          context, promiseOrCapability, argument, reactionType);
851cb0ef41Sopenharmony_ci    }
861cb0ef41Sopenharmony_ci  } else {
871cb0ef41Sopenharmony_ci    try {
881cb0ef41Sopenharmony_ci      const result =
891cb0ef41Sopenharmony_ci          Call(context, UnsafeCast<Callable>(handler), Undefined, argument);
901cb0ef41Sopenharmony_ci      if (promiseOrCapability == Undefined) {
911cb0ef41Sopenharmony_ci        // There's no [[Capability]] for this promise reaction job, which
921cb0ef41Sopenharmony_ci        // means that this is a specification-internal operation (aka
931cb0ef41Sopenharmony_ci        // await) where the result does not matter (see the specification
941cb0ef41Sopenharmony_ci        // change in https://github.com/tc39/ecma262/pull/1146 for
951cb0ef41Sopenharmony_ci        // details).
961cb0ef41Sopenharmony_ci        return Undefined;
971cb0ef41Sopenharmony_ci      } else {
981cb0ef41Sopenharmony_ci        return FuflfillPromiseReactionJob(
991cb0ef41Sopenharmony_ci            context, promiseOrCapability, result, reactionType);
1001cb0ef41Sopenharmony_ci      }
1011cb0ef41Sopenharmony_ci    } catch (e, _message) {
1021cb0ef41Sopenharmony_ci      return RejectPromiseReactionJob(
1031cb0ef41Sopenharmony_ci          context, promiseOrCapability, e, reactionType);
1041cb0ef41Sopenharmony_ci    }
1051cb0ef41Sopenharmony_ci  }
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_citransitioning builtin
1091cb0ef41Sopenharmony_ciPromiseFulfillReactionJob(implicit context: Context)(
1101cb0ef41Sopenharmony_ci    value: JSAny, handler: Callable|Undefined,
1111cb0ef41Sopenharmony_ci    promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny {
1121cb0ef41Sopenharmony_ci  return PromiseReactionJob(
1131cb0ef41Sopenharmony_ci      context, value, handler, promiseOrCapability, kPromiseReactionFulfill);
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_citransitioning builtin
1171cb0ef41Sopenharmony_ciPromiseRejectReactionJob(implicit context: Context)(
1181cb0ef41Sopenharmony_ci    reason: JSAny, handler: Callable|Undefined,
1191cb0ef41Sopenharmony_ci    promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny {
1201cb0ef41Sopenharmony_ci  return PromiseReactionJob(
1211cb0ef41Sopenharmony_ci      context, reason, handler, promiseOrCapability, kPromiseReactionReject);
1221cb0ef41Sopenharmony_ci}
1231cb0ef41Sopenharmony_ci}
124