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-gen.h' 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cinamespace runtime { 81cb0ef41Sopenharmony_ciextern transitioning runtime 91cb0ef41Sopenharmony_ciDebugPromiseThen(implicit context: Context)(JSAny): JSAny; 101cb0ef41Sopenharmony_ci} 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace promise { 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciextern macro 151cb0ef41Sopenharmony_ciCodeStubAssembler::HasAsyncEventDelegate(): bool; 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cimacro 181cb0ef41Sopenharmony_ciIsPromiseSpeciesLookupChainIntact( 191cb0ef41Sopenharmony_ci nativeContext: NativeContext, promiseMap: Map): bool { 201cb0ef41Sopenharmony_ci const promisePrototype = 211cb0ef41Sopenharmony_ci *NativeContextSlot(nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX); 221cb0ef41Sopenharmony_ci if (IsForceSlowPath()) return false; 231cb0ef41Sopenharmony_ci if (promiseMap.prototype != promisePrototype) return false; 241cb0ef41Sopenharmony_ci return !IsPromiseSpeciesProtectorCellInvalid(); 251cb0ef41Sopenharmony_ci} 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci// https://tc39.es/ecma262/#sec-promise.prototype.then 281cb0ef41Sopenharmony_citransitioning javascript builtin 291cb0ef41Sopenharmony_ciPromisePrototypeThen(js-implicit context: NativeContext, receiver: JSAny)( 301cb0ef41Sopenharmony_ci onFulfilled: JSAny, onRejected: JSAny): JSAny { 311cb0ef41Sopenharmony_ci // 1. Let promise be the this value. 321cb0ef41Sopenharmony_ci // 2. If IsPromise(promise) is false, throw a TypeError exception. 331cb0ef41Sopenharmony_ci const promise = Cast<JSPromise>(receiver) otherwise ThrowTypeError( 341cb0ef41Sopenharmony_ci MessageTemplate::kIncompatibleMethodReceiver, 'Promise.prototype.then', 351cb0ef41Sopenharmony_ci receiver); 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci // 3. Let C be ? SpeciesConstructor(promise, %Promise%). 381cb0ef41Sopenharmony_ci const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX); 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci // 4. Let resultCapability be ? NewPromiseCapability(C). 411cb0ef41Sopenharmony_ci let resultPromiseOrCapability: JSPromise|PromiseCapability; 421cb0ef41Sopenharmony_ci let resultPromise: JSAny; 431cb0ef41Sopenharmony_ci try { 441cb0ef41Sopenharmony_ci if (IsPromiseSpeciesLookupChainIntact(context, promise.map)) { 451cb0ef41Sopenharmony_ci goto AllocateAndInit; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci const constructor = SpeciesConstructor(promise, promiseFun); 491cb0ef41Sopenharmony_ci if (TaggedEqual(constructor, promiseFun)) { 501cb0ef41Sopenharmony_ci goto AllocateAndInit; 511cb0ef41Sopenharmony_ci } else { 521cb0ef41Sopenharmony_ci const promiseCapability = NewPromiseCapability(constructor, True); 531cb0ef41Sopenharmony_ci resultPromiseOrCapability = promiseCapability; 541cb0ef41Sopenharmony_ci resultPromise = promiseCapability.promise; 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci } label AllocateAndInit { 571cb0ef41Sopenharmony_ci const resultJSPromise = NewJSPromise(promise); 581cb0ef41Sopenharmony_ci resultPromiseOrCapability = resultJSPromise; 591cb0ef41Sopenharmony_ci resultPromise = resultJSPromise; 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci // We do some work of the PerformPromiseThen operation here, in that 631cb0ef41Sopenharmony_ci // we check the handlers and turn non-callable handlers into undefined. 641cb0ef41Sopenharmony_ci // This is because this is the one and only callsite of PerformPromiseThen 651cb0ef41Sopenharmony_ci // that has to do this. 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci // 3. If IsCallable(onFulfilled) is false, then 681cb0ef41Sopenharmony_ci // a. Set onFulfilled to undefined. 691cb0ef41Sopenharmony_ci const onFulfilled = CastOrDefault<Callable>(onFulfilled, Undefined); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // 4. If IsCallable(onRejected) is false, then 721cb0ef41Sopenharmony_ci // a. Set onRejected to undefined. 731cb0ef41Sopenharmony_ci const onRejected = CastOrDefault<Callable>(onRejected, Undefined); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // 5. Return PerformPromiseThen(promise, onFulfilled, onRejected, 761cb0ef41Sopenharmony_ci // resultCapability). 771cb0ef41Sopenharmony_ci PerformPromiseThenImpl( 781cb0ef41Sopenharmony_ci promise, onFulfilled, onRejected, resultPromiseOrCapability); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci // Async instrumentation for Promise#then(), Promise#catch() and 811cb0ef41Sopenharmony_ci // Promise#finally(), where the latter two both call eventually 821cb0ef41Sopenharmony_ci // call into Promise#then(). 831cb0ef41Sopenharmony_ci if (HasAsyncEventDelegate()) { 841cb0ef41Sopenharmony_ci return runtime::DebugPromiseThen(resultPromise); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci return resultPromise; 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci} 90