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