[Fetch API] response-consume.html is crashing on Mac WK1 Debug builds
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMPromise.h
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 #ifndef JSDOMPromise_h
27 #define JSDOMPromise_h
28
29 #include "JSDOMBinding.h"
30 #include <heap/StrongInlines.h>
31 #include <runtime/JSPromiseDeferred.h>
32 #include <wtf/Optional.h>
33
34 namespace WebCore {
35
36 class DeferredWrapper {
37 public:
38     DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*, JSC::JSPromiseDeferred*);
39
40     template<class ResolveResultType>
41     void resolve(const ResolveResultType&);
42
43     template<class RejectResultType>
44     void reject(const RejectResultType&);
45
46     JSDOMGlobalObject& globalObject() const;
47     JSC::JSPromiseDeferred& deferred() const;
48
49 private:
50     void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution);
51     void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); }
52     void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); }
53
54     JSC::Strong<JSDOMGlobalObject> m_globalObject;
55     JSC::Strong<JSC::JSPromiseDeferred> m_deferred;
56 };
57
58 void fulfillPromiseWithJSON(DeferredWrapper&, const String&);
59 void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
60
61 inline JSC::JSValue callPromiseFunction(JSC::ExecState& state, JSC::EncodedJSValue promiseFunction(JSC::ExecState*, JSC::JSPromiseDeferred*))
62 {
63     JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject());
64     JSC::JSPromiseDeferred& promiseDeferred = *JSC::JSPromiseDeferred::create(&state, &globalObject);
65     promiseFunction(&state, &promiseDeferred);
66
67     rejectPromiseWithExceptionIfAny(state, globalObject, promiseDeferred);
68     ASSERT(!state.hadException());
69     return promiseDeferred.promise();
70 }
71
72 template <typename Value, typename Error>
73 class DOMPromise {
74 public:
75     DOMPromise(DeferredWrapper&& wrapper) : m_wrapper(WTFMove(wrapper)) { }
76     DOMPromise(DOMPromise&& promise) : m_wrapper(WTFMove(promise.m_wrapper)) { }
77
78     DOMPromise(const DOMPromise&) = default;
79     DOMPromise& operator=(DOMPromise const&) = default;
80
81     void resolve(const Value& value) { m_wrapper.resolve<Value>(value); }
82     void reject(const Error& error) { m_wrapper.reject<Error>(error); }
83
84     JSC::JSPromiseDeferred& deferred() const { return m_wrapper.deferred(); }
85
86 private:
87     DeferredWrapper m_wrapper;
88 };
89
90 template<class ResolveResultType>
91 inline void DeferredWrapper::resolve(const ResolveResultType& result)
92 {
93     ASSERT(m_deferred);
94     ASSERT(m_globalObject);
95     JSC::ExecState* exec = m_globalObject->globalExec();
96     JSC::JSLockHolder locker(exec);
97     resolve(*exec, toJS(exec, m_globalObject.get(), result));
98 }
99
100 template<class RejectResultType>
101 inline void DeferredWrapper::reject(const RejectResultType& result)
102 {
103     ASSERT(m_deferred);
104     ASSERT(m_globalObject);
105     JSC::ExecState* exec = m_globalObject->globalExec();
106     JSC::JSLockHolder locker(exec);
107     reject(*exec, toJS(exec, m_globalObject.get(), result));
108 }
109
110 template<>
111 inline void DeferredWrapper::reject(const std::nullptr_t&)
112 {
113     ASSERT(m_deferred);
114     ASSERT(m_globalObject);
115     JSC::ExecState* exec = m_globalObject->globalExec();
116     JSC::JSLockHolder locker(exec);
117     reject(*exec, JSC::jsNull());
118 }
119
120 template<>
121 inline void DeferredWrapper::reject(const JSC::JSValue& value)
122 {
123     ASSERT(m_deferred);
124     ASSERT(m_globalObject);
125     JSC::ExecState* exec = m_globalObject->globalExec();
126     JSC::JSLockHolder locker(exec);
127     reject(*exec, value);
128 }
129
130 template<>
131 inline void DeferredWrapper::reject<ExceptionCode>(const ExceptionCode& ec)
132 {
133     ASSERT(m_deferred);
134     ASSERT(m_globalObject);
135     JSC::ExecState* exec = m_globalObject->globalExec();
136     JSC::JSLockHolder locker(exec);
137     reject(*exec, createDOMException(exec, ec));
138 }
139
140 template<>
141 inline void DeferredWrapper::resolve<String>(const String& result)
142 {
143     ASSERT(m_deferred);
144     ASSERT(m_globalObject);
145     JSC::ExecState* exec = m_globalObject->globalExec();
146     JSC::JSLockHolder locker(exec);
147     resolve(*exec, jsString(exec, result));
148 }
149
150 template<>
151 inline void DeferredWrapper::resolve<bool>(const bool& result)
152 {
153     ASSERT(m_deferred);
154     ASSERT(m_globalObject);
155     JSC::ExecState* exec = m_globalObject->globalExec();
156     JSC::JSLockHolder locker(exec);
157     resolve(*exec, JSC::jsBoolean(result));
158 }
159
160 template<>
161 inline void DeferredWrapper::resolve<JSC::JSValue>(const JSC::JSValue& value)
162 {
163     ASSERT(m_deferred);
164     ASSERT(m_globalObject);
165     JSC::ExecState* exec = m_globalObject->globalExec();
166     JSC::JSLockHolder locker(exec);
167     resolve(*exec, value);
168 }
169 template<>
170 inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result)
171 {
172     ASSERT(m_deferred);
173     ASSERT(m_globalObject);
174     JSC::ExecState* exec = m_globalObject->globalExec();
175     JSC::JSLockHolder locker(exec);
176     RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(result.data(), result.size());
177     resolve(*exec, toJS(exec, m_globalObject.get(), buffer.get()));
178 }
179
180 template<>
181 inline void DeferredWrapper::resolve(const std::nullptr_t&)
182 {
183     ASSERT(m_deferred);
184     ASSERT(m_globalObject);
185     JSC::ExecState* exec = m_globalObject->globalExec();
186     JSC::JSLockHolder locker(exec);
187     resolve(*exec, JSC::jsUndefined());
188 }
189
190 template<>
191 inline void DeferredWrapper::reject<String>(const String& result)
192 {
193     ASSERT(m_deferred);
194     ASSERT(m_globalObject);
195     JSC::ExecState* exec = m_globalObject->globalExec();
196     JSC::JSLockHolder locker(exec);
197     reject(*exec, jsString(exec, result));
198 }
199
200 }
201
202 #endif // JSDOMPromise_h