Welcome to mirror list, hosted at ThFree Co, Russian Federation.

promise-jobs.tq « builtins « src « v8 « deps - github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6c64baf22d19ba881285a1e434b3c76c89ee6b86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 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.h'

// https://tc39.es/ecma262/#sec-promise-jobs
namespace promise {
extern macro IsJSPromiseMap(Map): bool;

// https://tc39.es/ecma262/#sec-promiseresolvethenablejob
transitioning builtin
PromiseResolveThenableJob(implicit context: Context)(
    promiseToResolve: JSPromise, thenable: JSReceiver, then: JSAny): JSAny {
  // We can use a simple optimization here if we know that {then} is the
  // initial Promise.prototype.then method, and {thenable} is a JSPromise
  // whose
  // @@species lookup chain is intact: We can connect {thenable} and
  // {promise_to_resolve} directly in that case and avoid the allocation of a
  // temporary JSPromise and the closures plus context.
  //
  // We take the generic (slow-)path if a PromiseHook is enabled or the
  // debugger is active, to make sure we expose spec compliant behavior.
  const nativeContext = LoadNativeContext(context);
  const promiseThen = nativeContext[NativeContextSlot::PROMISE_THEN_INDEX];
  const thenableMap = thenable.map;
  if (TaggedEqual(then, promiseThen) && IsJSPromiseMap(thenableMap) &&
      !IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() &&
      IsPromiseSpeciesLookupChainIntact(nativeContext, thenableMap)) {
    // We know that the {thenable} is a JSPromise, which doesn't require
    // any special treatment and that {then} corresponds to the initial
    // Promise.prototype.then method. So instead of allocating a temporary
    // JSPromise to connect the {thenable} with the {promise_to_resolve},
    // we can directly schedule the {promise_to_resolve} with default
    // handlers onto the {thenable} promise. This does not only save the
    // JSPromise allocation, but also avoids the allocation of the two
    // resolving closures and the shared context.
    //
    // What happens normally in this case is
    //
    //   resolve, reject = CreateResolvingFunctions(promise_to_resolve)
    //   result_capability = NewPromiseCapability(%Promise%)
    //   PerformPromiseThen(thenable, resolve, reject, result_capability)
    //
    // which means that PerformPromiseThen will either schedule a new
    // PromiseReaction with resolve and reject or a PromiseReactionJob
    // with resolve or reject based on the state of {thenable}. And
    // resolve or reject will just invoke the default [[Resolve]] or
    // [[Reject]] functions on the {promise_to_resolve}.
    //
    // This is the same as just doing
    //
    //   PerformPromiseThen(thenable, undefined, undefined,
    //   promise_to_resolve)
    //
    // which performs exactly the same (observable) steps.
    return PerformPromiseThen(
        UnsafeCast<JSPromise>(thenable), UndefinedConstant(),
        UndefinedConstant(), promiseToResolve);
  } else {
    const funcs =
        CreatePromiseResolvingFunctions(promiseToResolve, False, nativeContext);
    const resolve = funcs.resolve;
    const reject = funcs.reject;
    try {
      return Call(
          context, UnsafeCast<Callable>(then), thenable, resolve, reject);
    } catch (e) {
      return Call(context, UnsafeCast<Callable>(reject), Undefined, e);
    }
  }
}
}