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; }
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()); }
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(); }