/* * Copyright (C) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "BufferSource.h" #include "IDLTypes.h" #include "JSDOMConvertBase.h" #include "JSDOMWrapperCache.h" #include "JavaScriptCore/JSTypedArrays.h" namespace WebCore { struct IDLInt8Array : IDLTypedArray { }; struct IDLInt16Array : IDLTypedArray { }; struct IDLInt32Array : IDLTypedArray { }; struct IDLUint8Array : IDLTypedArray { }; struct IDLUint16Array : IDLTypedArray { }; struct IDLUint32Array : IDLTypedArray { }; struct IDLUint8ClampedArray : IDLTypedArray { }; struct IDLFloat32Array : IDLTypedArray { }; struct IDLFloat64Array : IDLTypedArray { }; struct IDLBigInt64Array : IDLTypedArray { }; struct IDLBigUint64Array : IDLTypedArray { }; inline RefPtr toPossiblySharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedBigInt64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toPossiblySharedBigUint64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView(vm, value); } inline RefPtr toUnsharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedBigInt64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline RefPtr toUnsharedBigUint64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView(vm, value); } inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer& buffer) { if (auto result = getCachedWrapper(globalObject->world(), buffer)) return result; // The JSArrayBuffer::create function will register the wrapper in finishCreation. return JSC::JSArrayBuffer::create(JSC::getVM(lexicalGlobalObject), globalObject->arrayBufferStructure(buffer.sharingMode()), &buffer); } inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView& view) { return view.wrap(lexicalGlobalObject, globalObject); } inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer) { if (!buffer) return JSC::jsNull(); return toJS(lexicalGlobalObject, globalObject, *buffer); } inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view) { if (!view) return JSC::jsNull(); return toJS(lexicalGlobalObject, globalObject, *view); } inline RefPtr toPossiblySharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) { auto* wrapper = JSC::jsDynamicCast(value); if (!wrapper) return nullptr; return wrapper->possiblySharedImpl(); } inline RefPtr toUnsharedArrayBufferView(JSC::VM& vm, JSC::JSValue value) { auto result = toPossiblySharedArrayBufferView(vm, value); if (!result || result->isShared()) return nullptr; return result; } namespace Detail { enum class BufferSourceConverterAllowSharedMode { Allow, Disallow }; template struct BufferSourceConverter { using WrapperType = typename Converter::WrapperType; using ReturnType = typename Converter::ReturnType; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { auto& vm = JSC::getVM(&lexicalGlobalObject); auto scope = DECLARE_THROW_SCOPE(vm); ReturnType object {}; if constexpr (mode == BufferSourceConverterAllowSharedMode::Allow) object = WrapperType::toWrappedAllowShared(vm, value); else object = WrapperType::toWrapped(vm, value); if (UNLIKELY(!object)) exceptionThrower(lexicalGlobalObject, scope); return object; } }; } template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSArrayBuffer; using ReturnType = JSC::ArrayBuffer*; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSDataView; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSInt8Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSInt16Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSInt32Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSUint8Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } template static JSC::JSValue convertNewlyCreated(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, U&& value) { return convert(lexicalGlobalObject, globalObject, std::forward(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSUint16Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSUint32Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSUint8ClampedArray; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSFloat32Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSFloat64Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSBigInt64Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSBigUint64Array; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template<> struct Converter : DefaultConverter { using WrapperType = JSC::JSArrayBufferView; using ReturnType = RefPtr; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; template<> struct JSConverter { static constexpr bool needsState = true; static constexpr bool needsGlobalObject = true; template static JSC::JSValue convert(JSC::JSGlobalObject& lexicalGlobalObject, JSDOMGlobalObject& globalObject, const U& value) { return toJS(&lexicalGlobalObject, &globalObject, Detail::getPtrOrRef(value)); } }; template struct Converter> : DefaultConverter { using ConverterType = Converter; using WrapperType = typename ConverterType::WrapperType; using ReturnType = typename ConverterType::ReturnType; template static ReturnType convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower()) { return Detail::BufferSourceConverter::convert(lexicalGlobalObject, value, std::forward(exceptionThrower)); } }; } // namespace WebCore