diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp | 518 |
1 files changed, 49 insertions, 469 deletions
diff --git a/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp b/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp index 402619633..a97d99d37 100644 --- a/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp +++ b/Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,50 +26,45 @@ #include "config.h" #include "JSPromiseConstructor.h" -#if ENABLE(PROMISES) - +#include "BuiltinNames.h" #include "Error.h" -#include "JSCJSValueInlines.h" -#include "JSCellInlines.h" +#include "Exception.h" +#include "GetterSetter.h" +#include "IteratorOperations.h" +#include "JSCBuiltins.h" +#include "JSCInlines.h" +#include "JSFunction.h" #include "JSPromise.h" -#include "JSPromiseDeferred.h" -#include "JSPromiseFunctions.h" #include "JSPromisePrototype.h" #include "Lookup.h" #include "NumberObject.h" -#include "StructureInlines.h" namespace JSC { STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSPromiseConstructor); -static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncCast(ExecState*); -static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState*); -static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState*); -static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState*); -static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState*); } #include "JSPromiseConstructor.lut.h" namespace JSC { -const ClassInfo JSPromiseConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::promiseConstructorTable, CREATE_METHOD_TABLE(JSPromiseConstructor) }; +const ClassInfo JSPromiseConstructor::s_info = { "Function", &Base::s_info, &promiseConstructorTable, CREATE_METHOD_TABLE(JSPromiseConstructor) }; /* Source for JSPromiseConstructor.lut.h @begin promiseConstructorTable - cast JSPromiseConstructorFuncCast DontEnum|Function 1 - resolve JSPromiseConstructorFuncResolve DontEnum|Function 1 - reject JSPromiseConstructorFuncReject DontEnum|Function 1 - race JSPromiseConstructorFuncRace DontEnum|Function 1 - all JSPromiseConstructorFuncAll DontEnum|Function 1 + resolve JSBuiltin DontEnum|Function 1 + reject JSBuiltin DontEnum|Function 1 + race JSBuiltin DontEnum|Function 1 + all JSBuiltin DontEnum|Function 1 @end */ -JSPromiseConstructor* JSPromiseConstructor::create(VM& vm, Structure* structure, JSPromisePrototype* promisePrototype) +JSPromiseConstructor* JSPromiseConstructor::create(VM& vm, Structure* structure, JSPromisePrototype* promisePrototype, GetterSetter* speciesSymbol) { JSPromiseConstructor* constructor = new (NotNull, allocateCell<JSPromiseConstructor>(vm.heap)) JSPromiseConstructor(vm, structure); - constructor->finishCreation(vm, promisePrototype); + constructor->finishCreation(vm, promisePrototype, speciesSymbol); + constructor->addOwnInternalSlots(vm, structure->globalObject()); return constructor; } @@ -79,478 +74,63 @@ Structure* JSPromiseConstructor::createStructure(VM& vm, JSGlobalObject* globalO } JSPromiseConstructor::JSPromiseConstructor(VM& vm, Structure* structure) - : InternalFunction(vm, structure) + : Base(vm, structure) { } -void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype) +void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype, GetterSetter* speciesSymbol) { - Base::finishCreation(vm, "Promise"); + Base::finishCreation(vm, ASCIILiteral("Promise")); putDirectWithoutTransition(vm, vm.propertyNames->prototype, promisePrototype, DontEnum | DontDelete | ReadOnly); - putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete); -} - -static EncodedJSValue JSC_HOST_CALL constructPromise(ExecState* exec) -{ - // NOTE: We ignore steps 1-4 as they only matter if you support subclassing, which we do not yet. - // 1. Let promise be the this value. - // 2. If Type(promise) is not Object, then throw a TypeError exception. - // 3. If promise does not have a [[PromiseStatus]] internal slot, then throw a TypeError exception. - // 4. If promise's [[PromiseStatus]] internal slot is not undefined, then throw a TypeError exception. - - JSValue resolver = exec->argument(0); - - // 5. IsCallable(resolver) is false, then throw a TypeError exception - CallData callData; - CallType callType = getCallData(resolver, callData); - if (callType == CallTypeNone) - return JSValue::encode(throwTypeError(exec, ASCIILiteral("Promise constructor takes a function argument"))); - - VM& vm = exec->vm(); - JSGlobalObject* globalObject = exec->callee()->globalObject(); - - JSPromise* promise = JSPromise::create(vm, globalObject, jsCast<JSPromiseConstructor*>(exec->callee())); - - // NOTE: Steps 6-8 are handled by JSPromise::create(). - // 6. Set promise's [[PromiseStatus]] internal slot to "unresolved". - // 7. Set promise's [[ResolveReactions]] internal slot to a new empty List. - // 8. Set promise's [[RejectReactions]] internal slot to a new empty List. - - // 9. Let 'resolve' be a new built-in function object as defined in Resolve Promise Functions. - JSFunction* resolve = createResolvePromiseFunction(vm, globalObject); - - // 10. Set the [[Promise]] internal slot of 'resolve' to 'promise'. - resolve->putDirect(vm, vm.propertyNames->promisePrivateName, promise); - - // 11. Let 'reject' be a new built-in function object as defined in Reject Promise Functions - JSFunction* reject = createRejectPromiseFunction(vm, globalObject); - - // 12. Set the [[Promise]] internal slot of 'reject' to 'promise'. - reject->putDirect(vm, vm.propertyNames->promisePrivateName, promise); - - // 13. Let 'result' be the result of calling the [[Call]] internal method of resolver with - // undefined as thisArgument and a List containing resolve and reject as argumentsList. - MarkedArgumentBuffer arguments; - arguments.append(resolve); - arguments.append(reject); - call(exec, resolver, callType, callData, jsUndefined(), arguments); - - // 14. If result is an abrupt completion, call PromiseReject(promise, result.[[value]]). - if (exec->hadException()) { - JSValue exception = exec->exception(); - exec->clearException(); - - promise->reject(vm, exception); - } - - // 15. Return promise. - return JSValue::encode(promise); -} - -ConstructType JSPromiseConstructor::getConstructData(JSCell*, ConstructData& constructData) -{ - constructData.native.function = constructPromise; - return ConstructTypeHost; + putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), DontEnum | ReadOnly); + putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, Accessor | ReadOnly | DontEnum); } -CallType JSPromiseConstructor::getCallData(JSCell*, CallData& callData) +void JSPromiseConstructor::addOwnInternalSlots(VM& vm, JSGlobalObject* globalObject) { - callData.native.function = constructPromise; - return CallTypeHost; + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().resolvePrivateName(), promiseConstructorResolveCodeGenerator, DontEnum | DontDelete | ReadOnly); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().rejectPrivateName(), promiseConstructorRejectCodeGenerator, DontEnum | DontDelete | ReadOnly); } -bool JSPromiseConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - return getStaticFunctionSlot<InternalFunction>(exec, ExecState::promiseConstructorTable(exec->vm()), jsCast<JSPromiseConstructor*>(object), propertyName, slot); -} - -EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncCast(ExecState* exec) -{ - // -- Promise.cast(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()); -} - -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. 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 '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); - - // 5. ReturnIfAbrupt(resolveResult). - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - // 6. Return deferred.[[Promise]]. - return JSValue::encode(deferred->promise()); -} - -EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState* exec) +static EncodedJSValue JSC_HOST_CALL constructPromise(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); + VM& vm = exec->vm(); + auto scope = DECLARE_THROW_SCOPE(vm); + JSGlobalObject* globalObject = exec->jsCallee()->globalObject(); - // 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); + JSValue newTarget = exec->newTarget(); + if (newTarget.isUndefined()) + return throwVMTypeError(exec, scope); - // 5. ReturnIfAbrupt(resolveResult). - if (exec->hadException()) - return JSValue::encode(jsUndefined()); + Structure* promiseStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->promiseStructure()); + RETURN_IF_EXCEPTION(scope, encodedJSValue()); + JSPromise* promise = JSPromise::create(vm, promiseStructure); + promise->initialize(exec, globalObject, exec->argument(0)); - // 6. Return deferred.[[Promise]]. - return JSValue::encode(deferred->promise()); + return JSValue::encode(promise); } -EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncRace(ExecState* exec) +static EncodedJSValue JSC_HOST_CALL callPromise(ExecState* exec) { - // -- Promise.race(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()); - - JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); - - // 4. Let 'iterator' be the result of calling GetIterator(iterable). - JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName); - 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)); - - // 6. Repeat - do { - // i. Let 'next' be the result of calling IteratorStep(iterator). - JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData nextFunctionCallData; - CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData); - if (nextFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer nextFunctionArguments; - nextFunctionArguments.append(jsUndefined()); - JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments); - - // ii. RejectIfAbrupt(next, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - // iii. If 'next' is false, return deferred.[[Promise]]. - // Note: We implement this as an iterationTerminator - if (next == vm.iterationTerminator.get()) - return JSValue::encode(deferred->promise()); - - // iv. Let 'nextValue' be the result of calling IteratorValue(next). - // v. RejectIfAbrupt(nextValue, deferred). - // Note: 'next' is already the value, so there is nothing to do here. - - // vi. Let 'nextPromise' be the result of calling Invoke(C, "cast", (nextValue)). - JSValue castFunction = C.get(exec, vm.propertyNames->cast); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData castFunctionCallData; - CallType castFunctionCallType = getCallData(castFunction, castFunctionCallData); - if (castFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer castFunctionArguments; - castFunctionArguments.append(next); - JSValue nextPromise = call(exec, castFunction, castFunctionCallType, castFunctionCallData, C, castFunctionArguments); - - // vii. RejectIfAbrupt(nextPromise, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])). - JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData thenFunctionCallData; - CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData); - if (thenFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer thenFunctionArguments; - thenFunctionArguments.append(deferred->resolve()); - thenFunctionArguments.append(deferred->reject()); - - call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments); - - // ix. RejectIfAbrupt(result, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - } while (true); + auto scope = DECLARE_THROW_SCOPE(vm); + return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(exec, scope, "Promise")); } -EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncAll(ExecState* exec) +ConstructType JSPromiseConstructor::getConstructData(JSCell*, ConstructData& constructData) { - // -- 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. - JSObject* thisObject = asObject(C); - JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue); - - // 4. Let 'iterator' be the result of calling GetIterator(iterable). - JSValue iteratorFunction = iterable.get(exec, vm.propertyNames->iteratorPrivateName); - 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)); - - // 6. Let 'values' be the result of calling ArrayCreate(0). - JSArray* values = constructEmptyArray(exec, nullptr, thisObject->globalObject()); - - // 7. Let 'countdownHolder' be Record { [[Countdown]]: 0 }. - NumberObject* countdownHolder = constructNumber(exec, thisObject->globalObject(), JSValue(0)); - - // 8. Let 'index' be 0. - unsigned index = 0; - - // 9. Repeat. - do { - // i. Let 'next' be the result of calling IteratorStep(iterator). - JSValue nextFunction = iterator.get(exec, exec->vm().propertyNames->iteratorNextPrivateName); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData nextFunctionCallData; - CallType nextFunctionCallType = getCallData(nextFunction, nextFunctionCallData); - if (nextFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer nextFunctionArguments; - nextFunctionArguments.append(jsUndefined()); - JSValue next = call(exec, nextFunction, nextFunctionCallType, nextFunctionCallData, iterator, nextFunctionArguments); - - // ii. RejectIfAbrupt(next, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - // iii. If 'next' is false, - // Note: We implement this as an iterationTerminator - if (next == vm.iterationTerminator.get()) { - // a. If 'index' is 0, - if (!index) { - // a. Let 'resolveResult' be the result of calling the [[Call]] internal method - // of deferred.[[Resolve]] with undefined as thisArgument and a List containing - // values as argumentsList. - performDeferredResolve(exec, deferred, values); - - // b. ReturnIfAbrupt(resolveResult). - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - // b. Return deferred.[[Promise]]. - return JSValue::encode(deferred->promise()); - } - - // iv. Let 'nextValue' be the result of calling IteratorValue(next). - // v. RejectIfAbrupt(nextValue, deferred). - // Note: 'next' is already the value, so there is nothing to do here. - - // vi. Let 'nextPromise' be the result of calling Invoke(C, "cast", (nextValue)). - JSValue castFunction = C.get(exec, vm.propertyNames->cast); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData castFunctionCallData; - CallType castFunctionCallType = getCallData(castFunction, castFunctionCallData); - if (castFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer castFunctionArguments; - castFunctionArguments.append(next); - JSValue nextPromise = call(exec, castFunction, castFunctionCallType, castFunctionCallData, C, castFunctionArguments); - - // vii. RejectIfAbrupt(nextPromise, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - // viii. Let 'countdownFunction' be a new built-in function object as defined in Promise.all Countdown Functions. - JSFunction* countdownFunction = createPromiseAllCountdownFunction(vm, thisObject->globalObject()); - - // ix. Set the [[Index]] internal slot of 'countdownFunction' to 'index'. - countdownFunction->putDirect(vm, vm.propertyNames->indexPrivateName, JSValue(index)); - - // x. Set the [[Values]] internal slot of 'countdownFunction' to 'values'. - countdownFunction->putDirect(vm, vm.propertyNames->valuesPrivateName, values); - - // xi. Set the [[Deferred]] internal slot of 'countdownFunction' to 'deferred'. - countdownFunction->putDirect(vm, vm.propertyNames->deferredPrivateName, deferred); - - // xii. Set the [[CountdownHolder]] internal slot of 'countdownFunction' to 'countdownHolder'. - countdownFunction->putDirect(vm, vm.propertyNames->countdownHolderPrivateName, countdownHolder); - - // xiii. Let 'result' be the result of calling Invoke(nextPromise, "then", (countdownFunction, deferred.[[Reject]])). - JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then); - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - CallData thenFunctionCallData; - CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData); - if (thenFunctionCallType == CallTypeNone) { - throwTypeError(exec); - return JSValue::encode(abruptRejection(exec, deferred)); - } - - MarkedArgumentBuffer thenFunctionArguments; - thenFunctionArguments.append(countdownFunction); - thenFunctionArguments.append(deferred->reject()); - - call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments); - - // xiv. RejectIfAbrupt(result, deferred). - if (exec->hadException()) - return JSValue::encode(abruptRejection(exec, deferred)); - - // xv. Set index to index + 1. - index++; - - // xvi. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] + 1. - uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() + 1; - countdownHolder->setInternalValue(vm, JSValue(newCountdownValue)); - } while (true); + constructData.native.function = constructPromise; + return ConstructType::Host; } -JSPromise* constructPromise(ExecState* exec, JSGlobalObject* globalObject, JSFunction* resolver) +CallType JSPromiseConstructor::getCallData(JSCell*, CallData& callData) { - JSPromiseConstructor* promiseConstructor = globalObject->promiseConstructor(); - - ConstructData constructData; - ConstructType constructType = getConstructData(promiseConstructor, constructData); - ASSERT(constructType != ConstructTypeNone); - - MarkedArgumentBuffer arguments; - arguments.append(resolver); - - return jsCast<JSPromise*>(construct(exec, promiseConstructor, constructType, constructData, arguments)); + // FIXME: This is workaround. Since JSC does not expose @isConstructor to JS builtins, + // we use typeof function === "function" now. And since typeof constructorWithoutCallability + // returns "object", we need to define [[Call]] for now. + // https://bugs.webkit.org/show_bug.cgi?id=144093 + callData.native.function = callPromise; + return CallType::Host; } } // namespace JSC - -#endif // ENABLE(PROMISES) |