blob: 00f9b0c80f3632939806a26f28926518ba4d41a2 [file] [log] [blame]
// 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-gen.h'
namespace promise {
macro
IsPromiseSpeciesLookupChainIntact(
nativeContext: NativeContext, promiseMap: Map): bool {
const promisePrototype =
*NativeContextSlot(nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX);
if (IsForceSlowPath()) return false;
if (promiseMap.prototype != promisePrototype) return false;
return !IsPromiseSpeciesProtectorCellInvalid();
}
// https://tc39.es/ecma262/#sec-promise.prototype.then
transitioning javascript builtin
PromisePrototypeThen(js-implicit context: NativeContext, receiver: JSAny)(
onFulfilled: JSAny, onRejected: JSAny): JSAny {
// 1. Let promise be the this value.
// 2. If IsPromise(promise) is false, throw a TypeError exception.
const promise = Cast<JSPromise>(receiver) otherwise ThrowTypeError(
MessageTemplate::kIncompatibleMethodReceiver, 'Promise.prototype.then',
receiver);
// 3. Let C be ? SpeciesConstructor(promise, %Promise%).
const promiseFun = *NativeContextSlot(ContextSlot::PROMISE_FUNCTION_INDEX);
// 4. Let resultCapability be ? NewPromiseCapability(C).
let resultPromiseOrCapability: JSPromise|PromiseCapability;
let resultPromise: JSAny;
try {
if (IsPromiseSpeciesLookupChainIntact(context, promise.map)) {
goto AllocateAndInit;
}
const constructor = SpeciesConstructor(promise, promiseFun);
if (TaggedEqual(constructor, promiseFun)) {
goto AllocateAndInit;
} else {
const promiseCapability = NewPromiseCapability(constructor, True);
resultPromiseOrCapability = promiseCapability;
resultPromise = promiseCapability.promise;
}
} label AllocateAndInit {
const resultJSPromise = NewJSPromise(promise);
resultPromiseOrCapability = resultJSPromise;
resultPromise = resultJSPromise;
}
// We do some work of the PerformPromiseThen operation here, in that
// we check the handlers and turn non-callable handlers into undefined.
// This is because this is the one and only callsite of PerformPromiseThen
// that has to do this.
// 3. If IsCallable(onFulfilled) is false, then
// a. Set onFulfilled to undefined.
const onFulfilled = CastOrDefault<Callable>(onFulfilled, Undefined);
// 4. If IsCallable(onRejected) is false, then
// a. Set onRejected to undefined.
const onRejected = CastOrDefault<Callable>(onRejected, Undefined);
// 5. Return PerformPromiseThen(promise, onFulfilled, onRejected,
// resultCapability).
PerformPromiseThenImpl(
promise, onFulfilled, onRejected, resultPromiseOrCapability);
return resultPromise;
}
}