JSPromiseFunctions.cpp [plain text]
#include "config.h"
#include "JSPromiseFunctions.h"
#if ENABLE(PROMISES)
#include "Error.h"
#include "JSCJSValueInlines.h"
#include "JSCellInlines.h"
#include "JSPromise.h"
#include "JSPromiseConstructor.h"
#include "JSPromiseDeferred.h"
#include "NumberObject.h"
#include "StructureInlines.h"
namespace JSC {
static EncodedJSValue JSC_HOST_CALL deferredConstructionFunction(ExecState* exec)
{
JSObject* F = exec->callee();
VM& vm = exec->vm();
F->putDirect(vm, vm.propertyNames->resolvePrivateName, exec->argument(0));
F->putDirect(vm, vm.propertyNames->rejectPrivateName, exec->argument(1));
return JSValue::encode(jsUndefined());
}
JSFunction* createDeferredConstructionFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 2, ASCIILiteral("DeferredConstructionFunction"), deferredConstructionFunction);
}
static EncodedJSValue JSC_HOST_CALL identifyFunction(ExecState* exec)
{
return JSValue::encode(exec->argument(0));
}
JSFunction* createIdentifyFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("IdentityFunction"), identifyFunction);
}
static EncodedJSValue JSC_HOST_CALL promiseAllCountdownFunction(ExecState* exec)
{
JSValue x = exec->argument(0);
VM& vm = exec->vm();
JSObject* F = exec->callee();
uint32_t index = F->get(exec, vm.propertyNames->indexPrivateName).asUInt32();
JSArray* values = jsCast<JSArray*>(F->get(exec, vm.propertyNames->valuesPrivateName));
JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(F->get(exec, vm.propertyNames->deferredPrivateName));
NumberObject* countdownHolder = jsCast<NumberObject*>(F->get(exec, vm.propertyNames->countdownHolderPrivateName));
values->putDirectIndex(exec, index, x);
if (exec->hadException())
abruptRejection(exec, deferred);
uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() - 1;
countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
if (!newCountdownValue) {
performDeferredResolve(exec, deferred, values);
}
return JSValue::encode(jsUndefined());
}
JSFunction* createPromiseAllCountdownFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("PromiseAllCountdownFunction"), promiseAllCountdownFunction);
}
static EncodedJSValue JSC_HOST_CALL promiseResolutionHandlerFunction(ExecState* exec)
{
JSValue x = exec->argument(0);
VM& vm = exec->vm();
JSObject* F = exec->callee();
JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName));
JSValue fulfillmentHandler = F->get(exec, vm.propertyNames->fulfillmentHandlerPrivateName);
JSValue rejectionHandler = F->get(exec, vm.propertyNames->rejectionHandlerPrivateName);
if (sameValue(exec, x, promise)) {
JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
CallData rejectCallData;
CallType rejectCallType = getCallData(rejectionHandler, rejectCallData);
ASSERT(rejectCallType != CallTypeNone);
MarkedArgumentBuffer rejectArguments;
rejectArguments.append(selfResolutionError);
return JSValue::encode(call(exec, rejectionHandler, rejectCallType, rejectCallData, jsUndefined(), rejectArguments));
}
JSValue C = promise->constructor();
JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);
if (exec->hadException())
return JSValue::encode(jsUndefined());
JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);
ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, x, deferred);
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (updateResult != NotAThenable) {
JSObject* deferredPromise = deferred->promise();
JSValue thenValue = deferredPromise->get(exec, exec->vm().propertyNames->then);
if (exec->hadException())
return JSValue::encode(jsUndefined());
CallData thenCallData;
CallType thenCallType = getCallData(thenValue, thenCallData);
if (thenCallType == CallTypeNone)
return JSValue::encode(throwTypeError(exec));
MarkedArgumentBuffer arguments;
arguments.append(fulfillmentHandler);
arguments.append(rejectionHandler);
return JSValue::encode(call(exec, thenValue, thenCallType, thenCallData, deferredPromise, arguments));
}
CallData fulfillmentHandlerCallData;
CallType fulfillmentHandlerCallType = getCallData(fulfillmentHandler, fulfillmentHandlerCallData);
ASSERT(fulfillmentHandlerCallType != CallTypeNone);
MarkedArgumentBuffer fulfillmentHandlerArguments;
fulfillmentHandlerArguments.append(x);
return JSValue::encode(call(exec, fulfillmentHandler, fulfillmentHandlerCallType, fulfillmentHandlerCallData, jsUndefined(), fulfillmentHandlerArguments));
}
JSFunction* createPromiseResolutionHandlerFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("PromiseResolutionHandlerFunction"), promiseResolutionHandlerFunction);
}
static EncodedJSValue JSC_HOST_CALL rejectPromiseFunction(ExecState* exec)
{
JSValue reason = exec->argument(0);
JSObject* F = exec->callee();
VM& vm = exec->vm();
JSPromise* promise = jsCast<JSPromise*>(F->get(exec, exec->vm().propertyNames->promisePrivateName));
promise->reject(vm, reason);
return JSValue::encode(jsUndefined());
}
JSFunction* createRejectPromiseFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("RejectPromiseFunction"), rejectPromiseFunction);
}
static EncodedJSValue JSC_HOST_CALL resolvePromiseFunction(ExecState* exec)
{
JSValue resolution = exec->argument(0);
JSObject* F = exec->callee();
VM& vm = exec->vm();
JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName));
promise->resolve(vm, resolution);
return JSValue::encode(jsUndefined());
}
JSFunction* createResolvePromiseFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("ResolvePromiseFunction"), resolvePromiseFunction);
}
static EncodedJSValue JSC_HOST_CALL throwerFunction(ExecState* exec)
{
return JSValue::encode(exec->vm().throwException(exec, exec->argument(0)));
}
JSFunction* createThrowerFunction(VM& vm, JSGlobalObject* globalObject)
{
return JSFunction::create(vm, globalObject, 1, ASCIILiteral("ThrowerFunction"), throwerFunction);
}
}
#endif // ENABLE(PROMISES)