1a94c7195e35ee72fea6f0f958e49d51e3610df5
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSPromiseReaction.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSPromiseReaction.h"
28
29 #if ENABLE(PROMISES)
30
31 #include "Error.h"
32 #include "Exception.h"
33 #include "JSCJSValueInlines.h"
34 #include "JSCellInlines.h"
35 #include "JSGlobalObject.h"
36 #include "JSPromiseDeferred.h"
37 #include "Microtask.h"
38 #include "SlotVisitorInlines.h"
39 #include "StrongInlines.h"
40
41 namespace JSC {
42
43 class ExecutePromiseReactionMicrotask final : public Microtask {
44 public:
45     ExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
46     {
47         m_reaction.set(vm, reaction);
48         m_argument.set(vm, argument);
49     }
50
51     virtual ~ExecutePromiseReactionMicrotask()
52     {
53     }
54
55 private:
56     virtual void run(ExecState*) override;
57
58     Strong<JSPromiseReaction> m_reaction;
59     Strong<Unknown> m_argument;
60 };
61
62 PassRefPtr<Microtask> createExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
63 {
64     return adoptRef(new ExecutePromiseReactionMicrotask(vm, reaction, argument));
65 }
66
67 void ExecutePromiseReactionMicrotask::run(ExecState* exec)
68 {
69     // 1. Let 'deferred' be reaction.[[Deferred]].
70     JSPromiseDeferred* deferred = m_reaction->deferred();
71     
72     // 2. Let 'handler' be reaction.[[Handler]].
73     JSValue handler = m_reaction->handler();
74
75     // 3. Let 'handlerResult' be the result of calling the [[Call]] internal method of
76     //    handler passing undefined as thisArgument and a List containing argument as
77     //    argumentsList.
78
79     CallData handlerCallData;
80     CallType handlerCallType = getCallData(handler, handlerCallData);
81     ASSERT(handlerCallType != CallTypeNone);
82
83     MarkedArgumentBuffer handlerArguments;
84     handlerArguments.append(m_argument.get());
85
86     JSValue handlerResult = call(exec, handler, handlerCallType, handlerCallData, jsUndefined(), handlerArguments);
87
88     // 4. If handlerResult is an abrupt completion, return the result of calling the
89     //    [[Call]] internal method of deferred.[[Reject]] passing undefined as thisArgument
90     //    and a List containing handlerResult.[[value]] as argumentsList.
91     if (exec->hadException()) {
92         JSValue exception = exec->exception()->value();
93         exec->clearException();
94
95         performDeferredReject(exec, deferred, exception);
96     }
97     
98     // 5. Let 'handlerResult' be handlerResult.[[value]].
99     // Note: Nothing to do.
100
101     // 6. If SameValue(handlerResult, deferred.[[Promise]]) is true,
102     if (sameValue(exec, handlerResult, deferred->promise())) {
103         // i. Let 'selfResolutionError' be a newly-created TypeError object.
104         JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
105
106         // ii. Return the result of calling the [[Call]] internal method of deferred.[[Reject]] passing
107         //     undefined as thisArgument and a List containing selfResolutionError as argumentsList.
108         performDeferredReject(exec, deferred, selfResolutionError);
109     }
110
111     // 7. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(handlerResult, deferred).
112     ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, handlerResult, deferred);
113     
114     // 8. ReturnIfAbrupt(updateResult).
115     if (exec->hadException())
116         return;
117
118     // 9. If 'updateResult' is "not a thenable",
119     if (updateResult == NotAThenable) {
120         // i. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]]
121         //    passing undefined as thisArgument and a List containing handlerResult as argumentsList.
122         performDeferredResolve(exec, deferred, handlerResult);
123     }
124 }
125
126
127 const ClassInfo JSPromiseReaction::s_info = { "JSPromiseReaction", 0, 0, CREATE_METHOD_TABLE(JSPromiseReaction) };
128
129 JSPromiseReaction* JSPromiseReaction::create(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
130 {
131     JSPromiseReaction* promiseReaction = new (NotNull, allocateCell<JSPromiseReaction>(vm.heap)) JSPromiseReaction(vm);
132     promiseReaction->finishCreation(vm, deferred, handler);
133     return promiseReaction;
134 }
135
136 JSPromiseReaction::JSPromiseReaction(VM& vm)
137     : Base(vm, vm.promiseReactionStructure.get())
138 {
139 }
140
141 void JSPromiseReaction::finishCreation(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
142 {
143     Base::finishCreation(vm);
144     m_deferred.set(vm, this, deferred);
145     m_handler.set(vm, this, handler);
146 }
147
148 void JSPromiseReaction::visitChildren(JSCell* cell, SlotVisitor& visitor)
149 {
150     JSPromiseReaction* thisObject = jsCast<JSPromiseReaction*>(cell);
151     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
152
153     Base::visitChildren(thisObject, visitor);
154
155     visitor.append(&thisObject->m_deferred);
156     visitor.append(&thisObject->m_handler);
157 }
158
159 } // namespace JSC
160
161 #endif // ENABLE(PROMISES)