tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Promise.h (11747B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef builtin_Promise_h
      8 #define builtin_Promise_h
      9 
     10 #include "jstypes.h"  // JS_PUBLIC_API
     11 
     12 #include "js/RootingAPI.h"  // JS::{,Mutable}Handle
     13 #include "js/TypeDecls.h"   // JS::HandleObjectVector
     14 
     15 struct JS_PUBLIC_API JSContext;
     16 class JS_PUBLIC_API JSObject;
     17 
     18 namespace JS {
     19 class CallArgs;
     20 class Value;
     21 }  // namespace JS
     22 
     23 namespace js {
     24 
     25 class AsyncFunctionGeneratorObject;
     26 class AsyncGeneratorObject;
     27 class PromiseObject;
     28 class SavedFrame;
     29 
     30 enum class CompletionKind : uint8_t;
     31 
     32 enum class PromiseHandler : uint32_t {
     33  Identity = 0,
     34  Thrower,
     35 
     36  // ES2022 draft rev d03c1ec6e235a5180fa772b6178727c17974cb14
     37  //
     38  // Await in async function
     39  // https://tc39.es/ecma262/#await
     40  //
     41  // Step 3. fulfilledClosure Abstract Closure.
     42  // Step 5. rejectedClosure Abstract Closure.
     43  AsyncFunctionAwaitedFulfilled,
     44  AsyncFunctionAwaitedRejected,
     45 
     46  // Await in async generator
     47  // https://tc39.es/ecma262/#await
     48  //
     49  // Step 3. fulfilledClosure Abstract Closure.
     50  // Step 5. rejectedClosure Abstract Closure.
     51  AsyncGeneratorAwaitedFulfilled,
     52  AsyncGeneratorAwaitedRejected,
     53 
     54  // AsyncGeneratorAwaitReturn ( generator )
     55  // https://tc39.es/ecma262/#sec-asyncgeneratorawaitreturn
     56  //
     57  // Step 7. fulfilledClosure Abstract Closure.
     58  // Step 9. rejectedClosure Abstract Closure.
     59  AsyncGeneratorAwaitReturnFulfilled,
     60  AsyncGeneratorAwaitReturnRejected,
     61 
     62  // AsyncGeneratorUnwrapYieldResumption
     63  // https://tc39.es/ecma262/#sec-asyncgeneratorunwrapyieldresumption
     64  //
     65  // Steps 3-5 for awaited.[[Type]] handling.
     66  AsyncGeneratorYieldReturnAwaitedFulfilled,
     67  AsyncGeneratorYieldReturnAwaitedRejected,
     68 
     69  // AsyncFromSyncIteratorContinuation ( result, promiseCapability )
     70  // https://tc39.es/ecma262/#sec-asyncfromsynciteratorcontinuation
     71  //
     72  // Step 9. unwrap Abstract Closure.
     73  AsyncFromSyncIteratorValueUnwrapDone,
     74  AsyncFromSyncIteratorValueUnwrapNotDone,
     75 
     76  // AsyncFromSyncIteratorContinuation ( result, promiseCapability )
     77  // https://tc39.es/ecma262/#sec-asyncfromsynciteratorcontinuation
     78  //
     79  // Step 13.a. closeIterator Abstract Closure.
     80  AsyncFromSyncIteratorClose,
     81 
     82 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     83  // Explicit Resource Management Proposal
     84  // 27.1.3.1 %AsyncIteratorPrototype% [ @@asyncDispose ] ( )
     85  // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25asynciteratorprototype%25-%40%40asyncdispose
     86  //
     87  // Step 6.e. unwrap Abstract Closure
     88  AsyncIteratorDisposeAwaitFulfilled,
     89 #endif
     90 
     91  // One past the maximum allowed PromiseHandler value.
     92  Limit
     93 };
     94 
     95 // Promise.prototype.then.
     96 extern bool Promise_then(JSContext* cx, unsigned argc, JS::Value* vp);
     97 
     98 // Promise[Symbol.species].
     99 extern bool Promise_static_species(JSContext* cx, unsigned argc, JS::Value* vp);
    100 
    101 // Promise.resolve.
    102 extern bool Promise_static_resolve(JSContext* cx, unsigned argc, JS::Value* vp);
    103 
    104 /**
    105 * Unforgeable version of the JS builtin Promise.all.
    106 *
    107 * Takes a HandleValueVector of Promise objects and returns a promise that's
    108 * resolved with an array of resolution values when all those promises have
    109 * been resolved, or rejected with the rejection value of the first rejected
    110 * promise.
    111 *
    112 * Asserts that all objects in the `promises` vector are, maybe wrapped,
    113 * instances of `Promise` or a subclass of `Promise`.
    114 */
    115 [[nodiscard]] JSObject* GetWaitForAllPromise(JSContext* cx,
    116                                             JS::HandleObjectVector promises);
    117 
    118 /**
    119 * Enqueues resolve/reject reactions in the given Promise's reactions lists
    120 * as though by calling the original value of Promise.prototype.then, and
    121 * without regard to any Promise subclassing used in `promiseObj` itself.
    122 */
    123 [[nodiscard]] PromiseObject* OriginalPromiseThen(
    124    JSContext* cx, JS::Handle<JSObject*> promiseObj,
    125    JS::Handle<JSObject*> onFulfilled, JS::Handle<JSObject*> onRejected);
    126 
    127 enum class UnhandledRejectionBehavior { Ignore, Report };
    128 
    129 /**
    130 * React to[0] `unwrappedPromise` (which may not be from the current realm) as
    131 * if by using a fresh promise created for the provided nullable fulfill/reject
    132 * IsCallable objects.
    133 *
    134 * However, no dependent Promise will be created, and mucking with `Promise`,
    135 * `Promise.prototype.then`, and `Promise[Symbol.species]` will not alter this
    136 * function's behavior.
    137 *
    138 * If `unwrappedPromise` rejects and `onRejected_` is null, handling is
    139 * determined by `behavior`.  If `behavior == Report`, a fresh Promise will be
    140 * constructed and rejected on the fly (and thus will be reported as unhandled).
    141 * But if `behavior == Ignore`, the rejection is ignored and is not reported as
    142 * unhandled.
    143 *
    144 * Note: Reactions pushed using this function contain a null `promise` field.
    145 * That field is only ever used by devtools, which have to treat these reactions
    146 * specially.
    147 *
    148 * 0. The sense of "react" here is the sense of the term as defined by Web IDL:
    149 *    https://heycam.github.io/webidl/#dfn-perform-steps-once-promise-is-settled
    150 */
    151 [[nodiscard]] extern bool ReactToUnwrappedPromise(
    152    JSContext* cx, JS::Handle<PromiseObject*> unwrappedPromise,
    153    JS::Handle<JSObject*> onFulfilled_, JS::Handle<JSObject*> onRejected_,
    154    UnhandledRejectionBehavior behavior);
    155 
    156 /**
    157 * PromiseResolve ( C, x )
    158 *
    159 * The abstract operation PromiseResolve, given a constructor and a value,
    160 * returns a new promise resolved with that value.
    161 */
    162 [[nodiscard]] JSObject* PromiseResolve(JSContext* cx,
    163                                       JS::Handle<JSObject*> constructor,
    164                                       JS::Handle<JS::Value> value);
    165 
    166 /**
    167 * Reject |promise| with the value of the current pending exception.
    168 *
    169 * |promise| must be from the current realm.  Callers must enter the realm of
    170 * |promise| if they are not already in it.
    171 */
    172 [[nodiscard]] bool RejectPromiseWithPendingError(
    173    JSContext* cx, JS::Handle<PromiseObject*> promise);
    174 
    175 /**
    176 * Create the promise object which will be used as the return value of an async
    177 * function.
    178 */
    179 [[nodiscard]] PromiseObject* CreatePromiseObjectForAsync(JSContext* cx);
    180 
    181 /**
    182 * Returns true if the given object is a promise created by
    183 * either CreatePromiseObjectForAsync function or async generator's method.
    184 */
    185 [[nodiscard]] bool IsPromiseForAsyncFunctionOrGenerator(JSObject* promise);
    186 
    187 [[nodiscard]] bool AsyncFunctionReturned(
    188    JSContext* cx, JS::Handle<PromiseObject*> resultPromise,
    189    JS::Handle<JS::Value> value);
    190 
    191 [[nodiscard]] bool AsyncFunctionThrown(
    192    JSContext* cx, JS::Handle<PromiseObject*> resultPromise,
    193    JS::Handle<JS::Value> reason,
    194    JS::Handle<SavedFrame*> unwrappedRejectionStack = nullptr);
    195 
    196 // Start awaiting `value` in an async function (, but doesn't suspend the
    197 // async function's execution!). Returns the async function's result promise.
    198 [[nodiscard]] JSObject* AsyncFunctionAwait(
    199    JSContext* cx, JS::Handle<AsyncFunctionGeneratorObject*> genObj,
    200    JS::Handle<JS::Value> value);
    201 
    202 // If the await operation can be skipped and the resolution value for `val` can
    203 // be acquired, stored the resolved value to `resolved` and `true` to
    204 // `*canSkip`.  Otherwise, stores `false` to `*canSkip`.
    205 [[nodiscard]] bool CanSkipAwait(JSContext* cx, JS::Handle<JS::Value> val,
    206                                bool* canSkip);
    207 [[nodiscard]] bool ExtractAwaitValue(JSContext* cx, JS::Handle<JS::Value> val,
    208                                     JS::MutableHandle<JS::Value> resolved);
    209 
    210 bool AsyncFromSyncIteratorMethod(JSContext* cx, JS::CallArgs& args,
    211                                 CompletionKind completionKind);
    212 
    213 // Callback for describing promise reaction records, for use with
    214 // PromiseObject::getReactionRecords.
    215 struct PromiseReactionRecordBuilder {
    216  // A reaction record created by a call to 'then' or 'catch', with functions to
    217  // call on resolution or rejection, and the promise that will be settled
    218  // according to the result of calling them.
    219  //
    220  // Note that resolve, reject, and result may not be same-compartment with cx,
    221  // or with the promise we're inspecting. This function presents the values
    222  // exactly as they appear in the reaction record. They may also be wrapped or
    223  // unwrapped.
    224  //
    225  // Some reaction records refer to internal resolution or rejection functions
    226  // that are not naturally represented as debuggee JavaScript functions. In
    227  // this case, resolve and reject may be nullptr.
    228  [[nodiscard]] virtual bool then(JSContext* cx, JS::Handle<JSObject*> resolve,
    229                                  JS::Handle<JSObject*> reject,
    230                                  JS::Handle<JSObject*> result) = 0;
    231 
    232  // A reaction record created when one native promise is resolved to another.
    233  // The 'promise' argument is the promise that will be settled in the same way
    234  // the promise this reaction record is attached to is settled.
    235  //
    236  // Note that promise may not be same-compartment with cx. This function
    237  // presents the promise exactly as it appears in the reaction record.
    238  [[nodiscard]] virtual bool direct(
    239      JSContext* cx, JS::Handle<PromiseObject*> unwrappedPromise) = 0;
    240 
    241  // A reaction record that resumes an asynchronous function suspended at an
    242  // await expression. The 'generator' argument is the generator object
    243  // representing the call.
    244  //
    245  // Note that generator may not be same-compartment with cx. This function
    246  // presents the generator exactly as it appears in the reaction record.
    247  [[nodiscard]] virtual bool asyncFunction(
    248      JSContext* cx,
    249      JS::Handle<AsyncFunctionGeneratorObject*> unwrappedGenerator) = 0;
    250 
    251  // A reaction record that resumes an asynchronous generator suspended at an
    252  // await expression. The 'generator' argument is the generator object
    253  // representing the call.
    254  //
    255  // Note that generator may not be same-compartment with cx. This function
    256  // presents the generator exactly as it appears in the reaction record.
    257  [[nodiscard]] virtual bool asyncGenerator(
    258      JSContext* cx, JS::Handle<AsyncGeneratorObject*> unwrappedGenerator) = 0;
    259 };
    260 
    261 [[nodiscard]] PromiseObject* CreatePromiseObjectForAsyncGenerator(
    262    JSContext* cx);
    263 
    264 // This implements "Let promiseCapability be ! NewPromiseCapability(%Promise%)".
    265 [[nodiscard]] PromiseObject* CreatePromiseObjectWithoutResolutionFunctions(
    266    JSContext* cx);
    267 
    268 [[nodiscard]] bool ResolvePromiseInternal(JSContext* cx,
    269                                          JS::Handle<JSObject*> promise,
    270                                          JS::Handle<JS::Value> resolutionVal);
    271 [[nodiscard]] bool RejectPromiseInternal(
    272    JSContext* cx, JS::Handle<PromiseObject*> promise,
    273    JS::Handle<JS::Value> reason,
    274    JS::Handle<SavedFrame*> unwrappedRejectionStack = nullptr);
    275 
    276 [[nodiscard]] bool InternalAsyncGeneratorAwait(
    277    JSContext* cx, JS::Handle<AsyncGeneratorObject*> generator,
    278    JS::Handle<JS::Value> value, PromiseHandler onFulfilled,
    279    PromiseHandler onRejected);
    280 
    281 bool IsPromiseWithDefaultResolvingFunction(PromiseObject* promise);
    282 void SetAlreadyResolvedPromiseWithDefaultResolvingFunction(
    283    PromiseObject* promise);
    284 
    285 bool IsPromiseConstructor(const JSObject* obj);
    286 
    287 bool AbruptRejectPromise(JSContext* cx, JS::CallArgs& args,
    288                         JS::Handle<JSObject*> promiseObj,
    289                         JS::Handle<JSObject*> reject);
    290 
    291 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
    292 [[nodiscard]] bool InternalAsyncIteratorDisposeAwait(
    293    JSContext* cx, JS::Handle<JS::Value> value,
    294    JS::Handle<JSObject*> resultPromise);
    295 #endif
    296 }  // namespace js
    297 
    298 #endif  // builtin_Promise_h