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

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/promise-misc.tq')
-rw-r--r--deps/v8/src/builtins/promise-misc.tq431
1 files changed, 226 insertions, 205 deletions
diff --git a/deps/v8/src/builtins/promise-misc.tq b/deps/v8/src/builtins/promise-misc.tq
index 61461de29fe..7ed2f7909a8 100644
--- a/deps/v8/src/builtins/promise-misc.tq
+++ b/deps/v8/src/builtins/promise-misc.tq
@@ -6,246 +6,267 @@
#include 'src/builtins/builtins-promise-gen.h'
namespace runtime {
- extern transitioning runtime
- AllowDynamicFunction(implicit context: Context)(JSAny): JSAny;
+extern transitioning runtime
+AllowDynamicFunction(implicit context: Context)(JSAny): JSAny;
}
// Unsafe functions that should be used very carefully.
namespace promise_internal {
- extern macro PromiseBuiltinsAssembler::ZeroOutEmbedderOffsets(JSPromise):
- void;
+extern macro PromiseBuiltinsAssembler::ZeroOutEmbedderOffsets(JSPromise): void;
- extern macro PromiseBuiltinsAssembler::AllocateJSPromise(Context): HeapObject;
+extern macro PromiseBuiltinsAssembler::AllocateJSPromise(Context): HeapObject;
}
namespace promise {
- extern macro IsFunctionWithPrototypeSlotMap(Map): bool;
+extern macro IsFunctionWithPrototypeSlotMap(Map): bool;
- @export
- macro PromiseHasHandler(promise: JSPromise): bool {
- return promise.HasHandler();
- }
+@export
+macro PromiseHasHandler(promise: JSPromise): bool {
+ return promise.HasHandler();
+}
- @export
- macro PromiseInit(promise: JSPromise): void {
- assert(PromiseState::kPending == 0);
- promise.reactions_or_result = kZero;
- promise.flags = 0;
- promise_internal::ZeroOutEmbedderOffsets(promise);
- }
+@export
+macro PromiseInit(promise: JSPromise): void {
+ promise.reactions_or_result = kZero;
+ promise.flags = SmiTag(JSPromiseFlags{
+ status: PromiseState::kPending,
+ has_handler: false,
+ handled_hint: false,
+ async_task_id: 0
+ });
+ promise_internal::ZeroOutEmbedderOffsets(promise);
+}
- macro InnerNewJSPromise(implicit context: Context)(): JSPromise {
- const nativeContext = LoadNativeContext(context);
- const promiseFun = UnsafeCast<JSFunction>(
- nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
- assert(IsFunctionWithPrototypeSlotMap(promiseFun.map));
- const promiseMap = UnsafeCast<Map>(promiseFun.prototype_or_initial_map);
- const promiseHeapObject = promise_internal::AllocateJSPromise(context);
- * UnsafeConstCast(& promiseHeapObject.map) = promiseMap;
- const promise = UnsafeCast<JSPromise>(promiseHeapObject);
- promise.properties_or_hash = kEmptyFixedArray;
- promise.elements = kEmptyFixedArray;
- promise.reactions_or_result = kZero;
- promise.flags = 0;
- return promise;
- }
+macro InnerNewJSPromise(implicit context: Context)(): JSPromise {
+ const nativeContext = LoadNativeContext(context);
+ const promiseFun = UnsafeCast<JSFunction>(
+ nativeContext[NativeContextSlot::PROMISE_FUNCTION_INDEX]);
+ assert(IsFunctionWithPrototypeSlotMap(promiseFun.map));
+ const promiseMap = UnsafeCast<Map>(promiseFun.prototype_or_initial_map);
+ const promiseHeapObject = promise_internal::AllocateJSPromise(context);
+ * UnsafeConstCast(& promiseHeapObject.map) = promiseMap;
+ const promise = UnsafeCast<JSPromise>(promiseHeapObject);
+ promise.properties_or_hash = kEmptyFixedArray;
+ promise.elements = kEmptyFixedArray;
+ promise.reactions_or_result = kZero;
+ promise.flags = SmiTag(JSPromiseFlags{
+ status: PromiseState::kPending,
+ has_handler: false,
+ handled_hint: false,
+ async_task_id: 0
+ });
+ return promise;
+}
- macro NewPromiseFulfillReactionJobTask(implicit context: Context)(
- handlerContext: Context, argument: Object, handler: Callable|Undefined,
- promiseOrCapability: JSPromise|PromiseCapability|
- Undefined): PromiseFulfillReactionJobTask {
- const nativeContext = LoadNativeContext(handlerContext);
- return new PromiseFulfillReactionJobTask{
- map: PromiseFulfillReactionJobTaskMapConstant(),
- argument,
- context: handlerContext,
- handler,
- promise_or_capability: promiseOrCapability,
- continuation_preserved_embedder_data: nativeContext
- [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
- };
- }
+macro NewPromiseFulfillReactionJobTask(implicit context: Context)(
+ handlerContext: Context, argument: Object, handler: Callable|Undefined,
+ promiseOrCapability: JSPromise|PromiseCapability|
+ Undefined): PromiseFulfillReactionJobTask {
+ const nativeContext = LoadNativeContext(handlerContext);
+ return new PromiseFulfillReactionJobTask{
+ map: PromiseFulfillReactionJobTaskMapConstant(),
+ argument,
+ context: handlerContext,
+ handler,
+ promise_or_capability: promiseOrCapability,
+ continuation_preserved_embedder_data: nativeContext
+ [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
+ };
+}
- macro NewPromiseRejectReactionJobTask(implicit context: Context)(
- handlerContext: Context, argument: Object, handler: Callable|Undefined,
- promiseOrCapability: JSPromise|PromiseCapability|
- Undefined): PromiseRejectReactionJobTask {
- const nativeContext = LoadNativeContext(handlerContext);
- return new PromiseRejectReactionJobTask{
- map: PromiseRejectReactionJobTaskMapConstant(),
- argument,
- context: handlerContext,
- handler,
- promise_or_capability: promiseOrCapability,
- continuation_preserved_embedder_data: nativeContext
- [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
- };
- }
+macro NewPromiseRejectReactionJobTask(implicit context: Context)(
+ handlerContext: Context, argument: Object, handler: Callable|Undefined,
+ promiseOrCapability: JSPromise|PromiseCapability|
+ Undefined): PromiseRejectReactionJobTask {
+ const nativeContext = LoadNativeContext(handlerContext);
+ return new PromiseRejectReactionJobTask{
+ map: PromiseRejectReactionJobTaskMapConstant(),
+ argument,
+ context: handlerContext,
+ handler,
+ promise_or_capability: promiseOrCapability,
+ continuation_preserved_embedder_data: nativeContext
+ [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
+ };
+}
- // These allocate and initialize a promise with pending state and
- // undefined fields.
- //
- // This uses the given parent as the parent promise for the promise
- // init hook.
- @export
- transitioning macro NewJSPromise(implicit context: Context)(parent: Object):
- JSPromise {
- const instance = InnerNewJSPromise();
- PromiseInit(instance);
- if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
- runtime::PromiseHookInit(instance, parent);
- }
- return instance;
+// These allocate and initialize a promise with pending state and
+// undefined fields.
+//
+// This uses the given parent as the parent promise for the promise
+// init hook.
+@export
+transitioning macro NewJSPromise(implicit context: Context)(parent: Object):
+ JSPromise {
+ const instance = InnerNewJSPromise();
+ PromiseInit(instance);
+ if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
+ runtime::PromiseHookInit(instance, parent);
}
+ return instance;
+}
- // This uses undefined as the parent promise for the promise init
- // hook.
- @export
- transitioning macro NewJSPromise(implicit context: Context)(): JSPromise {
- return NewJSPromise(Undefined);
- }
+// This uses undefined as the parent promise for the promise init
+// hook.
+@export
+transitioning macro NewJSPromise(implicit context: Context)(): JSPromise {
+ return NewJSPromise(Undefined);
+}
- // This allocates and initializes a promise with the given state and
- // fields.
- @export
- transitioning macro NewJSPromise(implicit context: Context)(
- status: constexpr PromiseState, result: JSAny): JSPromise {
- assert(status != PromiseState::kPending);
- assert(kJSPromiseStatusShift == 0);
-
- const instance = InnerNewJSPromise();
- instance.reactions_or_result = result;
- instance.SetStatus(status);
- promise_internal::ZeroOutEmbedderOffsets(instance);
-
- if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
- runtime::PromiseHookInit(instance, Undefined);
- }
- return instance;
- }
+// This allocates and initializes a promise with the given state and
+// fields.
+@export
+transitioning macro NewJSPromise(implicit context: Context)(
+ status: constexpr PromiseState, result: JSAny): JSPromise {
+ assert(status != PromiseState::kPending);
- macro NewPromiseReaction(implicit context: Context)(
- handlerContext: Context, next: Zero|PromiseReaction,
- promiseOrCapability: JSPromise|PromiseCapability|Undefined,
- fulfillHandler: Callable|Undefined,
- rejectHandler: Callable|Undefined): PromiseReaction {
- const nativeContext = LoadNativeContext(handlerContext);
- return new PromiseReaction{
- map: PromiseReactionMapConstant(),
- next: next,
- reject_handler: rejectHandler,
- fulfill_handler: fulfillHandler,
- promise_or_capability: promiseOrCapability,
- continuation_preserved_embedder_data: nativeContext
- [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
- };
- }
+ const instance = InnerNewJSPromise();
+ instance.reactions_or_result = result;
+ instance.SetStatus(status);
+ promise_internal::ZeroOutEmbedderOffsets(instance);
- extern macro PromiseResolveThenableJobTaskMapConstant(): Map;
-
- macro NewPromiseResolveThenableJobTask(implicit context: Context)(
- promiseToResolve: JSPromise, then: JSReceiver, thenable: JSReceiver,
- thenContext: Context): PromiseResolveThenableJobTask {
- return new PromiseResolveThenableJobTask{
- map: PromiseResolveThenableJobTaskMapConstant(),
- context: thenContext,
- promise_to_resolve: promiseToResolve,
- then: then,
- thenable: thenable
- };
+ if (IsPromiseHookEnabledOrHasAsyncEventDelegate()) {
+ runtime::PromiseHookInit(instance, Undefined);
}
+ return instance;
+}
- struct InvokeThenOneArgFunctor {
- transitioning
- macro Call(
- nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
- _arg2: JSAny): JSAny {
- return Call(nativeContext, then, receiver, arg1);
- }
- }
+macro NewPromiseReaction(implicit context: Context)(
+ handlerContext: Context, next: Zero|PromiseReaction,
+ promiseOrCapability: JSPromise|PromiseCapability|Undefined,
+ fulfillHandler: Callable|Undefined,
+ rejectHandler: Callable|Undefined): PromiseReaction {
+ const nativeContext = LoadNativeContext(handlerContext);
+ return new PromiseReaction{
+ map: PromiseReactionMapConstant(),
+ next: next,
+ reject_handler: rejectHandler,
+ fulfill_handler: fulfillHandler,
+ promise_or_capability: promiseOrCapability,
+ continuation_preserved_embedder_data: nativeContext
+ [NativeContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX]
+ };
+}
- struct InvokeThenTwoArgFunctor {
- transitioning
- macro Call(
- nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
- arg2: JSAny): JSAny {
- return Call(nativeContext, then, receiver, arg1, arg2);
- }
- }
+extern macro PromiseResolveThenableJobTaskMapConstant(): Map;
- transitioning
- macro InvokeThen<F: type>(implicit context: Context)(
- nativeContext: NativeContext, receiver: JSAny, arg1: JSAny, arg2: JSAny,
- callFunctor: F): JSAny {
- // We can skip the "then" lookup on {receiver} if it's [[Prototype]]
- // is the (initial) Promise.prototype and the Promise#then protector
- // is intact, as that guards the lookup path for the "then" property
- // on JSPromise instances which have the (initial) %PromisePrototype%.
- if (!Is<Smi>(receiver) &&
- IsPromiseThenLookupChainIntact(
- nativeContext, UnsafeCast<HeapObject>(receiver).map)) {
- const then = UnsafeCast<JSAny>(
- nativeContext[NativeContextSlot::PROMISE_THEN_INDEX]);
- return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
- } else
- deferred {
- const then = UnsafeCast<JSAny>(GetProperty(receiver, kThenString));
- return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
- }
- }
+// https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob
+macro NewPromiseResolveThenableJobTask(implicit context: Context)(
+ promiseToResolve: JSPromise, thenable: JSReceiver,
+ then: Callable): PromiseResolveThenableJobTask {
+ // 2. Let getThenRealmResult be GetFunctionRealm(then).
+ // 3. If getThenRealmResult is a normal completion, then let thenRealm be
+ // getThenRealmResult.[[Value]].
+ // 4. Otherwise, let thenRealm be null.
+ //
+ // The only cases where |thenRealm| can be null is when |then| is a revoked
+ // Proxy object, which would throw when it is called anyway. So instead of
+ // setting the context to null as the spec does, we just use the current
+ // realm.
+ const thenContext: Context = ExtractHandlerContext(then);
+ const nativeContext = LoadNativeContext(thenContext);
+
+ // 1. Let job be a new Job abstract closure with no parameters that
+ // captures promiseToResolve, thenable, and then...
+ // 5. Return { [[Job]]: job, [[Realm]]: thenRealm }.
+ return new PromiseResolveThenableJobTask{
+ map: PromiseResolveThenableJobTaskMapConstant(),
+ context: nativeContext,
+ promise_to_resolve: promiseToResolve,
+ thenable,
+ then
+ };
+}
+struct InvokeThenOneArgFunctor {
transitioning
- macro InvokeThen(implicit context: Context)(
- nativeContext: NativeContext, receiver: JSAny, arg: JSAny): JSAny {
- return InvokeThen(
- nativeContext, receiver, arg, Undefined, InvokeThenOneArgFunctor{});
+ macro Call(
+ nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
+ _arg2: JSAny): JSAny {
+ return Call(nativeContext, then, receiver, arg1);
}
+}
+struct InvokeThenTwoArgFunctor {
transitioning
- macro InvokeThen(implicit context: Context)(
- nativeContext: NativeContext, receiver: JSAny, arg1: JSAny,
+ macro Call(
+ nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny,
arg2: JSAny): JSAny {
- return InvokeThen(
- nativeContext, receiver, arg1, arg2, InvokeThenTwoArgFunctor{});
+ return Call(nativeContext, then, receiver, arg1, arg2);
}
+}
- transitioning
- macro BranchIfAccessCheckFailed(implicit context: Context)(
- nativeContext: NativeContext, promiseConstructor: JSAny,
- executor: JSAny): void labels IfNoAccess {
- try {
- // If executor is a bound function, load the bound function until we've
- // reached an actual function.
- let foundExecutor = executor;
- while (true) {
- typeswitch (foundExecutor) {
- case (f: JSFunction): {
- // Load the context from the function and compare it to the Promise
- // constructor's context. If they match, everything is fine,
- // otherwise, bail out to the runtime.
- const functionContext = f.context;
- const nativeFunctionContext = LoadNativeContext(functionContext);
- if (TaggedEqual(nativeContext, nativeFunctionContext)) {
- goto HasAccess;
- } else {
- goto CallRuntime;
- }
- }
- case (b: JSBoundFunction): {
- foundExecutor = b.bound_target_function;
- }
- case (Object): {
+transitioning
+macro InvokeThen<F: type>(implicit context: Context)(
+ nativeContext: NativeContext, receiver: JSAny, arg1: JSAny, arg2: JSAny,
+ callFunctor: F): JSAny {
+ // We can skip the "then" lookup on {receiver} if it's [[Prototype]]
+ // is the (initial) Promise.prototype and the Promise#then protector
+ // is intact, as that guards the lookup path for the "then" property
+ // on JSPromise instances which have the (initial) %PromisePrototype%.
+ if (!Is<Smi>(receiver) &&
+ IsPromiseThenLookupChainIntact(
+ nativeContext, UnsafeCast<HeapObject>(receiver).map)) {
+ const then =
+ UnsafeCast<JSAny>(nativeContext[NativeContextSlot::PROMISE_THEN_INDEX]);
+ return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
+ } else
+ deferred {
+ const then = UnsafeCast<JSAny>(GetProperty(receiver, kThenString));
+ return callFunctor.Call(nativeContext, then, receiver, arg1, arg2);
+ }
+}
+
+transitioning
+macro InvokeThen(implicit context: Context)(
+ nativeContext: NativeContext, receiver: JSAny, arg: JSAny): JSAny {
+ return InvokeThen(
+ nativeContext, receiver, arg, Undefined, InvokeThenOneArgFunctor{});
+}
+
+transitioning
+macro InvokeThen(implicit context: Context)(
+ nativeContext: NativeContext, receiver: JSAny, arg1: JSAny,
+ arg2: JSAny): JSAny {
+ return InvokeThen(
+ nativeContext, receiver, arg1, arg2, InvokeThenTwoArgFunctor{});
+}
+
+transitioning
+macro BranchIfAccessCheckFailed(implicit context: Context)(
+ nativeContext: NativeContext, promiseConstructor: JSAny,
+ executor: JSAny): void labels IfNoAccess {
+ try {
+ // If executor is a bound function, load the bound function until we've
+ // reached an actual function.
+ let foundExecutor = executor;
+ while (true) {
+ typeswitch (foundExecutor) {
+ case (f: JSFunction): {
+ // Load the context from the function and compare it to the Promise
+ // constructor's context. If they match, everything is fine,
+ // otherwise, bail out to the runtime.
+ const functionContext = f.context;
+ const nativeFunctionContext = LoadNativeContext(functionContext);
+ if (TaggedEqual(nativeContext, nativeFunctionContext)) {
+ goto HasAccess;
+ } else {
goto CallRuntime;
}
}
+ case (b: JSBoundFunction): {
+ foundExecutor = b.bound_target_function;
+ }
+ case (Object): {
+ goto CallRuntime;
+ }
}
}
- label CallRuntime deferred {
- const result = runtime::AllowDynamicFunction(promiseConstructor);
- if (result != True) {
- goto IfNoAccess;
- }
+ } label CallRuntime deferred {
+ const result = runtime::AllowDynamicFunction(promiseConstructor);
+ if (result != True) {
+ goto IfNoAccess;
}
- label HasAccess {}
- }
+ } label HasAccess {}
+}
}