[WebIDL] Remove GetterMayThrowException
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMConvertBase.h
1 /*
2  * Copyright (C) 2016 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 #pragma once
27
28 #include "JSDOMExceptionHandling.h"
29 #include <runtime/Error.h>
30
31 namespace WebCore {
32
33 // Conversion from JSValue -> Implementation
34 template<typename T> struct Converter;
35
36 namespace Detail {
37
38 template <typename T> inline T* getPtrOrRef(const T* p) { return const_cast<T*>(p); }
39 template <typename T> inline T& getPtrOrRef(const T& p) { return const_cast<T&>(p); }
40 template <typename T> inline T* getPtrOrRef(const RefPtr<T>& p) { return p.get(); }
41 template <typename T> inline T& getPtrOrRef(const Ref<T>& p) { return p.get(); }
42
43 }
44
45 struct DefaultExceptionThrower {
46     void operator()(JSC::ExecState& state, JSC::ThrowScope& scope)
47     {
48         throwTypeError(&state, scope);
49     }
50 };
51
52 template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue);
53 template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&);
54 template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&);
55 template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, ExceptionThrower&&);
56 template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&, ExceptionThrower&&);
57 template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&, ExceptionThrower&&);
58
59 template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
60 {
61     return Converter<T>::convert(state, value);
62 }
63
64 template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject)
65 {
66     return Converter<T>::convert(state, value, thisObject);
67 }
68
69 template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject)
70 {
71     return Converter<T>::convert(state, value, globalObject);
72 }
73
74 template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower)
75 {
76     return Converter<T>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower));
77 }
78
79 template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject, ExceptionThrower&& exceptionThrower)
80 {
81     return Converter<T>::convert(state, value, thisObject, std::forward<ExceptionThrower>(exceptionThrower));
82 }
83
84 template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower)
85 {
86     return Converter<T>::convert(state, value, globalObject, std::forward<ExceptionThrower>(exceptionThrower));
87 }
88
89 // Conversion from Implementation -> JSValue
90 template<typename T> struct JSConverter;
91
92 template<typename T, typename U> inline JSC::JSValue toJS(U&&);
93 template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, U&&);
94 template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, U&&);
95 template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, U&&);
96 template<typename T, typename U> inline auto toJS(JSC::ExecState&, JSC::ThrowScope&, U&&) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
97 template<typename T, typename U> inline auto toJS(JSC::ExecState&, JSC::ThrowScope&, U&&) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
98 template<typename T, typename U> inline auto toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, U&&) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
99 template<typename T, typename U> inline auto toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, U&&) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
100 template<typename T, typename U> inline auto toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, U&&) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
101 template<typename T, typename U> inline auto toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, U&&) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>;
102
103 template<typename T, bool needsState = JSConverter<T>::needsState, bool needsGlobalObject = JSConverter<T>::needsGlobalObject>
104 struct JSConverterOverloader;
105
106 template<typename T>
107 struct JSConverterOverloader<T, true, true> {
108     template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
109     {
110         return JSConverter<T>::convert(state, globalObject, std::forward<U>(value));
111     }
112 };
113
114 template<typename T>
115 struct JSConverterOverloader<T, true, false> {
116     template<typename U> static JSC::JSValue convert(JSC::ExecState& state, U&& value)
117     {
118         return JSConverter<T>::convert(state, std::forward<U>(value));
119     }
120
121     template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject&, U&& value)
122     {
123         return JSConverter<T>::convert(state, std::forward<U>(value));
124     }
125 };
126
127 template<typename T>
128 struct JSConverterOverloader<T, false, false> {
129     template<typename U> static JSC::JSValue convert(JSC::ExecState&, U&& value)
130     {
131         return JSConverter<T>::convert(std::forward<U>(value));
132     }
133
134     template<typename U> static JSC::JSValue convert(JSC::ExecState&, JSDOMGlobalObject&, U&& value)
135     {
136         return JSConverter<T>::convert(std::forward<U>(value));
137     }
138 };
139
140 template<typename T, typename U> inline JSC::JSValue toJS(U&& value)
141 {
142     return JSConverter<T>::convert(std::forward<U>(value));
143 }
144
145 template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, U&& value)
146 {
147     return JSConverterOverloader<T>::convert(state, std::forward<U>(value));
148 }
149
150 template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
151 {
152     return JSConverterOverloader<T>::convert(state, globalObject, std::forward<U>(value));
153 }
154
155 template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
156 {
157     return JSConverter<T>::convertNewlyCreated(state, globalObject, std::forward<U>(value));
158 }
159
160 template<typename T, typename U> inline auto toJS(JSC::ExecState& state, JSC::ThrowScope& throwScope, U&& value) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
161 {
162     if (UNLIKELY(value.hasException())) {
163         propagateException(state, throwScope, value.releaseException());
164         return { };
165     }
166
167     return toJS<T>(state, value.releaseReturnValue());
168 }
169
170 template<typename T, typename U> inline auto toJS(JSC::ExecState& state, JSC::ThrowScope&, U&& value) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
171 {
172     return toJS<T>(state, std::forward<U>(value));
173 }
174
175 template<typename T, typename U> inline auto toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, U&& value) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
176 {
177     if (UNLIKELY(value.hasException())) {
178         propagateException(state, throwScope, value.releaseException());
179         return { };
180     }
181
182     return toJS<T>(state, globalObject, value.releaseReturnValue());
183 }
184
185 template<typename T, typename U> inline auto toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope&, U&& value) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
186 {
187     return toJS<T>(state, globalObject, std::forward<U>(value));
188 }
189
190 template<typename T, typename U> inline auto toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, U&& value) -> std::enable_if_t<WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
191 {
192     if (UNLIKELY(value.hasException())) {
193         propagateException(state, throwScope, value.releaseException());
194         return { };
195     }
196
197     return toJSNewlyCreated<T>(state, globalObject, value.releaseReturnValue());
198 }
199
200 template<typename T, typename U> inline auto toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope&, U&& value) -> std::enable_if_t<!WTF::IsTemplate<std::decay_t<U>, ExceptionOr>::value, JSC::JSValue>
201 {
202     return toJSNewlyCreated<T>(state, globalObject, std::forward<U>(value));
203 }
204
205
206 template<typename T> struct DefaultConverter {
207     using ReturnType = typename T::ImplementationType;
208
209     // We assume the worst, subtypes can override to be less pessimistic.
210     // An example of something that can have side effects
211     // is having a converter that does JSC::JSValue::toNumber.
212     // toNumber() in JavaScript can call arbitrary JS functions.
213     //
214     // An example of something that does not have side effects
215     // is something having a converter that does JSC::JSValue::toBoolean.
216     // toBoolean() in JS can't call arbitrary functions.
217     static constexpr bool conversionHasSideEffects = true;
218 };
219
220 // Conversion from JSValue -> Implementation for variadic arguments
221 template<typename IDLType> struct VariadicConverter;
222
223 } // namespace WebCore