promise-reaction-job.tq 4.54 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include 'src/builtins/builtins-promise-gen.h'

namespace promise {

9 10 11 12 13 14
transitioning
macro RejectPromiseReactionJob(
    context: Context,
    promiseOrCapability: JSPromise|PromiseCapability|Undefined, reason: JSAny,
    reactionType: constexpr PromiseReactionType): JSAny {
  if constexpr (reactionType == kPromiseReactionReject) {
15 16 17
    typeswitch (promiseOrCapability) {
      case (promise: JSPromise): {
        // For fast native promises we can skip the indirection via the
18
        // promiseCapability.[[Reject]] function and run the resolve logic
19
        // directly from here.
20
        return RejectPromise(promise, reason, False);
21 22 23 24 25
      }
      case (Undefined): {
        return Undefined;
      }
      case (capability: PromiseCapability): {
26
        // In the general case we need to call the (user provided)
27 28 29
        // promiseCapability.[[Reject]] function.
        const reject = UnsafeCast<Callable>(capability.reject);
        return Call(context, reject, Undefined, reason);
30
      }
31
    }
32
  } else {
33
    static_assert(reactionType == kPromiseReactionFulfill);
34 35 36 37 38
    // We have to call out to the dedicated PromiseRejectReactionJob
    // builtin here, instead of just doing the work inline, as otherwise
    // the catch predictions in the debugger will be wrong, which just
    // walks the stack and checks for certain builtins.
    return PromiseRejectReactionJob(reason, Undefined, promiseOrCapability);
39
  }
40
}
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
transitioning
macro FuflfillPromiseReactionJob(
    context: Context,
    promiseOrCapability: JSPromise|PromiseCapability|Undefined, result: JSAny,
    reactionType: constexpr PromiseReactionType): JSAny {
  typeswitch (promiseOrCapability) {
    case (promise: JSPromise): {
      // For fast native promises we can skip the indirection via the
      // promiseCapability.[[Resolve]] function and run the resolve logic
      // directly from here.
      return ResolvePromise(context, promise, result);
    }
    case (Undefined): {
      return Undefined;
    }
    case (capability: PromiseCapability): {
      // In the general case we need to call the (user provided)
      // promiseCapability.[[Resolve]] function.
      const resolve = UnsafeCast<Callable>(capability.resolve);
61
      try {
62
        return Call(context, resolve, Undefined, result);
63
      } catch (e, _message) {
64 65 66 67 68
        return RejectPromiseReactionJob(
            context, promiseOrCapability, e, reactionType);
      }
    }
  }
69
}
70

71 72 73 74 75 76 77 78 79 80 81
// https://tc39.es/ecma262/#sec-promisereactionjob
transitioning
macro PromiseReactionJob(
    context: Context, argument: JSAny, handler: Callable|Undefined,
    promiseOrCapability: JSPromise|PromiseCapability|Undefined,
    reactionType: constexpr PromiseReactionType): JSAny {
  if (handler == Undefined) {
    if constexpr (reactionType == kPromiseReactionFulfill) {
      return FuflfillPromiseReactionJob(
          context, promiseOrCapability, argument, reactionType);
    } else {
82
      static_assert(reactionType == kPromiseReactionReject);
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
      return RejectPromiseReactionJob(
          context, promiseOrCapability, argument, reactionType);
    }
  } else {
    try {
      const result =
          Call(context, UnsafeCast<Callable>(handler), Undefined, argument);
      if (promiseOrCapability == Undefined) {
        // There's no [[Capability]] for this promise reaction job, which
        // means that this is a specification-internal operation (aka
        // await) where the result does not matter (see the specification
        // change in https://github.com/tc39/ecma262/pull/1146 for
        // details).
        return Undefined;
      } else {
        return FuflfillPromiseReactionJob(
            context, promiseOrCapability, result, reactionType);
      }
101
    } catch (e, _message) {
102 103 104
      return RejectPromiseReactionJob(
          context, promiseOrCapability, e, reactionType);
    }
105
  }
106
}
107

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
transitioning builtin
PromiseFulfillReactionJob(implicit context: Context)(
    value: JSAny, handler: Callable|Undefined,
    promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny {
  return PromiseReactionJob(
      context, value, handler, promiseOrCapability, kPromiseReactionFulfill);
}

transitioning builtin
PromiseRejectReactionJob(implicit context: Context)(
    reason: JSAny, handler: Callable|Undefined,
    promiseOrCapability: JSPromise|PromiseCapability|Undefined): JSAny {
  return PromiseReactionJob(
      context, reason, handler, promiseOrCapability, kPromiseReactionReject);
}
123
}