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.h' 61cb0ef41Sopenharmony_ci#include 'src/builtins/builtins-promise-gen.h' 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_cinamespace runtime { 91cb0ef41Sopenharmony_ciextern transitioning runtime 101cb0ef41Sopenharmony_ciAllowDynamicFunction(implicit context: Context)(JSAny): JSAny; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciextern transitioning runtime ThrowNoAccess(implicit context: Context)(): never; 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciextern transitioning runtime 151cb0ef41Sopenharmony_ciReportMessageFromMicrotask(implicit context: Context)(JSAny): JSAny; 161cb0ef41Sopenharmony_ci} 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci// Unsafe functions that should be used very carefully. 191cb0ef41Sopenharmony_cinamespace promise_internal { 201cb0ef41Sopenharmony_ciextern macro PromiseBuiltinsAssembler::ZeroOutEmbedderOffsets(JSPromise): void; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ciextern macro PromiseBuiltinsAssembler::AllocateJSPromise(Context): HeapObject; 231cb0ef41Sopenharmony_ci} 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciextern macro 261cb0ef41Sopenharmony_ciPromiseBuiltinsAssembler::IsContextPromiseHookEnabled(uint32): bool; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciextern macro 291cb0ef41Sopenharmony_ciPromiseBuiltinsAssembler::IsIsolatePromiseHookEnabled(uint32): bool; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciextern macro 321cb0ef41Sopenharmony_ciPromiseBuiltinsAssembler::PromiseHookFlags(): uint32; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_cinamespace promise { 351cb0ef41Sopenharmony_ciextern macro IsFunctionWithPrototypeSlotMap(Map): bool; 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci@export 381cb0ef41Sopenharmony_cimacro PromiseHasHandler(promise: JSPromise): bool { 391cb0ef41Sopenharmony_ci return promise.HasHandler(); 401cb0ef41Sopenharmony_ci} 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci@export 431cb0ef41Sopenharmony_cimacro PromiseInit(promise: JSPromise): void { 441cb0ef41Sopenharmony_ci promise.reactions_or_result = kZero; 451cb0ef41Sopenharmony_ci promise.flags = SmiTag(JSPromiseFlags{ 461cb0ef41Sopenharmony_ci status: PromiseState::kPending, 471cb0ef41Sopenharmony_ci has_handler: false, 481cb0ef41Sopenharmony_ci handled_hint: false, 491cb0ef41Sopenharmony_ci is_silent: false, 501cb0ef41Sopenharmony_ci async_task_id: 0 511cb0ef41Sopenharmony_ci }); 521cb0ef41Sopenharmony_ci promise_internal::ZeroOutEmbedderOffsets(promise); 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cimacro InnerNewJSPromise(implicit context: Context)(): JSPromise { 561cb0ef41Sopenharmony_ci const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX); 571cb0ef41Sopenharmony_ci dcheck(IsFunctionWithPrototypeSlotMap(promiseFun.map)); 581cb0ef41Sopenharmony_ci const promiseMap = UnsafeCast<Map>(promiseFun.prototype_or_initial_map); 591cb0ef41Sopenharmony_ci const promiseHeapObject = promise_internal::AllocateJSPromise(context); 601cb0ef41Sopenharmony_ci *UnsafeConstCast(&promiseHeapObject.map) = promiseMap; 611cb0ef41Sopenharmony_ci const promise = UnsafeCast<JSPromise>(promiseHeapObject); 621cb0ef41Sopenharmony_ci promise.properties_or_hash = kEmptyFixedArray; 631cb0ef41Sopenharmony_ci promise.elements = kEmptyFixedArray; 641cb0ef41Sopenharmony_ci promise.reactions_or_result = kZero; 651cb0ef41Sopenharmony_ci promise.flags = SmiTag(JSPromiseFlags{ 661cb0ef41Sopenharmony_ci status: PromiseState::kPending, 671cb0ef41Sopenharmony_ci has_handler: false, 681cb0ef41Sopenharmony_ci handled_hint: false, 691cb0ef41Sopenharmony_ci is_silent: false, 701cb0ef41Sopenharmony_ci async_task_id: 0 711cb0ef41Sopenharmony_ci }); 721cb0ef41Sopenharmony_ci return promise; 731cb0ef41Sopenharmony_ci} 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_cimacro NewPromiseFulfillReactionJobTask(implicit context: Context)( 761cb0ef41Sopenharmony_ci handlerContext: Context, argument: Object, handler: Callable|Undefined, 771cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability| 781cb0ef41Sopenharmony_ci Undefined): PromiseFulfillReactionJobTask { 791cb0ef41Sopenharmony_ci const nativeContext = LoadNativeContext(handlerContext); 801cb0ef41Sopenharmony_ci return new PromiseFulfillReactionJobTask{ 811cb0ef41Sopenharmony_ci map: PromiseFulfillReactionJobTaskMapConstant(), 821cb0ef41Sopenharmony_ci argument, 831cb0ef41Sopenharmony_ci context: handlerContext, 841cb0ef41Sopenharmony_ci handler, 851cb0ef41Sopenharmony_ci promise_or_capability: promiseOrCapability, 861cb0ef41Sopenharmony_ci continuation_preserved_embedder_data: 871cb0ef41Sopenharmony_ci *ContextSlot( 881cb0ef41Sopenharmony_ci nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX) 891cb0ef41Sopenharmony_ci }; 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_cimacro NewPromiseRejectReactionJobTask(implicit context: Context)( 931cb0ef41Sopenharmony_ci handlerContext: Context, argument: Object, handler: Callable|Undefined, 941cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability| 951cb0ef41Sopenharmony_ci Undefined): PromiseRejectReactionJobTask { 961cb0ef41Sopenharmony_ci const nativeContext = LoadNativeContext(handlerContext); 971cb0ef41Sopenharmony_ci return new PromiseRejectReactionJobTask{ 981cb0ef41Sopenharmony_ci map: PromiseRejectReactionJobTaskMapConstant(), 991cb0ef41Sopenharmony_ci argument, 1001cb0ef41Sopenharmony_ci context: handlerContext, 1011cb0ef41Sopenharmony_ci handler, 1021cb0ef41Sopenharmony_ci promise_or_capability: promiseOrCapability, 1031cb0ef41Sopenharmony_ci continuation_preserved_embedder_data: 1041cb0ef41Sopenharmony_ci *ContextSlot( 1051cb0ef41Sopenharmony_ci nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX) 1061cb0ef41Sopenharmony_ci }; 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci@export 1101cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookInit(implicit context: Context)( 1111cb0ef41Sopenharmony_ci promise: JSPromise, parent: Object): void { 1121cb0ef41Sopenharmony_ci const maybeHook = *NativeContextSlot( 1131cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_INIT_FUNCTION_INDEX); 1141cb0ef41Sopenharmony_ci const hook = Cast<Callable>(maybeHook) otherwise return; 1151cb0ef41Sopenharmony_ci const parentObject = Is<JSPromise>(parent) ? Cast<JSPromise>(parent) 1161cb0ef41Sopenharmony_ci otherwise unreachable: Undefined; 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci try { 1191cb0ef41Sopenharmony_ci Call(context, hook, Undefined, promise, parentObject); 1201cb0ef41Sopenharmony_ci } catch (e, _message) { 1211cb0ef41Sopenharmony_ci runtime::ReportMessageFromMicrotask(e); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci} 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci@export 1261cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookResolve(implicit context: Context)( 1271cb0ef41Sopenharmony_ci promise: JSPromise): void { 1281cb0ef41Sopenharmony_ci // Use potentially unused variables. 1291cb0ef41Sopenharmony_ci const _unusedPromise = promise; 1301cb0ef41Sopenharmony_ci @if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) { 1311cb0ef41Sopenharmony_ci RunContextPromiseHook( 1321cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_RESOLVE_FUNCTION_INDEX, promise, 1331cb0ef41Sopenharmony_ci PromiseHookFlags()); 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci} 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci@export 1381cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookResolve(implicit context: Context)( 1391cb0ef41Sopenharmony_ci promise: JSPromise, flags: uint32): void { 1401cb0ef41Sopenharmony_ci RunContextPromiseHook( 1411cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_RESOLVE_FUNCTION_INDEX, promise, flags); 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci@export 1451cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookBefore(implicit context: Context)( 1461cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined): void { 1471cb0ef41Sopenharmony_ci // Use potentially unused variables. 1481cb0ef41Sopenharmony_ci const _unusedPromiseOrCapability = promiseOrCapability; 1491cb0ef41Sopenharmony_ci @if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) { 1501cb0ef41Sopenharmony_ci RunContextPromiseHook( 1511cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_BEFORE_FUNCTION_INDEX, promiseOrCapability, 1521cb0ef41Sopenharmony_ci PromiseHookFlags()); 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci@export 1571cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookBefore(implicit context: Context)( 1581cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined, flags: uint32): 1591cb0ef41Sopenharmony_ci void { 1601cb0ef41Sopenharmony_ci RunContextPromiseHook( 1611cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_BEFORE_FUNCTION_INDEX, promiseOrCapability, 1621cb0ef41Sopenharmony_ci flags); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci@export 1661cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookAfter(implicit context: Context)( 1671cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined): void { 1681cb0ef41Sopenharmony_ci // Use potentially unused variables. 1691cb0ef41Sopenharmony_ci const _unusedPromiseOrCapability = promiseOrCapability; 1701cb0ef41Sopenharmony_ci @if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) { 1711cb0ef41Sopenharmony_ci RunContextPromiseHook( 1721cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_AFTER_FUNCTION_INDEX, promiseOrCapability, 1731cb0ef41Sopenharmony_ci PromiseHookFlags()); 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci} 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci@export 1781cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHookAfter(implicit context: Context)( 1791cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined, flags: uint32): 1801cb0ef41Sopenharmony_ci void { 1811cb0ef41Sopenharmony_ci RunContextPromiseHook( 1821cb0ef41Sopenharmony_ci ContextSlot::PROMISE_HOOK_AFTER_FUNCTION_INDEX, promiseOrCapability, 1831cb0ef41Sopenharmony_ci flags); 1841cb0ef41Sopenharmony_ci} 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_citransitioning macro RunContextPromiseHook(implicit context: Context)( 1871cb0ef41Sopenharmony_ci slot: Slot<NativeContext, Undefined|Callable>, 1881cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined, 1891cb0ef41Sopenharmony_ci flags: uint32): void { 1901cb0ef41Sopenharmony_ci // Use potentially unused variables. 1911cb0ef41Sopenharmony_ci const _unusedSlot = slot; 1921cb0ef41Sopenharmony_ci const _unusedPromiseOrCapability = promiseOrCapability; 1931cb0ef41Sopenharmony_ci const _unusedFlags = flags; 1941cb0ef41Sopenharmony_ci @if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) { 1951cb0ef41Sopenharmony_ci if (!IsContextPromiseHookEnabled(flags)) return; 1961cb0ef41Sopenharmony_ci const maybeHook = *NativeContextSlot(slot); 1971cb0ef41Sopenharmony_ci const hook = Cast<Callable>(maybeHook) otherwise return; 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci let promise: JSPromise; 2001cb0ef41Sopenharmony_ci typeswitch (promiseOrCapability) { 2011cb0ef41Sopenharmony_ci case (jspromise: JSPromise): { 2021cb0ef41Sopenharmony_ci promise = jspromise; 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci case (capability: PromiseCapability): { 2051cb0ef41Sopenharmony_ci promise = Cast<JSPromise>(capability.promise) otherwise return; 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci case (Undefined): { 2081cb0ef41Sopenharmony_ci return; 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci try { 2131cb0ef41Sopenharmony_ci Call(context, hook, Undefined, promise); 2141cb0ef41Sopenharmony_ci } catch (e, _message) { 2151cb0ef41Sopenharmony_ci runtime::ReportMessageFromMicrotask(e); 2161cb0ef41Sopenharmony_ci } 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_citransitioning macro RunAnyPromiseHookInit(implicit context: Context)( 2211cb0ef41Sopenharmony_ci promise: JSPromise, parent: Object): void { 2221cb0ef41Sopenharmony_ci const promiseHookFlags = PromiseHookFlags(); 2231cb0ef41Sopenharmony_ci // Fast return if no hooks are set. 2241cb0ef41Sopenharmony_ci if (promiseHookFlags == 0) return; 2251cb0ef41Sopenharmony_ci @if(V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS) { 2261cb0ef41Sopenharmony_ci if (IsContextPromiseHookEnabled(promiseHookFlags)) { 2271cb0ef41Sopenharmony_ci RunContextPromiseHookInit(promise, parent); 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci if (IsIsolatePromiseHookEnabled(promiseHookFlags)) { 2311cb0ef41Sopenharmony_ci runtime::PromiseHookInit(promise, parent); 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci} 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci// These allocate and initialize a promise with pending state and 2361cb0ef41Sopenharmony_ci// undefined fields. 2371cb0ef41Sopenharmony_ci// 2381cb0ef41Sopenharmony_ci// This uses the given parent as the parent promise for the promise 2391cb0ef41Sopenharmony_ci// init hook. 2401cb0ef41Sopenharmony_ci@export 2411cb0ef41Sopenharmony_citransitioning macro NewJSPromise(implicit context: Context)(parent: Object): 2421cb0ef41Sopenharmony_ci JSPromise { 2431cb0ef41Sopenharmony_ci const instance = InnerNewJSPromise(); 2441cb0ef41Sopenharmony_ci PromiseInit(instance); 2451cb0ef41Sopenharmony_ci RunAnyPromiseHookInit(instance, parent); 2461cb0ef41Sopenharmony_ci return instance; 2471cb0ef41Sopenharmony_ci} 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci// This uses undefined as the parent promise for the promise init 2501cb0ef41Sopenharmony_ci// hook. 2511cb0ef41Sopenharmony_ci@export 2521cb0ef41Sopenharmony_citransitioning macro NewJSPromise(implicit context: Context)(): JSPromise { 2531cb0ef41Sopenharmony_ci return NewJSPromise(Undefined); 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci// This allocates and initializes a promise with the given state and 2571cb0ef41Sopenharmony_ci// fields. 2581cb0ef41Sopenharmony_ci@export 2591cb0ef41Sopenharmony_citransitioning macro NewJSPromise(implicit context: Context)( 2601cb0ef41Sopenharmony_ci status: constexpr PromiseState, result: JSAny): JSPromise { 2611cb0ef41Sopenharmony_ci dcheck(status != PromiseState::kPending); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci const instance = InnerNewJSPromise(); 2641cb0ef41Sopenharmony_ci instance.reactions_or_result = result; 2651cb0ef41Sopenharmony_ci instance.SetStatus(status); 2661cb0ef41Sopenharmony_ci promise_internal::ZeroOutEmbedderOffsets(instance); 2671cb0ef41Sopenharmony_ci RunAnyPromiseHookInit(instance, Undefined); 2681cb0ef41Sopenharmony_ci return instance; 2691cb0ef41Sopenharmony_ci} 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_cimacro NewPromiseReaction(implicit context: Context)( 2721cb0ef41Sopenharmony_ci handlerContext: Context, next: Zero|PromiseReaction, 2731cb0ef41Sopenharmony_ci promiseOrCapability: JSPromise|PromiseCapability|Undefined, 2741cb0ef41Sopenharmony_ci fulfillHandler: Callable|Undefined, 2751cb0ef41Sopenharmony_ci rejectHandler: Callable|Undefined): PromiseReaction { 2761cb0ef41Sopenharmony_ci const nativeContext = LoadNativeContext(handlerContext); 2771cb0ef41Sopenharmony_ci return new PromiseReaction{ 2781cb0ef41Sopenharmony_ci map: PromiseReactionMapConstant(), 2791cb0ef41Sopenharmony_ci next: next, 2801cb0ef41Sopenharmony_ci reject_handler: rejectHandler, 2811cb0ef41Sopenharmony_ci fulfill_handler: fulfillHandler, 2821cb0ef41Sopenharmony_ci promise_or_capability: promiseOrCapability, 2831cb0ef41Sopenharmony_ci continuation_preserved_embedder_data: 2841cb0ef41Sopenharmony_ci *ContextSlot( 2851cb0ef41Sopenharmony_ci nativeContext, ContextSlot::CONTINUATION_PRESERVED_EMBEDDER_DATA_INDEX) 2861cb0ef41Sopenharmony_ci }; 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ciextern macro PromiseResolveThenableJobTaskMapConstant(): Map; 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-newpromiseresolvethenablejob 2921cb0ef41Sopenharmony_cimacro NewPromiseResolveThenableJobTask(implicit context: Context)( 2931cb0ef41Sopenharmony_ci promiseToResolve: JSPromise, thenable: JSReceiver, 2941cb0ef41Sopenharmony_ci then: Callable): PromiseResolveThenableJobTask { 2951cb0ef41Sopenharmony_ci // 2. Let getThenRealmResult be GetFunctionRealm(then). 2961cb0ef41Sopenharmony_ci // 3. If getThenRealmResult is a normal completion, then let thenRealm be 2971cb0ef41Sopenharmony_ci // getThenRealmResult.[[Value]]. 2981cb0ef41Sopenharmony_ci // 4. Otherwise, let thenRealm be null. 2991cb0ef41Sopenharmony_ci // 3001cb0ef41Sopenharmony_ci // The only cases where |thenRealm| can be null is when |then| is a revoked 3011cb0ef41Sopenharmony_ci // Proxy object, which would throw when it is called anyway. So instead of 3021cb0ef41Sopenharmony_ci // setting the context to null as the spec does, we just use the current 3031cb0ef41Sopenharmony_ci // realm. 3041cb0ef41Sopenharmony_ci const thenContext: Context = ExtractHandlerContext(then); 3051cb0ef41Sopenharmony_ci const nativeContext = LoadNativeContext(thenContext); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci // 1. Let job be a new Job abstract closure with no parameters that 3081cb0ef41Sopenharmony_ci // captures promiseToResolve, thenable, and then... 3091cb0ef41Sopenharmony_ci // 5. Return { [[Job]]: job, [[Realm]]: thenRealm }. 3101cb0ef41Sopenharmony_ci return new PromiseResolveThenableJobTask{ 3111cb0ef41Sopenharmony_ci map: PromiseResolveThenableJobTaskMapConstant(), 3121cb0ef41Sopenharmony_ci context: nativeContext, 3131cb0ef41Sopenharmony_ci promise_to_resolve: promiseToResolve, 3141cb0ef41Sopenharmony_ci thenable, 3151cb0ef41Sopenharmony_ci then 3161cb0ef41Sopenharmony_ci }; 3171cb0ef41Sopenharmony_ci} 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_cistruct InvokeThenOneArgFunctor { 3201cb0ef41Sopenharmony_ci transitioning 3211cb0ef41Sopenharmony_ci macro Call( 3221cb0ef41Sopenharmony_ci nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny, 3231cb0ef41Sopenharmony_ci _arg2: JSAny): JSAny { 3241cb0ef41Sopenharmony_ci return Call(nativeContext, then, receiver, arg1); 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci} 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_cistruct InvokeThenTwoArgFunctor { 3291cb0ef41Sopenharmony_ci transitioning 3301cb0ef41Sopenharmony_ci macro Call( 3311cb0ef41Sopenharmony_ci nativeContext: NativeContext, then: JSAny, receiver: JSAny, arg1: JSAny, 3321cb0ef41Sopenharmony_ci arg2: JSAny): JSAny { 3331cb0ef41Sopenharmony_ci return Call(nativeContext, then, receiver, arg1, arg2); 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci} 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_citransitioning 3381cb0ef41Sopenharmony_cimacro InvokeThen<F: type>(implicit context: Context)( 3391cb0ef41Sopenharmony_ci nativeContext: NativeContext, receiver: JSAny, arg1: JSAny, arg2: JSAny, 3401cb0ef41Sopenharmony_ci callFunctor: F): JSAny { 3411cb0ef41Sopenharmony_ci // We can skip the "then" lookup on {receiver} if it's [[Prototype]] 3421cb0ef41Sopenharmony_ci // is the (initial) Promise.prototype and the Promise#then protector 3431cb0ef41Sopenharmony_ci // is intact, as that guards the lookup path for the "then" property 3441cb0ef41Sopenharmony_ci // on JSPromise instances which have the (initial) %PromisePrototype%. 3451cb0ef41Sopenharmony_ci if (!Is<Smi>(receiver) && 3461cb0ef41Sopenharmony_ci IsPromiseThenLookupChainIntact( 3471cb0ef41Sopenharmony_ci nativeContext, UnsafeCast<HeapObject>(receiver).map)) { 3481cb0ef41Sopenharmony_ci const then = 3491cb0ef41Sopenharmony_ci *NativeContextSlot(nativeContext, ContextSlot::PROMISE_THEN_INDEX); 3501cb0ef41Sopenharmony_ci return callFunctor.Call(nativeContext, then, receiver, arg1, arg2); 3511cb0ef41Sopenharmony_ci } else 3521cb0ef41Sopenharmony_ci deferred { 3531cb0ef41Sopenharmony_ci const then = UnsafeCast<JSAny>(GetProperty(receiver, kThenString)); 3541cb0ef41Sopenharmony_ci return callFunctor.Call(nativeContext, then, receiver, arg1, arg2); 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci} 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_citransitioning 3591cb0ef41Sopenharmony_cimacro InvokeThen(implicit context: Context)( 3601cb0ef41Sopenharmony_ci nativeContext: NativeContext, receiver: JSAny, arg: JSAny): JSAny { 3611cb0ef41Sopenharmony_ci return InvokeThen( 3621cb0ef41Sopenharmony_ci nativeContext, receiver, arg, Undefined, InvokeThenOneArgFunctor{}); 3631cb0ef41Sopenharmony_ci} 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_citransitioning 3661cb0ef41Sopenharmony_cimacro InvokeThen(implicit context: Context)( 3671cb0ef41Sopenharmony_ci nativeContext: NativeContext, receiver: JSAny, arg1: JSAny, 3681cb0ef41Sopenharmony_ci arg2: JSAny): JSAny { 3691cb0ef41Sopenharmony_ci return InvokeThen( 3701cb0ef41Sopenharmony_ci nativeContext, receiver, arg1, arg2, InvokeThenTwoArgFunctor{}); 3711cb0ef41Sopenharmony_ci} 3721cb0ef41Sopenharmony_ci 3731cb0ef41Sopenharmony_citransitioning 3741cb0ef41Sopenharmony_cimacro BranchIfAccessCheckFailed(implicit context: Context)( 3751cb0ef41Sopenharmony_ci nativeContext: NativeContext, promiseConstructor: JSAny, 3761cb0ef41Sopenharmony_ci executor: JSAny): void labels IfNoAccess { 3771cb0ef41Sopenharmony_ci try { 3781cb0ef41Sopenharmony_ci // If executor is a bound function, load the bound function until we've 3791cb0ef41Sopenharmony_ci // reached an actual function. 3801cb0ef41Sopenharmony_ci let foundExecutor = executor; 3811cb0ef41Sopenharmony_ci while (true) { 3821cb0ef41Sopenharmony_ci typeswitch (foundExecutor) { 3831cb0ef41Sopenharmony_ci case (f: JSFunction): { 3841cb0ef41Sopenharmony_ci // Load the context from the function and compare it to the Promise 3851cb0ef41Sopenharmony_ci // constructor's context. If they match, everything is fine, 3861cb0ef41Sopenharmony_ci // otherwise, bail out to the runtime. 3871cb0ef41Sopenharmony_ci const functionContext = f.context; 3881cb0ef41Sopenharmony_ci const nativeFunctionContext = LoadNativeContext(functionContext); 3891cb0ef41Sopenharmony_ci if (TaggedEqual(nativeContext, nativeFunctionContext)) { 3901cb0ef41Sopenharmony_ci goto HasAccess; 3911cb0ef41Sopenharmony_ci } else { 3921cb0ef41Sopenharmony_ci goto CallRuntime; 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci case (b: JSBoundFunction): { 3961cb0ef41Sopenharmony_ci foundExecutor = b.bound_target_function; 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci case (Object): { 3991cb0ef41Sopenharmony_ci goto CallRuntime; 4001cb0ef41Sopenharmony_ci } 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci } label CallRuntime deferred { 4041cb0ef41Sopenharmony_ci const result = runtime::AllowDynamicFunction(promiseConstructor); 4051cb0ef41Sopenharmony_ci if (result != True) { 4061cb0ef41Sopenharmony_ci goto IfNoAccess; 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci } label HasAccess {} 4091cb0ef41Sopenharmony_ci} 4101cb0ef41Sopenharmony_ci} 411