JSPromiseDeferred.cpp [plain text]
#include "config.h"
#include "JSPromiseDeferred.h"
#if ENABLE(PROMISES)
#include "Error.h"
#include "JSCJSValueInlines.h"
#include "JSCellInlines.h"
#include "JSPromise.h"
#include "JSPromiseConstructor.h"
#include "JSPromiseFunctions.h"
#include "SlotVisitorInlines.h"
#include "StructureInlines.h"
namespace JSC {
const ClassInfo JSPromiseDeferred::s_info = { "JSPromiseDeferred", 0, 0, 0, CREATE_METHOD_TABLE(JSPromiseDeferred) };
JSPromiseDeferred* JSPromiseDeferred::create(ExecState* exec, JSGlobalObject* globalObject)
{
VM& vm = exec->vm();
JSFunction* resolver = createDeferredConstructionFunction(vm, globalObject);
JSPromise* promise = constructPromise(exec, globalObject, resolver);
JSValue resolve = resolver->get(exec, vm.propertyNames->resolvePrivateName);
JSValue reject = resolver->get(exec, vm.propertyNames->rejectPrivateName);
return JSPromiseDeferred::create(vm, promise, resolve, reject);
}
JSPromiseDeferred* JSPromiseDeferred::create(VM& vm, JSObject* promise, JSValue resolve, JSValue reject)
{
JSPromiseDeferred* deferred = new (NotNull, allocateCell<JSPromiseDeferred>(vm.heap)) JSPromiseDeferred(vm);
deferred->finishCreation(vm, promise, resolve, reject);
return deferred;
}
JSPromiseDeferred::JSPromiseDeferred(VM& vm)
: Base(vm, vm.promiseDeferredStructure.get())
{
}
void JSPromiseDeferred::finishCreation(VM& vm, JSObject* promise, JSValue resolve, JSValue reject)
{
Base::finishCreation(vm);
m_promise.set(vm, this, promise);
m_resolve.set(vm, this, resolve);
m_reject.set(vm, this, reject);
}
void JSPromiseDeferred::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSPromiseDeferred* thisObject = jsCast<JSPromiseDeferred*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
visitor.append(&thisObject->m_promise);
visitor.append(&thisObject->m_resolve);
visitor.append(&thisObject->m_reject);
}
JSValue createJSPromiseDeferredFromConstructor(ExecState* exec, JSValue C)
{
if (!C.isObject())
return throwTypeError(exec);
ConstructData constructData;
ConstructType constructType = getConstructData(C, constructData);
if (constructType == ConstructTypeNone)
return throwTypeError(exec);
VM& vm = exec->vm();
JSFunction* resolver = createDeferredConstructionFunction(vm, asObject(C)->globalObject());
MarkedArgumentBuffer constructArguments;
constructArguments.append(resolver);
JSObject* promise = construct(exec, C, constructType, constructData, constructArguments);
if (exec->hadException())
return jsUndefined();
JSValue resolve = resolver->get(exec, vm.propertyNames->resolvePrivateName);
CallData resolveCallData;
CallType resolveCallType = getCallData(resolve, resolveCallData);
if (resolveCallType == CallTypeNone)
return throwTypeError(exec);
JSValue reject = resolver->get(exec, vm.propertyNames->rejectPrivateName);
CallData rejectCallData;
CallType rejectCallType = getCallData(reject, rejectCallData);
if (rejectCallType == CallTypeNone)
return throwTypeError(exec);
return JSPromiseDeferred::create(exec->vm(), promise, resolve, reject);
}
ThenableStatus updateDeferredFromPotentialThenable(ExecState* exec, JSValue x, JSPromiseDeferred* deferred)
{
if (!x.isObject())
return NotAThenable;
JSValue thenValue = x.get(exec, exec->vm().propertyNames->then);
if (exec->hadException()) {
JSValue exception = exec->exception();
exec->clearException();
performDeferredReject(exec, deferred, exception);
return WasAThenable;
}
CallData thenCallData;
CallType thenCallType = getCallData(thenValue, thenCallData);
if (thenCallType == CallTypeNone)
return NotAThenable;
MarkedArgumentBuffer thenArguments;
thenArguments.append(deferred->resolve());
thenArguments.append(deferred->reject());
call(exec, thenValue, thenCallType, thenCallData, x, thenArguments);
if (exec->hadException()) {
JSValue exception = exec->exception();
exec->clearException();
performDeferredReject(exec, deferred, exception);
}
return WasAThenable;
}
void performDeferredResolve(ExecState* exec, JSPromiseDeferred* deferred, JSValue argument)
{
JSValue deferredResolve = deferred->resolve();
CallData resolveCallData;
CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
ASSERT(resolveCallType != CallTypeNone);
MarkedArgumentBuffer arguments;
arguments.append(argument);
call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
}
void performDeferredReject(ExecState* exec, JSPromiseDeferred* deferred, JSValue argument)
{
JSValue deferredReject = deferred->reject();
CallData rejectCallData;
CallType rejectCallType = getCallData(deferredReject, rejectCallData);
ASSERT(rejectCallType != CallTypeNone);
MarkedArgumentBuffer arguments;
arguments.append(argument);
call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
}
JSValue abruptRejection(ExecState* exec, JSPromiseDeferred* deferred)
{
ASSERT(exec->hadException());
JSValue argument = exec->exception();
exec->clearException();
performDeferredReject(exec, deferred, argument);
if (exec->hadException())
return jsUndefined();
return deferred->promise();
}
}
#endif // ENABLE(PROMISES)