EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState* exec) { // -- Promise.reject(x) -- JSValue r = exec->argument(0); // 1. Let 'C' be the this value. JSValue C = exec->thisValue(); // 2. Let 'deferred' be the result of calling GetDeferred(C). JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); // 3. ReturnIfAbrupt(deferred). if (exec->hadException()) return JSValue::encode(jsUndefined()); JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); // 4. Let 'rejectResult' be the result of calling the [[Call]] internal method // of deferred.[[Reject]] with undefined as thisArgument and a List containing r // as argumentsList. performDeferredReject(exec, deferred, r); // 5. ReturnIfAbrupt(resolveResult). if (exec->hadException()) return JSValue::encode(jsUndefined()); // 6. Return deferred.[[Promise]]. return JSValue::encode(deferred->promise()); }
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState* exec) { // -- Promise.all(iterable) -- JSValue iterable = exec->argument(0); VM& vm = exec->vm(); // 1. Let 'C' be the this value. JSValue C = exec->thisValue(); // 2. Let 'deferred' be the result of calling GetDeferred(C). JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); // 3. ReturnIfAbrupt(deferred). if (exec->hadException()) return JSValue::encode(jsUndefined()); // NOTE: A non-abrupt completion of createJSPromiseDeferredFromConstructor implies that // C and deferredValue are objects. JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); // 4. Let 'iterator' be the result of calling GetIterator(iterable). JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorSymbol); if (exec->hadException()) return JSValue::encode(abruptRejection(exec, deferred)); CallData iteratorFunctionCallData; CallType iteratorFunctionCallType = getCallData(iteratorFunction, iteratorFunctionCallData); if (iteratorFunctionCallType == CallTypeNone) { throwTypeError(exec); return JSValue::encode(abruptRejection(exec, deferred)); } ArgList iteratorFunctionArguments; JSValue iterator = call(exec, iteratorFunction, iteratorFunctionCallType, iteratorFunctionCallData, iterable, iteratorFunctionArguments); // 5. RejectIfAbrupt(iterator, deferred). if (exec->hadException()) return JSValue::encode(abruptRejection(exec, deferred)); JSValue result = performPromiseAll(exec, iterator, C, deferred); if (exec->hadException()) { iteratorClose(exec, iterator); if (exec->hadException()) return JSValue::encode(abruptRejection(exec, deferred)); } return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState* exec) { // -- Promise.resolve(x) -- JSValue x = exec->argument(0); // 1. Let 'C' be the this value. JSValue C = exec->thisValue(); // 2. If IsPromise(x) is true, JSPromise* promise = jsDynamicCast<JSPromise*>(x); if (promise) { // i. Let 'constructor' be the value of x's [[PromiseConstructor]] internal slot. JSValue constructor = promise->constructor(); // ii. If SameValue(constructor, C) is true, return x. if (sameValue(exec, constructor, C)) return JSValue::encode(x); } // 3. Let 'deferred' be the result of calling GetDeferred(C). JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); // 4. ReturnIfAbrupt(deferred). if (exec->hadException()) return JSValue::encode(jsUndefined()); JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); // 5. Let 'resolveResult' be the result of calling the [[Call]] internal method // of deferred.[[Resolve]] with undefined as thisArgument and a List containing x // as argumentsList. performDeferredResolve(exec, deferred, x); // 6. ReturnIfAbrupt(resolveResult). if (exec->hadException()) return JSValue::encode(jsUndefined()); // 7. Return deferred.[[Promise]]. return JSValue::encode(deferred->promise()); }
static EncodedJSValue JSC_HOST_CALL promiseResolutionHandlerFunction(ExecState* exec) { JSValue x = exec->argument(0); VM& vm = exec->vm(); JSObject* F = exec->callee(); // 1. Let 'promise' be the value of F's [[Promise]] internal slot JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName)); // 2. Let 'fulfillmentHandler' be the value of F's [[FulfillmentHandler]] internal slot. JSValue fulfillmentHandler = F->get(exec, vm.propertyNames->fulfillmentHandlerPrivateName); // 3. Let 'rejectionHandler' be the value of F's [[RejectionHandler]] internal slot. JSValue rejectionHandler = F->get(exec, vm.propertyNames->rejectionHandlerPrivateName); // 4. If SameValue(x, promise) is true, if (sameValue(exec, x, promise)) { // i. Let 'selfResolutionError' be a newly-created TypeError object. JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself")); // ii. Return the result of calling the [[Call]] internal method of rejectionHandler with // undefined as thisArgument and a List containing selfResolutionError as argumentsList. 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)); } // 5. Let 'C' be the value of promise's [[PromiseConstructor]] internal slot. JSValue C = promise->constructor(); // 6. Let 'deferred' be the result of calling GetDeferred(C) JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C); // 7. ReturnIfAbrupt(deferred). if (exec->hadException()) return JSValue::encode(jsUndefined()); JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); // 8. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(x, deferred). ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, x, deferred); // 9. ReturnIfAbrupt(updateResult). if (exec->hadException()) return JSValue::encode(jsUndefined()); // 10. If 'updateResult' is not "not a thenable", return the result of calling // Invoke(deferred.[[Promise]], "then", (fulfillmentHandler, rejectionHandler)). // NOTE: Invoke does not seem to be defined anywhere, so I am guessing here. 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)); } // 11. Return the result of calling the [[Call]] internal method of fulfillmentHandler // with undefined as thisArgument and a List containing x as argumentsList. 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)); }