#if ENABLE(PROMISES)
+#include "BuiltinNames.h"
#include "Error.h"
+#include "Exception.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) };
+const ClassInfo JSPromiseDeferred::s_info = { "JSPromiseDeferred", 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);
+ JSFunction* newPromiseDeferredFunction = globalObject->newPromiseDeferredFunction();
+ CallData callData;
+ CallType callType = JSC::getCallData(newPromiseDeferredFunction, callData);
+ ASSERT(callType != CallTypeNone);
- return JSPromiseDeferred::create(vm, promise, resolve, reject);
+ MarkedArgumentBuffer arguments;
+ JSValue deferred = call(exec, newPromiseDeferredFunction, callType, callData, jsUndefined(), arguments);
+
+ JSValue promise = deferred.get(exec, vm.propertyNames->promisePrivateName);
+ ASSERT(promise.inherits(JSPromise::info()));
+ JSValue resolve = deferred.get(exec, vm.propertyNames->builtinNames().resolvePrivateName());
+ JSValue reject = deferred.get(exec, vm.propertyNames->builtinNames().rejectPrivateName());
+
+ return JSPromiseDeferred::create(vm, jsCast<JSPromise*>(promise), resolve, reject);
}
JSPromiseDeferred* JSPromiseDeferred::create(VM& vm, JSObject* promise, JSValue resolve, JSValue reject)
{
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_reject);
}
-JSValue createJSPromiseDeferredFromConstructor(ExecState* exec, JSValue C)
-{
- // -- This implements the GetDeferred(C) abstract operation --
-
- // 1. If IsConstructor(C) is false, throw a TypeError.
- if (!C.isObject())
- return throwTypeError(exec);
-
- ConstructData constructData;
- ConstructType constructType = getConstructData(C, constructData);
- if (constructType == ConstructTypeNone)
- return throwTypeError(exec);
-
- VM& vm = exec->vm();
-
- // 2. Let 'resolver' be a new built-in function object as defined in Deferred Construction Functions.
- JSFunction* resolver = createDeferredConstructionFunction(vm, asObject(C)->globalObject());
-
- // 3. Let 'promise' be the result of calling the [[Construct]] internal method of 'C' with
- // an argument list containing the single item resolver.
- MarkedArgumentBuffer constructArguments;
- constructArguments.append(resolver);
- JSObject* promise = construct(exec, C, constructType, constructData, constructArguments);
-
- // 4. ReturnIfAbrupt(promise).
- if (exec->hadException())
- return jsUndefined();
-
- // 5. Let 'resolve' be the value of resolver's [[Resolve]] internal slot.
- JSValue resolve = resolver->get(exec, vm.propertyNames->resolvePrivateName);
-
- // 6. If IsCallable(resolve) is false, throw a TypeError.
- CallData resolveCallData;
- CallType resolveCallType = getCallData(resolve, resolveCallData);
- if (resolveCallType == CallTypeNone)
- return throwTypeError(exec);
-
- // 7. Let 'reject' be the value of resolver's [[Reject]] internal slot.
- JSValue reject = resolver->get(exec, vm.propertyNames->rejectPrivateName);
-
- // 8. If IsCallable(reject) is false, throw a TypeError.
- CallData rejectCallData;
- CallType rejectCallType = getCallData(reject, rejectCallData);
- if (rejectCallType == CallTypeNone)
- return throwTypeError(exec);
-
- // 9. Return the Deferred { [[Promise]]: promise, [[Resolve]]: resolve, [[Reject]]: reject }.
- return JSPromiseDeferred::create(exec->vm(), promise, resolve, reject);
-}
-
-ThenableStatus updateDeferredFromPotentialThenable(ExecState* exec, JSValue x, JSPromiseDeferred* deferred)
-{
- // 1. If Type(x) is not Object, return "not a thenable".
- if (!x.isObject())
- return NotAThenable;
-
- // 2. Let 'then' be the result of calling Get(x, "then").
- JSValue thenValue = x.get(exec, exec->vm().propertyNames->then);
-
- // 3. If then is an abrupt completion,
- if (exec->hadException()) {
- // i. Let 'rejectResult' be the result of calling the [[Call]] internal method of
- // deferred.[[Reject]] with undefined as thisArgument and a List containing
- // then.[[value]] as argumentsList.
- JSValue exception = exec->exception();
- exec->clearException();
-
- performDeferredReject(exec, deferred, exception);
-
- // ii. ReturnIfAbrupt(rejectResult).
- // NOTE: Nothing to do.
-
- // iii. Return.
- return WasAThenable;
- }
-
- // 4. Let 'then' be then.[[value]].
- // Note: Nothing to do.
-
- // 5. If IsCallable(then) is false, return "not a thenable".
- CallData thenCallData;
- CallType thenCallType = getCallData(thenValue, thenCallData);
- if (thenCallType == CallTypeNone)
- return NotAThenable;
-
- // 6. Let 'thenCallResult' be the result of calling the [[Call]] internal method of
- // 'then' passing x as thisArgument and a List containing deferred.[[Resolve]] and
- // deferred.[[Reject]] as argumentsList.
- MarkedArgumentBuffer thenArguments;
- thenArguments.append(deferred->resolve());
- thenArguments.append(deferred->reject());
-
- call(exec, thenValue, thenCallType, thenCallData, x, thenArguments);
-
- // 7. If 'thenCallResult' is an abrupt completion,
- if (exec->hadException()) {
- // i. Let 'rejectResult' be the result of calling the [[Call]] internal method of
- // deferred.[[Reject]] with undefined as thisArgument and a List containing
- // thenCallResult.[[value]] as argumentsList.
- JSValue exception = exec->exception();
- exec->clearException();
-
- performDeferredReject(exec, deferred, exception);
-
- // ii. ReturnIfAbrupt(rejectResult).
- // NOTE: Nothing to do.
- }
-
- 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();
-
- // i. Let 'rejectResult' be the result of calling the [[Call]] internal method
- // of deferred.[[Reject]] with undefined as thisArgument and a List containing
- // argument.[[value]] as argumentsList.
- performDeferredReject(exec, deferred, argument);
-
- // ii. ReturnIfAbrupt(rejectResult).
- if (exec->hadException())
- return jsUndefined();
-
- // iii. Return deferred.[[Promise]].
- return deferred->promise();
-}
-
} // namespace JSC
#endif // ENABLE(PROMISES)