2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "JSPromise.h"
32 #include "JSCJSValueInlines.h"
33 #include "JSCellInlines.h"
34 #include "JSPromiseConstructor.h"
35 #include "JSPromiseReaction.h"
36 #include "Microtask.h"
37 #include "SlotVisitorInlines.h"
38 #include "StructureInlines.h"
42 static void triggerPromiseReactions(VM
&, JSGlobalObject
*, Vector
<WriteBarrier
<JSPromiseReaction
>>&, JSValue
);
44 const ClassInfo
JSPromise::s_info
= { "Promise", &Base::s_info
, 0, 0, CREATE_METHOD_TABLE(JSPromise
) };
46 JSPromise
* JSPromise::create(VM
& vm
, JSGlobalObject
* globalObject
, JSPromiseConstructor
* constructor
)
48 JSPromise
* promise
= new (NotNull
, allocateCell
<JSPromise
>(vm
.heap
)) JSPromise(vm
, globalObject
->promiseStructure());
49 promise
->finishCreation(vm
, constructor
);
53 Structure
* JSPromise::createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
55 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(ObjectType
, StructureFlags
), info());
58 JSPromise::JSPromise(VM
& vm
, Structure
* structure
)
59 : JSDestructibleObject(vm
, structure
)
60 , m_status(Status::Unresolved
)
64 void JSPromise::finishCreation(VM
& vm
, JSPromiseConstructor
* constructor
)
66 Base::finishCreation(vm
);
67 ASSERT(inherits(info()));
69 m_constructor
.set(vm
, this, constructor
);
72 void JSPromise::destroy(JSCell
* cell
)
74 static_cast<JSPromise
*>(cell
)->JSPromise::~JSPromise();
77 void JSPromise::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
79 JSPromise
* thisObject
= jsCast
<JSPromise
*>(cell
);
80 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
81 COMPILE_ASSERT(StructureFlags
& OverridesVisitChildren
, OverridesVisitChildrenWithoutSettingFlag
);
82 ASSERT(thisObject
->structure()->typeInfo().overridesVisitChildren());
84 Base::visitChildren(thisObject
, visitor
);
86 visitor
.append(&thisObject
->m_result
);
87 visitor
.append(&thisObject
->m_constructor
);
88 visitor
.append(thisObject
->m_resolveReactions
.begin(), thisObject
->m_resolveReactions
.end());
89 visitor
.append(thisObject
->m_rejectReactions
.begin(), thisObject
->m_rejectReactions
.end());
92 void JSPromise::reject(VM
& vm
, JSValue reason
)
94 // 1. If the value of promise's internal slot [[PromiseStatus]] is not "unresolved", return.
95 if (m_status
!= Status::Unresolved
)
98 DeferGC
deferGC(vm
.heap
);
100 // 2. Let 'reactions' be the value of promise's [[RejectReactions]] internal slot.
101 Vector
<WriteBarrier
<JSPromiseReaction
>> reactions
;
102 reactions
.swap(m_rejectReactions
);
104 // 3. Set the value of promise's [[Result]] internal slot to reason.
105 m_result
.set(vm
, this, reason
);
107 // 4. Set the value of promise's [[ResolveReactions]] internal slot to undefined.
108 m_resolveReactions
.clear();
110 // 5. Set the value of promise's [[RejectReactions]] internal slot to undefined.
111 // NOTE: Handled by the swap above.
113 // 6. Set the value of promise's [[PromiseStatus]] internal slot to "has-rejection".
114 m_status
= Status::HasRejection
;
116 // 7. Return the result of calling TriggerPromiseReactions(reactions, reason).
117 triggerPromiseReactions(vm
, globalObject(), reactions
, reason
);
120 void JSPromise::resolve(VM
& vm
, JSValue resolution
)
122 // 1. If the value of promise's internal slot [[PromiseStatus]] is not "unresolved", return.
123 if (m_status
!= Status::Unresolved
)
126 DeferGC
deferGC(vm
.heap
);
128 // 2. Let 'reactions' be the value of promise's [[ResolveReactions]] internal slot.
129 Vector
<WriteBarrier
<JSPromiseReaction
>> reactions
;
130 reactions
.swap(m_resolveReactions
);
132 // 3. Set the value of promise's [[Result]] internal slot to resolution.
133 m_result
.set(vm
, this, resolution
);
135 // 4. Set the value of promise's [[ResolveReactions]] internal slot to undefined.
136 // NOTE: Handled by the swap above.
138 // 5. Set the value of promise's [[RejectReactions]] internal slot to undefined.
139 m_rejectReactions
.clear();
141 // 6. Set the value of promise's [[PromiseStatus]] internal slot to "has-resolution".
142 m_status
= Status::HasResolution
;
144 // 7. Return the result of calling TriggerPromiseReactions(reactions, resolution).
145 triggerPromiseReactions(vm
, globalObject(), reactions
, resolution
);
148 void JSPromise::appendResolveReaction(VM
& vm
, JSPromiseReaction
* reaction
)
150 m_resolveReactions
.append(WriteBarrier
<JSPromiseReaction
>(vm
, this, reaction
));
153 void JSPromise::appendRejectReaction(VM
& vm
, JSPromiseReaction
* reaction
)
155 m_rejectReactions
.append(WriteBarrier
<JSPromiseReaction
>(vm
, this, reaction
));
158 void triggerPromiseReactions(VM
& vm
, JSGlobalObject
* globalObject
, Vector
<WriteBarrier
<JSPromiseReaction
>>& reactions
, JSValue argument
)
160 // 1. Repeat for each reaction in reactions, in original insertion order
161 for (auto& reaction
: reactions
) {
162 // i. Call QueueMicrotask(ExecutePromiseReaction, (reaction, argument)).
163 globalObject
->queueMicrotask(createExecutePromiseReactionMicrotask(vm
, reaction
.get(), argument
));
171 #endif // ENABLE(PROMISES)