diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp | 185 |
1 files changed, 168 insertions, 17 deletions
diff --git a/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp b/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp index 6f3543235..cbc42eb9f 100644 --- a/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp +++ b/Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp @@ -26,38 +26,29 @@ #include "config.h" #include "JSPromiseDeferred.h" -#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, CREATE_METHOD_TABLE(JSPromiseDeferred) }; +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); - JSFunction* newPromiseDeferredFunction = globalObject->newPromiseDeferredFunction(); - CallData callData; - CallType callType = JSC::getCallData(newPromiseDeferredFunction, callData); - ASSERT(callType != CallTypeNone); + JSPromise* promise = constructPromise(exec, globalObject, resolver); + JSValue resolve = resolver->get(exec, vm.propertyNames->resolvePrivateName); + JSValue reject = resolver->get(exec, vm.propertyNames->rejectPrivateName); - 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); + return JSPromiseDeferred::create(vm, promise, resolve, reject); } JSPromiseDeferred* JSPromiseDeferred::create(VM& vm, JSObject* promise, JSValue resolve, JSValue reject) @@ -84,6 +75,8 @@ 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); @@ -92,4 +85,162 @@ void JSPromiseDeferred::visitChildren(JSCell* cell, SlotVisitor& 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 |