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
34namespace WebCore {
35
36struct IDLInt8Array : IDLTypedArray<JSC::Int8Array> { };
37struct IDLInt16Array : IDLTypedArray<JSC::Int16Array> { };
38struct IDLInt32Array : IDLTypedArray<JSC::Int32Array> { };
39struct IDLUint8Array : IDLTypedArray<JSC::Uint8Array> { };
40struct IDLUint16Array : IDLTypedArray<JSC::Uint16Array> { };
41struct IDLUint32Array : IDLTypedArray<JSC::Uint32Array> { };
42struct IDLUint8ClampedArray : IDLTypedArray<JSC::Uint8ClampedArray> { };
43struct IDLFloat32Array : IDLTypedArray<JSC::Float32Array> { };
44struct IDLFloat64Array : IDLTypedArray<JSC::Float64Array> { };
45
46inline RefPtr<JSC::Int8Array> toPossiblySharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int8Adaptor>(vm, value); }
47inline RefPtr<JSC::Int16Array> toPossiblySharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int16Adaptor>(vm, value); }
48inline RefPtr<JSC::Int32Array> toPossiblySharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int32Adaptor>(vm, value); }
49inline RefPtr<JSC::Uint8Array> toPossiblySharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); }
50inline RefPtr<JSC::Uint8ClampedArray> toPossiblySharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); }
51inline RefPtr<JSC::Uint16Array> toPossiblySharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); }
52inline RefPtr<JSC::Uint32Array> toPossiblySharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); }
53inline RefPtr<JSC::Float32Array> toPossiblySharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float32Adaptor>(vm, value); }
54inline RefPtr<JSC::Float64Array> toPossiblySharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float64Adaptor>(vm, value); }
55
56inline RefPtr<JSC::Int8Array> toUnsharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int8Adaptor>(vm, value); }
57inline RefPtr<JSC::Int16Array> toUnsharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int16Adaptor>(vm, value); }
58inline RefPtr<JSC::Int32Array> toUnsharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int32Adaptor>(vm, value); }
59inline RefPtr<JSC::Uint8Array> toUnsharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); }
60inline RefPtr<JSC::Uint8ClampedArray> toUnsharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); }
61inline RefPtr<JSC::Uint16Array> toUnsharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); }
62inline RefPtr<JSC::Uint32Array> toUnsharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); }
63inline RefPtr<JSC::Float32Array> toUnsharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float32Adaptor>(vm, value); }
64inline RefPtr<JSC::Float64Array> toUnsharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float64Adaptor>(vm, value); }
65
66inline 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
75inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView& view)
76{
77 return view.wrap(state, globalObject);
78}
79
80inline 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
87inline 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
94inline 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
102inline 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
110namespace Detail {
111
112template<typename BufferSourceType>
113struct 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
131template<> 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
142template<> 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
153template<> 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
164template<> 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
175template<> 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
186template<> 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
197template<> 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
208template<> 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
219template<> 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
230template<> 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
241template<> 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
252template<> 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
263template<> 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
274template<> 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
285template<> 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
296template<> 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
307template<> 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
318template<> 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
329template<> 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
340template<> 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
351template<> 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
362template<> 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
373template<> 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
384template<> 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