]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSPromiseReaction.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / 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 "JSCJSValueInlines.h"
33 #include "JSCellInlines.h"
34 #include "JSGlobalObject.h"
35 #include "JSPromiseDeferred.h"
36 #include "Microtask.h"
37 #include "SlotVisitorInlines.h"
38 #include "StrongInlines.h"
39
40 namespace JSC {
41
42 class ExecutePromiseReactionMicrotask final : public Microtask {
43 public:
44 ExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
45 {
46 m_reaction.set(vm, reaction);
47 m_argument.set(vm, argument);
48 }
49
50 virtual ~ExecutePromiseReactionMicrotask()
51 {
52 }
53
54 private:
55 virtual void run(ExecState*) override;
56
57 Strong<JSPromiseReaction> m_reaction;
58 Strong<Unknown> m_argument;
59 };
60
61 PassRefPtr<Microtask> createExecutePromiseReactionMicrotask(VM& vm, JSPromiseReaction* reaction, JSValue argument)
62 {
63 return adoptRef(new ExecutePromiseReactionMicrotask(vm, reaction, argument));
64 }
65
66 void ExecutePromiseReactionMicrotask::run(ExecState* exec)
67 {
68 // 1. Let 'deferred' be reaction.[[Deferred]].
69 JSPromiseDeferred* deferred = m_reaction->deferred();
70
71 // 2. Let 'handler' be reaction.[[Handler]].
72 JSValue handler = m_reaction->handler();
73
74 // 3. Let 'handlerResult' be the result of calling the [[Call]] internal method of
75 // handler passing undefined as thisArgument and a List containing argument as
76 // argumentsList.
77
78 CallData handlerCallData;
79 CallType handlerCallType = getCallData(handler, handlerCallData);
80 ASSERT(handlerCallType != CallTypeNone);
81
82 MarkedArgumentBuffer handlerArguments;
83 handlerArguments.append(m_argument.get());
84
85 JSValue handlerResult = call(exec, handler, handlerCallType, handlerCallData, jsUndefined(), handlerArguments);
86
87 // 4. If handlerResult is an abrupt completion, return the result of calling the
88 // [[Call]] internal method of deferred.[[Reject]] passing undefined as thisArgument
89 // and a List containing handlerResult.[[value]] as argumentsList.
90 if (exec->hadException()) {
91 JSValue exception = exec->exception();
92 exec->clearException();
93
94 performDeferredReject(exec, deferred, exception);
95 }
96
97 // 5. Let 'handlerResult' be handlerResult.[[value]].
98 // Note: Nothing to do.
99
100 // 6. If SameValue(handlerResult, deferred.[[Promise]]) is true,
101 if (sameValue(exec, handlerResult, deferred->promise())) {
102 // i. Let 'selfResolutionError' be a newly-created TypeError object.
103 JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
104
105 // ii. Return the result of calling the [[Call]] internal method of deferred.[[Reject]] passing
106 // undefined as thisArgument and a List containing selfResolutionError as argumentsList.
107 performDeferredReject(exec, deferred, selfResolutionError);
108 }
109
110 // 7. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(handlerResult, deferred).
111 ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, handlerResult, deferred);
112
113 // 8. ReturnIfAbrupt(updateResult).
114 if (exec->hadException())
115 return;
116
117 // 9. If 'updateResult' is "not a thenable",
118 if (updateResult == NotAThenable) {
119 // i. Return the result of calling the [[Call]] internal method of deferred.[[Resolve]]
120 // passing undefined as thisArgument and a List containing handlerResult as argumentsList.
121 performDeferredResolve(exec, deferred, handlerResult);
122 }
123 }
124
125
126 const ClassInfo JSPromiseReaction::s_info = { "JSPromiseReaction", 0, 0, 0, CREATE_METHOD_TABLE(JSPromiseReaction) };
127
128 JSPromiseReaction* JSPromiseReaction::create(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
129 {
130 JSPromiseReaction* promiseReaction = new (NotNull, allocateCell<JSPromiseReaction>(vm.heap)) JSPromiseReaction(vm);
131 promiseReaction->finishCreation(vm, deferred, handler);
132 return promiseReaction;
133 }
134
135 JSPromiseReaction::JSPromiseReaction(VM& vm)
136 : Base(vm, vm.promiseReactionStructure.get())
137 {
138 }
139
140 void JSPromiseReaction::finishCreation(VM& vm, JSPromiseDeferred* deferred, JSValue handler)
141 {
142 Base::finishCreation(vm);
143 m_deferred.set(vm, this, deferred);
144 m_handler.set(vm, this, handler);
145 }
146
147 void JSPromiseReaction::visitChildren(JSCell* cell, SlotVisitor& visitor)
148 {
149 JSPromiseReaction* thisObject = jsCast<JSPromiseReaction*>(cell);
150 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
151 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
152 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
153
154 Base::visitChildren(thisObject, visitor);
155
156 visitor.append(&thisObject->m_deferred);
157 visitor.append(&thisObject->m_handler);
158 }
159
160 } // namespace JSC
161
162 #endif // ENABLE(PROMISES)