JSPromiseReaction.cpp [plain text]
#include "config.h"
#include "JSPromiseReaction.h"
#if ENABLE(PROMISES)
#include "Error.h"
#include "JSCJSValueInlines.h"
#include "JSCellInlines.h"
#include "JSGlobalObject.h"
#include "JSPromiseDeferred.h"
#include "Microtask.h"
#include "SlotVisitorInlines.h"
#include "StrongInlines.h"
namespace JSC {
class ExecutePromiseReactionMicrotask final : public Microtask {
public:
ExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
{
m_reaction.set(vm, reaction);
m_argument.set(vm, argument);
}
virtual ~ExecutePromiseReactionMicrotask()
{
}
private:
virtual void run(ExecState*) override;
Strong<JSPromiseReaction> m_reaction;
Strong<Unknown> m_argument;
};
PassRefPtr<Microtask> createExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
{
return adoptRef(new ExecutePromiseReactionMicrotask(vm, reaction, argument));
}
void ExecutePromiseReactionMicrotask::run(ExecState* exec)
{
JSPromiseDeferred* deferred = m_reaction->deferred();
JSValue handler = m_reaction->handler();
CallData handlerCallData;
CallType handlerCallType = getCallData(handler, handlerCallData);
ASSERT(handlerCallType != CallTypeNone);
MarkedArgumentBuffer handlerArguments;
handlerArguments.append(m_argument.get());
JSValue handlerResult = call(exec, handler, handlerCallType, handlerCallData, jsUndefined(), handlerArguments);
if (exec->hadException()) {
JSValue exception = exec->exception();
exec->clearException();
performDeferredReject(exec, deferred, exception);
}
if (sameValue(exec, handlerResult, deferred->promise())) {
JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
performDeferredReject(exec, deferred, selfResolutionError);
}
ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, handlerResult, deferred);
if (exec->hadException())
return;
if (updateResult == NotAThenable) {
performDeferredResolve(exec, deferred, handlerResult);
}
}
const ClassInfo JSPromiseReaction::s_info = { "JSPromiseReaction", 0, 0, 0, CREATE_METHOD_TABLE(JSPromiseReaction) };
JSPromiseReaction* JSPromiseReaction::create(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
{
JSPromiseReaction* promiseReaction = new (NotNull, allocateCell<JSPromiseReaction>(vm.heap)) JSPromiseReaction(vm);
promiseReaction->finishCreation(vm, deferred, handler);
return promiseReaction;
}
JSPromiseReaction::JSPromiseReaction(VM& vm)
: Base(vm, vm.promiseReactionStructure.get())
{
}
void JSPromiseReaction::finishCreation(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
{
Base::finishCreation(vm);
m_deferred.set(vm, this, deferred);
m_handler.set(vm, this, handler);
}
void JSPromiseReaction::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSPromiseReaction* thisObject = jsCast<JSPromiseReaction*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
visitor.append(&thisObject->m_deferred);
visitor.append(&thisObject->m_handler);
}
}
#endif // ENABLE(PROMISES)