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 "BufferSource.h" |
29 | #include "IDLTypes.h" |
30 | #include "JSDOMConvertBase.h" |
31 | #include "JSDOMWrapperCache.h" |
32 | #include <JavaScriptCore/JSTypedArrays.h> |
33 | |
34 | namespace WebCore { |
35 | |
36 | struct IDLInt8Array : IDLTypedArray<JSC::Int8Array> { }; |
37 | struct IDLInt16Array : IDLTypedArray<JSC::Int16Array> { }; |
38 | struct IDLInt32Array : IDLTypedArray<JSC::Int32Array> { }; |
39 | struct IDLUint8Array : IDLTypedArray<JSC::Uint8Array> { }; |
40 | struct IDLUint16Array : IDLTypedArray<JSC::Uint16Array> { }; |
41 | struct IDLUint32Array : IDLTypedArray<JSC::Uint32Array> { }; |
42 | struct IDLUint8ClampedArray : IDLTypedArray<JSC::Uint8ClampedArray> { }; |
43 | struct IDLFloat32Array : IDLTypedArray<JSC::Float32Array> { }; |
44 | struct IDLFloat64Array : IDLTypedArray<JSC::Float64Array> { }; |
45 | |
46 | inline RefPtr<JSC::Int8Array> toPossiblySharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int8Adaptor>(vm, value); } |
47 | inline RefPtr<JSC::Int16Array> toPossiblySharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int16Adaptor>(vm, value); } |
48 | inline RefPtr<JSC::Int32Array> toPossiblySharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int32Adaptor>(vm, value); } |
49 | inline RefPtr<JSC::Uint8Array> toPossiblySharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); } |
50 | inline RefPtr<JSC::Uint8ClampedArray> toPossiblySharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); } |
51 | inline RefPtr<JSC::Uint16Array> toPossiblySharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); } |
52 | inline RefPtr<JSC::Uint32Array> toPossiblySharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); } |
53 | inline RefPtr<JSC::Float32Array> toPossiblySharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float32Adaptor>(vm, value); } |
54 | inline RefPtr<JSC::Float64Array> toPossiblySharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float64Adaptor>(vm, value); } |
55 | |
56 | inline RefPtr<JSC::Int8Array> toUnsharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int8Adaptor>(vm, value); } |
57 | inline RefPtr<JSC::Int16Array> toUnsharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int16Adaptor>(vm, value); } |
58 | inline RefPtr<JSC::Int32Array> toUnsharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int32Adaptor>(vm, value); } |
59 | inline RefPtr<JSC::Uint8Array> toUnsharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); } |
60 | inline RefPtr<JSC::Uint8ClampedArray> toUnsharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); } |
61 | inline RefPtr<JSC::Uint16Array> toUnsharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); } |
62 | inline RefPtr<JSC::Uint32Array> toUnsharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); } |
63 | inline RefPtr<JSC::Float32Array> toUnsharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float32Adaptor>(vm, value); } |
64 | inline RefPtr<JSC::Float64Array> toUnsharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float64Adaptor>(vm, value); } |
65 | |
66 | inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer& buffer) |
67 | { |
68 | if (auto result = getCachedWrapper(globalObject->world(), buffer)) |
69 | return result; |
70 | |
71 | // The JSArrayBuffer::create function will register the wrapper in finishCreation. |
72 | return JSC::JSArrayBuffer::create(state->vm(), globalObject->arrayBufferStructure(buffer.sharingMode()), &buffer); |
73 | } |
74 | |
75 | inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView& view) |
76 | { |
77 | return view.wrap(state, globalObject); |
78 | } |
79 | |
80 | inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer) |
81 | { |
82 | if (!buffer) |
83 | return JSC::jsNull(); |
84 | return toJS(state, globalObject, *buffer); |
85 | } |
86 | |
87 | inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view) |
88 | { |
89 | if (!view) |
90 | return JSC::jsNull(); |
91 | return toJS(state, globalObject, *view); |
92 | } |
93 | |
94 | inline RefPtr<JSC::ArrayBufferView> toPossiblySharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) |
95 | { |
96 | auto* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(vm, value); |
97 | if (!wrapper) |
98 | return nullptr; |
99 | return wrapper->possiblySharedImpl(); |
100 | } |
101 | |
102 | inline RefPtr<JSC::ArrayBufferView> toUnsharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) |
103 | { |
104 | auto result = toPossiblySharedArrayBufferView(vm, value); |
105 | if (!result || result->isShared()) |
106 | return nullptr; |
107 | return result; |
108 | } |
109 | |
110 | namespace Detail { |
111 | |
112 | template<typename BufferSourceType> |
113 | struct BufferSourceConverter { |
114 | using WrapperType = typename Converter<BufferSourceType>::WrapperType; |
115 | using ReturnType = typename Converter<BufferSourceType>::ReturnType; |
116 | |
117 | template<typename ExceptionThrower = DefaultExceptionThrower> |
118 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
119 | { |
120 | auto& vm = state.vm(); |
121 | auto scope = DECLARE_THROW_SCOPE(vm); |
122 | ReturnType object = WrapperType::toWrapped(vm, value); |
123 | if (UNLIKELY(!object)) |
124 | exceptionThrower(state, scope); |
125 | return object; |
126 | } |
127 | }; |
128 | |
129 | } |
130 | |
131 | template<> struct Converter<IDLArrayBuffer> : DefaultConverter<IDLArrayBuffer> { |
132 | using WrapperType = JSC::JSArrayBuffer; |
133 | using ReturnType = JSC::ArrayBuffer*; |
134 | |
135 | template<typename ExceptionThrower = DefaultExceptionThrower> |
136 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
137 | { |
138 | return Detail::BufferSourceConverter<IDLArrayBuffer>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
139 | } |
140 | }; |
141 | |
142 | template<> struct JSConverter<IDLArrayBuffer> { |
143 | static constexpr bool needsState = true; |
144 | static constexpr bool needsGlobalObject = true; |
145 | |
146 | template <typename U> |
147 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
148 | { |
149 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
150 | } |
151 | }; |
152 | |
153 | template<> struct Converter<IDLDataView> : DefaultConverter<IDLDataView> { |
154 | using WrapperType = JSC::JSDataView; |
155 | using ReturnType = RefPtr<JSC::DataView>; |
156 | |
157 | template<typename ExceptionThrower = DefaultExceptionThrower> |
158 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
159 | { |
160 | return Detail::BufferSourceConverter<IDLDataView>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
161 | } |
162 | }; |
163 | |
164 | template<> struct JSConverter<IDLDataView> { |
165 | static constexpr bool needsState = true; |
166 | static constexpr bool needsGlobalObject = true; |
167 | |
168 | template <typename U> |
169 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
170 | { |
171 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
172 | } |
173 | }; |
174 | |
175 | template<> struct Converter<IDLInt8Array> : DefaultConverter<IDLInt8Array> { |
176 | using WrapperType = JSC::JSInt8Array; |
177 | using ReturnType = RefPtr<JSC::Int8Array>; |
178 | |
179 | template<typename ExceptionThrower = DefaultExceptionThrower> |
180 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
181 | { |
182 | return Detail::BufferSourceConverter<IDLInt8Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
183 | } |
184 | }; |
185 | |
186 | template<> struct JSConverter<IDLInt8Array> { |
187 | static constexpr bool needsState = true; |
188 | static constexpr bool needsGlobalObject = true; |
189 | |
190 | template <typename U> |
191 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
192 | { |
193 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
194 | } |
195 | }; |
196 | |
197 | template<> struct Converter<IDLInt16Array> : DefaultConverter<IDLInt16Array> { |
198 | using WrapperType = JSC::JSInt16Array; |
199 | using ReturnType = RefPtr<JSC::Int16Array>; |
200 | |
201 | template<typename ExceptionThrower = DefaultExceptionThrower> |
202 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
203 | { |
204 | return Detail::BufferSourceConverter<IDLInt16Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
205 | } |
206 | }; |
207 | |
208 | template<> struct JSConverter<IDLInt16Array> { |
209 | static constexpr bool needsState = true; |
210 | static constexpr bool needsGlobalObject = true; |
211 | |
212 | template <typename U> |
213 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
214 | { |
215 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
216 | } |
217 | }; |
218 | |
219 | template<> struct Converter<IDLInt32Array> : DefaultConverter<IDLInt32Array> { |
220 | using WrapperType = JSC::JSInt32Array; |
221 | using ReturnType = RefPtr<JSC::Int32Array>; |
222 | |
223 | template<typename ExceptionThrower = DefaultExceptionThrower> |
224 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
225 | { |
226 | return Detail::BufferSourceConverter<IDLInt32Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
227 | } |
228 | }; |
229 | |
230 | template<> struct JSConverter<IDLInt32Array> { |
231 | static constexpr bool needsState = true; |
232 | static constexpr bool needsGlobalObject = true; |
233 | |
234 | template <typename U> |
235 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
236 | { |
237 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
238 | } |
239 | }; |
240 | |
241 | template<> struct Converter<IDLUint8Array> : DefaultConverter<IDLUint8Array> { |
242 | using WrapperType = JSC::JSUint8Array; |
243 | using ReturnType = RefPtr<JSC::Uint8Array>; |
244 | |
245 | template<typename ExceptionThrower = DefaultExceptionThrower> |
246 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
247 | { |
248 | return Detail::BufferSourceConverter<IDLUint8Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
249 | } |
250 | }; |
251 | |
252 | template<> struct JSConverter<IDLUint8Array> { |
253 | static constexpr bool needsState = true; |
254 | static constexpr bool needsGlobalObject = true; |
255 | |
256 | template <typename U> |
257 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
258 | { |
259 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
260 | } |
261 | }; |
262 | |
263 | template<> struct Converter<IDLUint16Array> : DefaultConverter<IDLUint16Array> { |
264 | using WrapperType = JSC::JSUint16Array; |
265 | using ReturnType = RefPtr<JSC::Uint16Array>; |
266 | |
267 | template<typename ExceptionThrower = DefaultExceptionThrower> |
268 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
269 | { |
270 | return Detail::BufferSourceConverter<IDLUint16Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
271 | } |
272 | }; |
273 | |
274 | template<> struct JSConverter<IDLUint16Array> { |
275 | static constexpr bool needsState = true; |
276 | static constexpr bool needsGlobalObject = true; |
277 | |
278 | template <typename U> |
279 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
280 | { |
281 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
282 | } |
283 | }; |
284 | |
285 | template<> struct Converter<IDLUint32Array> : DefaultConverter<IDLUint32Array> { |
286 | using WrapperType = JSC::JSUint32Array; |
287 | using ReturnType = RefPtr<JSC::Uint32Array>; |
288 | |
289 | template<typename ExceptionThrower = DefaultExceptionThrower> |
290 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
291 | { |
292 | return Detail::BufferSourceConverter<IDLUint32Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
293 | } |
294 | }; |
295 | |
296 | template<> struct JSConverter<IDLUint32Array> { |
297 | static constexpr bool needsState = true; |
298 | static constexpr bool needsGlobalObject = true; |
299 | |
300 | template <typename U> |
301 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
302 | { |
303 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
304 | } |
305 | }; |
306 | |
307 | template<> struct Converter<IDLUint8ClampedArray> : DefaultConverter<IDLUint8ClampedArray> { |
308 | using WrapperType = JSC::JSUint8ClampedArray; |
309 | using ReturnType = RefPtr<JSC::Uint8ClampedArray>; |
310 | |
311 | template<typename ExceptionThrower = DefaultExceptionThrower> |
312 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
313 | { |
314 | return Detail::BufferSourceConverter<IDLUint8ClampedArray>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
315 | } |
316 | }; |
317 | |
318 | template<> struct JSConverter<IDLUint8ClampedArray> { |
319 | static constexpr bool needsState = true; |
320 | static constexpr bool needsGlobalObject = true; |
321 | |
322 | template <typename U> |
323 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
324 | { |
325 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
326 | } |
327 | }; |
328 | |
329 | template<> struct Converter<IDLFloat32Array> : DefaultConverter<IDLFloat32Array> { |
330 | using WrapperType = JSC::JSFloat32Array; |
331 | using ReturnType = RefPtr<JSC::Float32Array>; |
332 | |
333 | template<typename ExceptionThrower = DefaultExceptionThrower> |
334 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
335 | { |
336 | return Detail::BufferSourceConverter<IDLFloat32Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
337 | } |
338 | }; |
339 | |
340 | template<> struct JSConverter<IDLFloat32Array> { |
341 | static constexpr bool needsState = true; |
342 | static constexpr bool needsGlobalObject = true; |
343 | |
344 | template <typename U> |
345 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
346 | { |
347 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
348 | } |
349 | }; |
350 | |
351 | template<> struct Converter<IDLFloat64Array> : DefaultConverter<IDLFloat64Array> { |
352 | using WrapperType = JSC::JSFloat64Array; |
353 | using ReturnType = RefPtr<JSC::Float64Array>; |
354 | |
355 | template<typename ExceptionThrower = DefaultExceptionThrower> |
356 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
357 | { |
358 | return Detail::BufferSourceConverter<IDLFloat64Array>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
359 | } |
360 | }; |
361 | |
362 | template<> struct JSConverter<IDLFloat64Array> { |
363 | static constexpr bool needsState = true; |
364 | static constexpr bool needsGlobalObject = true; |
365 | |
366 | template <typename U> |
367 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
368 | { |
369 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
370 | } |
371 | }; |
372 | |
373 | template<> struct Converter<IDLArrayBufferView> : DefaultConverter<IDLArrayBufferView> { |
374 | using WrapperType = JSC::JSArrayBufferView; |
375 | using ReturnType = RefPtr<JSC::ArrayBufferView>; |
376 | |
377 | template<typename ExceptionThrower = DefaultExceptionThrower> |
378 | static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) |
379 | { |
380 | return Detail::BufferSourceConverter<IDLArrayBufferView>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower)); |
381 | } |
382 | }; |
383 | |
384 | template<> struct JSConverter<IDLArrayBufferView> { |
385 | static constexpr bool needsState = true; |
386 | static constexpr bool needsGlobalObject = true; |
387 | |
388 | template <typename U> |
389 | static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value) |
390 | { |
391 | return toJS(&state, &globalObject, Detail::getPtrOrRef(value)); |
392 | } |
393 | }; |
394 | |
395 | } // namespace WebCore |
396 | |