diff --git a/JavaScriptCore/API/JSTypedArray.cpp b/JavaScriptCore/API/JSTypedArray.cpp index 1ec2a0dc..4eddc5a3 100644 --- a/JavaScriptCore/API/JSTypedArray.cpp +++ b/JavaScriptCore/API/JSTypedArray.cpp @@ -1,10 +1,32 @@ +/* + * Copyright (C) 2015 Dominic Szablewski (dominic@phoboslab.org) + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ -#include "config.h" +#include "config.h" #include "JSTypedArray.h" -#include - #include "JSObjectRef.h" #include "APICast.h" #include "InitializeThreading.h" @@ -12,6 +34,7 @@ #include "JSClassRef.h" #include "JSGlobalObject.h" +#include "TypedArrayInlines.h" #include "JSArrayBuffer.h" #include "JSFloat32Array.h" #include "JSFloat64Array.h" @@ -23,11 +46,42 @@ #include "JSUint16Array.h" #include "JSUint32Array.h" -#include "TypedArrayInlines.h" +#include + using namespace JSC; -// Better be safe than sorry! +struct OpaqueJSData : public ThreadSafeRefCounted { + + static PassRefPtr create(PassRefPtr buffer, void* baseAddress, size_t byteLength) + { + return adoptRef(new OpaqueJSData(buffer, baseAddress, byteLength)); + } + + size_t length() { + return m_byteLength; + } + + void* baseAddress() { + return m_baseAddress; + } + +private: + friend class WTF::ThreadSafeRefCounted; + + OpaqueJSData( + PassRefPtr buffer, void* baseAddress, size_t byteLength) + : m_byteLength(byteLength) + , m_baseAddress(baseAddress) + , m_buffer(buffer) + {} + + unsigned m_byteLength; + void* m_baseAddress; + PassRefPtr m_buffer; +}; + + const JSTypedArrayType TypedArrayTypes[] = { [NotTypedArray] = kJSTypedArrayTypeNone, [TypeInt8] = kJSTypedArrayTypeInt8Array, @@ -42,89 +96,104 @@ const JSTypedArrayType TypedArrayTypes[] = { /* not a TypedArray */ kJSTypedArrayTypeArrayBuffer }; -const int kJSTypedArrayTypeLast = kJSTypedArrayTypeArrayBuffer; - - -template JSObject * CreateTypedArray(JSC::ExecState* exec, size_t length) { - return ArrayType::create(length)->wrap(exec, exec->lexicalGlobalObject()); -} - -template JSObject * CreateArrayBuffer(JSC::ExecState* exec, size_t length) { - RefPtr buffer = BufferType::create(length, 1); - if( !buffer ) { - return NULL; - } - - JSArrayBuffer* result = JSArrayBuffer::create( - exec->vm(), exec->lexicalGlobalObject()->arrayBufferStructure(), buffer); - return result; -} - -typedef JSObject*(*CreateTypedArrayFuncPtr)(JSC::ExecState*, size_t); -const CreateTypedArrayFuncPtr CreateTypedArrayFunc[] = { - [kJSTypedArrayTypeNone] = NULL, - [kJSTypedArrayTypeInt8Array] = CreateTypedArray, - [kJSTypedArrayTypeInt16Array] = CreateTypedArray, - [kJSTypedArrayTypeInt32Array] = CreateTypedArray, - [kJSTypedArrayTypeUint8Array] = CreateTypedArray, - [kJSTypedArrayTypeUint8ClampedArray] = CreateTypedArray, - [kJSTypedArrayTypeUint16Array] = CreateTypedArray, - [kJSTypedArrayTypeUint32Array] = CreateTypedArray, - [kJSTypedArrayTypeFloat32Array] = CreateTypedArray, - [kJSTypedArrayTypeFloat64Array] = CreateTypedArray, - [kJSTypedArrayTypeArrayBuffer] = CreateArrayBuffer, -}; - - - - -JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectRef object) { +JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectRef object) +{ ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSTypedArrayType type = kJSTypedArrayTypeNone; - if( jsObject->inherits(JSArrayBufferView::info()) ) { + if (jsObject->inherits(JSArrayBufferView::info())) type = TypedArrayTypes[jsObject->classInfo()->typedArrayStorageType]; - } - else if( jsObject->inherits(JSArrayBuffer::info()) ) { + else if (jsObject->inherits(JSArrayBuffer::info())) type = kJSTypedArrayTypeArrayBuffer; - } + return type; } -JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t numElements) { +JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t numElements) +{ ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); - JSObject* result = NULL; - if( arrayType > kJSTypedArrayTypeNone && arrayType <= kJSTypedArrayTypeLast ) { - result = CreateTypedArrayFunc[arrayType]( exec, numElements ); + JSObject* result; + JSGlobalObject* jsGlobal = exec->lexicalGlobalObject(); + + switch (arrayType) { + case kJSTypedArrayTypeInt8Array: + result = Int8Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeInt16Array: + result = Int16Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeInt32Array: + result = Int8Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeUint8Array: + result = Int32Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeUint8ClampedArray: + result = Uint8ClampedArray::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeUint16Array: + result = Uint16Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeUint32Array: + result = Uint32Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeFloat32Array: + result = Float32Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeFloat64Array: + result = Float64Array::create(numElements)->wrap(exec, jsGlobal); + break; + case kJSTypedArrayTypeArrayBuffer: + result = JSArrayBuffer::create( + exec->vm(), jsGlobal->arrayBufferStructure(), ArrayBuffer::create(numElements, 1)); + break; + default: + result = nullptr; + break; } return toRef(result); } -void* JSObjectGetTypedArrayDataPtr(JSContextRef ctx, JSObjectRef object, size_t* byteLength) { +JSDataRef JSObjectGetRetainedTypedArrayData(JSContextRef ctx, JSObjectRef object) +{ ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); - if( JSArrayBufferView * view = jsDynamicCast(jsObject) ) { - if( byteLength ) { - *byteLength = view->impl()->byteLength(); - } - return view->impl()->baseAddress(); - } - else if( ArrayBuffer* buffer = toArrayBuffer(jsObject) ) { - if( byteLength ) { - *byteLength = buffer->byteLength(); - } - return buffer->data(); - } + if (JSArrayBufferView * view = jsDynamicCast(jsObject)) + return OpaqueJSData::create(view->buffer(), view->impl()->baseAddress(), view->impl()->byteLength()).leakRef(); - if( byteLength ) { - *byteLength = 0; - } + if (ArrayBuffer* buffer = toArrayBuffer(jsObject)) + return OpaqueJSData::create(buffer, buffer->data(), buffer->byteLength()).leakRef(); + return NULL; } + +JSDataRef JSDataRetain(JSDataRef data) +{ + if (data) + data->ref(); + return data; +} + +void JSDataRelease(JSDataRef data) +{ + if (data) + data->deref(); +} + +void* JSDataGetBytesPtr(JSDataRef data) +{ + return data->baseAddress(); +} + +size_t JSDataGetLength(JSDataRef data) +{ + return data->length(); +} + diff --git a/JavaScriptCore/API/JSTypedArray.h b/JavaScriptCore/API/JSTypedArray.h index b7c827b6..fdbf3e1f 100644 --- a/JavaScriptCore/API/JSTypedArray.h +++ b/JavaScriptCore/API/JSTypedArray.h @@ -1,3 +1,29 @@ +/* + * Copyright (C) 2015 Dominic Szablewski (dominic@phoboslab.org) + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + + #ifndef JSTypedArray_h #define JSTypedArray_h @@ -41,7 +67,7 @@ typedef enum { @abstract Returns a JavaScript value's Typed Array type @param ctx The execution context to use. @param value The JSValue whose Typed Array type you want to obtain. -@result A value of type JSTypedArrayType that identifies value's Typed Array type. +@result A value of type JSTypedArrayType that identifies value's Typed Array type, or kJSTypedArrayTypeNone if the object is not a Typed Array. */ JS_EXPORT JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectRef object); @@ -55,15 +81,50 @@ JS_EXPORT JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectR */ JS_EXPORT JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t numElements); +/*! @typedef JSDataRef A Typed Array data buffer. */ +typedef struct OpaqueJSData* JSDataRef; + /*! @function -@abstract Returns a pointer to a Typed Array's data in memory +@abstract Returns a retained JSDataRef that encapsulates a pointer to a Typed Array's data in memory @param ctx The execution context to use. -@param value The JSValue whose Typed Array type data pointer you want to obtain. -@param byteLength A pointer to a size_t in which to store the byte length of the Typed Array -@result A pointer to the Typed Array's data or NULL if the JSValue is not a Typed Array. +@param value The JSObjectRef whose Typed Array type data pointer you want to obtain. +@result A JSDataRef or NULL if the JSObjectRef is not a Typed Array. The return value is automatically retained and has to be released again with JSDataRelease +*/ +JS_EXPORT JSDataRef JSObjectGetRetainedTypedArrayData(JSContextRef ctx, JSObjectRef object); + +/*! +@function +@abstract Retains a JavaScript data object. +@param data The JSData to retain. +@result A JSDataRef that is the same as data. +*/ +JS_EXPORT JSDataRef JSDataRetain(JSDataRef data); + +/*! +@function +@abstract Releases a JavaScript data object. +@param data The JSData to release. */ -JS_EXPORT void * JSObjectGetTypedArrayDataPtr(JSContextRef ctx, JSObjectRef object, size_t* byteLength); +JS_EXPORT void JSDataRelease(JSDataRef data); + +/*! +@function +@abstract Returns a pointer to the data buffer that serves as the backing store for a JavaScript data object. +@param data The JSData whose backing store you want to access. +@result A pointer to the raw data buffer that serves as data's backing store, which will be deallocated when the data is deallocated. +*/ +JS_EXPORT void * JSDataGetBytesPtr(JSDataRef data); + +/*! +@function +@abstract Returns the number of bytes in a JavaScript data object. +@param data The JSData whose length (in bytes) you want to know. +@result The number of bytes stored in the data object. +*/ +JS_EXPORT size_t JSDataGetLength(JSDataRef data); + + #ifdef __cplusplus