blob: 88cfb48941fb42a61e45f72f1a142ba787b3af18 [file] [log] [blame]
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSPromiseConstructor.h"
#if ENABLE(PROMISES)
#include "Error.h"
#include "JSCJSValueInlines.h"
#include "JSCellInlines.h"
#include "JSPromise.h"
#include "JSPromiseCallback.h"
#include "JSPromisePrototype.h"
#include "JSPromiseResolver.h"
#include "Lookup.h"
#include "StructureInlines.h"
namespace JSC {
STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSPromiseConstructor);
// static Promise fulfill(any value);
static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncFulfill(ExecState*);
// static Promise resolve(any value); // same as any(value)
static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState*);
// static Promise reject(any value);
static EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState*);
}
#include "JSPromiseConstructor.lut.h"
namespace JSC {
const ClassInfo JSPromiseConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::promiseConstructorTable, CREATE_METHOD_TABLE(JSPromiseConstructor) };
/* Source for JSPromiseConstructor.lut.h
@begin promiseConstructorTable
fulfill JSPromiseConstructorFuncFulfill DontEnum|Function 1
resolve JSPromiseConstructorFuncResolve DontEnum|Function 1
reject JSPromiseConstructorFuncReject DontEnum|Function 1
@end
*/
JSPromiseConstructor* JSPromiseConstructor::create(VM& vm, Structure* structure, JSPromisePrototype* promisePrototype)
{
JSPromiseConstructor* constructor = new (NotNull, allocateCell<JSPromiseConstructor>(vm.heap)) JSPromiseConstructor(vm, structure);
constructor->finishCreation(vm, promisePrototype);
return constructor;
}
Structure* JSPromiseConstructor::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
JSPromiseConstructor::JSPromiseConstructor(VM& vm, Structure* structure)
: InternalFunction(vm, structure)
{
}
void JSPromiseConstructor::finishCreation(VM& vm, JSPromisePrototype* promisePrototype)
{
Base::finishCreation(vm, "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)
{
if (!exec->argumentCount())
return throwVMError(exec, createTypeError(exec, "Expected at least one argument"));
JSValue function = exec->uncheckedArgument(0);
CallData callData;
CallType callType = getCallData(function, callData);
if (callType == CallTypeNone)
return throwVMError(exec, createTypeError(exec, "Expected function as as first argument"));
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
// 1. Let promise be a new promise.
JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);
// 2. Let resolver be promise's associated resolver.
JSPromiseResolver* resolver = promise->resolver();
// 3. Set init's callback this value to promise.
// 4. Invoke init with resolver passed as parameter.
MarkedArgumentBuffer initArguments;
initArguments.append(resolver);
call(exec, function, callType, callData, promise, initArguments);
// 5. If init threw an exception, catch it, and then, if resolver's resolved flag
// is unset, run resolver's reject with the thrown exception as argument.
if (exec->hadException()) {
JSValue exception = exec->exception();
exec->clearException();
resolver->rejectIfNotResolved(exec, exception);
}
return JSValue::encode(promise);
}
ConstructType JSPromiseConstructor::getConstructData(JSCell*, ConstructData& constructData)
{
constructData.native.function = constructPromise;
return ConstructTypeHost;
}
CallType JSPromiseConstructor::getCallData(JSCell*, CallData&)
{
return CallTypeNone;
}
bool JSPromiseConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
return getStaticFunctionSlot<InternalFunction>(exec, ExecState::promiseConstructorTable(exec), jsCast<JSPromiseConstructor*>(object), propertyName, slot);
}
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncFulfill(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createTypeError(exec, "Expected at least one argument"));
JSGlobalObject* globalObject = exec->callee()->globalObject();
JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);
promise->resolver()->fulfill(exec, exec->uncheckedArgument(0));
return JSValue::encode(promise);
}
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncResolve(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createTypeError(exec, "Expected at least one argument"));
JSGlobalObject* globalObject = exec->callee()->globalObject();
JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);
promise->resolver()->resolve(exec, exec->uncheckedArgument(0));
return JSValue::encode(promise);
}
EncodedJSValue JSC_HOST_CALL JSPromiseConstructorFuncReject(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createTypeError(exec, "Expected at least one argument"));
JSGlobalObject* globalObject = exec->callee()->globalObject();
JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject);
promise->resolver()->reject(exec, exec->uncheckedArgument(0));
return JSValue::encode(promise);
}
} // namespace JSC
#endif // ENABLE(PROMISES)