Title: [197983] trunk/Source/_javascript_Core
Revision
197983
Author
keith_mil...@apple.com
Date
2016-03-10 18:46:03 -0800 (Thu, 10 Mar 2016)

Log Message

Typed Arrays have no public facing API
https://bugs.webkit.org/show_bug.cgi?id=120112

Reviewed by Geoffrey Garen.

This patch adds a new C-API (an Obj-C API will follow in the future) for Typed Arrays. The API has two sets of
functions. One for Typed Arrays and another for Array Buffers. This API is intended to reflect the use of Typed
Array objects in JS code. There is a method for each of the core TypedArray and Array Buffer methods.
Originally, we were planning on using a separate non-JS object as the backing store instead of a JS Array Buffer
but we decide to defer that idea since there was no good CF/NS API that met all the constraints we needed
(Discussed further below). We also wanted to want until Shared Array Buffers had reached a more finished state
to see what impact they might have on an API.

The API has the following Typed Array construction methods:
1) Create with length (the backing buffer is zero initialized). -- JSObjectMakeTypedArray
2) Create with an existing pointer and a destructor. -- JSObjectMakeTypedArrayFromBytesNoCopy
3) Create with an Array Buffer object. -- JSObjectMakeTypedArrayFromArrayBuffer
4) Create with an Array Buffer object with a given offset and length. -- JSObjectMakeTypedArrayFromArrayBufferWithOffset

The API has the following functions on Typed Array JSObjectRefs:
5) Get access to a temporary void* of the backing store's data. -- JSObjectGetTypedArrayBytesPtr
6) Get the length of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayLength
7) Get the byte length of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayByteLength
8) Get the byte offset of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayByteOffset
9) Get a Typed Array object's Array Buffer  backing store. -- JSObjectGetTypedArrayBuffer

The API has the following Array Buffer construction method:
10) Create with an existing pointer and a destructor. -- JSObjectMakeArrayBufferWithBytesNoCopy

The API has the following functions on Array Buffer JSObjectRefs:
11) Get access to a temporary void* of the backing store's data. -- JSObjectGetArrayBufferBytesPtr
12) Get the byte length of an Array Buffer object (returns 0 if it is not an Array Buffer object). -- JSObjectGetArrayBufferByteLength

The API adds the following new typedefs and enumerations:
13) A typedef representing the function pointer type used to deallocate byte pointers provided to constructors. -- JSTypedArrayByesDeallocator
14) An enumeration indicating the Typed Array API type of a JSValueRef. -- JSTypedArrayType

Finally, The API has the following function to get Typed Array Types:
15)  Get the Typed Array type of a JS value. -- JSValueGetTypedArrayType

There are a couple of things to note about these functions. Calling JSObjectGetTypedArrayBytesPtr (5) or
JSObjectGetArrayBufferBytesPtr (12) will pin and lock the ArrayBuffer's data for the remaining lifetime of that
ArrayBuffer. This is because, currently, we do not have finalizers for our Array Buffers or Typed Arrays with a
backing ArrayBuffer and adding one would likely incur a non-trivial cost to GC. Also, we do not have a direct
way to make a Typed Array from a pointer with an offset as we do not expect using offsets to be a common use
case of the API.

While it would have been nice to integrate our backing store with CFData or one of its subclasses, it is not
possible to force a CFData/CFMutableData to be both writable and have a fixed size/backing store pointer.
NSData is not writable and CFMutableData can have a fixed pointer if it is allocated with a non-zero capacity
but there is no way for us to force an existing CFMutableData into this state.

* API/APIUtils.h: Copied from Source/_javascript_Core/runtime/ArrayBuffer.cpp.
(handleExceptionIfNeeded):
(setException):
* API/JSBase.h:
* API/JSObjectRef.cpp:
(handleExceptionIfNeeded): Deleted.
* API/JSTypedArray.cpp: Added.
(toJSTypedArrayType):
(toTypedArrayType):
(createTypedArray):
(JSValueGetTypedArrayType):
(JSObjectMakeTypedArray):
(JSObjectMakeTypedArrayWithBytesNoCopy):
(JSObjectMakeTypedArrayWithArrayBuffer):
(JSObjectMakeTypedArrayWithArrayBufferAndOffset):
(JSObjectGetTypedArrayBytesPtr):
(JSObjectGetTypedArrayLength):
(JSObjectGetTypedArrayByteLength):
(JSObjectGetTypedArrayByteOffset):
(JSObjectGetTypedArrayBuffer):
(JSObjectMakeArrayBufferWithBytesNoCopy):
(JSObjectGetArrayBufferBytesPtr):
(JSObjectGetArrayBufferByteLength):
* API/JSTypedArray.h: Added.
* API/JSValueRef.cpp:
(handleExceptionIfNeeded): Deleted.
* API/JSValueRef.h:
* API/_javascript_.h:
* API/WebKitAvailability.h:
* API/tests/TypedArrayCTest.cpp: Added.
(id):
(freePtr):
(assertEqualsAsNumber):
(testAccess):
(testConstructors):
(forEachTypedArrayType):
(testTypedArrayCAPI):
* API/tests/TypedArrayCTest.h: Added.
* API/tests/testapi.c:
(main):
* CMakeLists.txt:
* ForwardingHeaders/_javascript_Core/JSTypedArray.h: Added.
* _javascript_Core.xcodeproj/project.pbxproj:
* PlatformEfl.cmake:
* PlatformGTK.cmake:
* runtime/ArrayBuffer.cpp:
(JSC::ArrayBuffer::transfer):
* runtime/ArrayBuffer.h:
(JSC::arrayBufferDestructorNull):
(JSC::arrayBufferDestructorDefault):
(JSC::ArrayBufferContents::ArrayBufferContents):
(JSC::ArrayBufferContents::transfer):
(JSC::ArrayBuffer::createAdopted):
(JSC::ArrayBuffer::createFromBytes):
(JSC::ArrayBuffer::ArrayBuffer):
(JSC::ArrayBuffer::pinAndLock):
(JSC::ArrayBufferContents::tryAllocate):
(JSC::ArrayBufferContents::~ArrayBufferContents):
* shell/PlatformWin.cmake:

Modified Paths

Added Paths

Diff

Copied: trunk/Source/_javascript_Core/API/APIUtils.h (from rev 197982, trunk/Source/_javascript_Core/runtime/ArrayBuffer.cpp) (0 => 197983)


--- trunk/Source/_javascript_Core/API/APIUtils.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/APIUtils.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1,63 @@
+/*
+ * 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. ``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
+ * 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 APIUtils_h
+#define APIUtils_h
+
+#include "Exception.h"
+#include "JSCJSValue.h"
+#include "JSGlobalObjectInspectorController.h"
+#include "JSValueRef.h"
+
+enum class ExceptionStatus {
+    DidThrow,
+    DidNotThrow
+};
+
+inline ExceptionStatus handleExceptionIfNeeded(JSC::ExecState* exec, JSValueRef* returnedExceptionRef)
+{
+    if (exec->hadException()) {
+        JSC::Exception* exception = exec->exception();
+        if (returnedExceptionRef)
+            *returnedExceptionRef = toRef(exec, exception->value());
+        exec->clearException();
+#if ENABLE(REMOTE_INSPECTOR)
+        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
+#endif
+        return ExceptionStatus::DidThrow;
+    }
+    return ExceptionStatus::DidNotThrow;
+}
+
+inline void setException(JSC::ExecState* exec, JSValueRef* returnedExceptionRef, JSC::JSValue exception)
+{
+    if (returnedExceptionRef)
+        *returnedExceptionRef = toRef(exec, exception);
+#if ENABLE(REMOTE_INSPECTOR)
+    exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, JSC::Exception::create(exec->vm(), exception));
+#endif
+}
+
+#endif /* APIUtils_h */

Modified: trunk/Source/_javascript_Core/API/JSBase.h (197982 => 197983)


--- trunk/Source/_javascript_Core/API/JSBase.h	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/JSBase.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -57,6 +57,8 @@
 /*! @typedef JSPropertyNameAccumulatorRef An ordered set used to collect the names of a _javascript_ object's properties. */
 typedef struct OpaqueJSPropertyNameAccumulator* JSPropertyNameAccumulatorRef;
 
+/*! @typedef JSTypedArrayBytesDeallocator A function used to deallocate bytes passed to a Typed Array constructor. The function should take two arguments. The first is a pointer to the bytes that were originally passed to the Typed Array constructor. The second is a pointer to additional information desired at the time the bytes are to be freed. */
+typedef void (*JSTypedArrayBytesDeallocator)(void* bytes, void* deallocatorContext);
 
 /* _javascript_ data types */
 

Modified: trunk/Source/_javascript_Core/API/JSObjectRef.cpp (197982 => 197983)


--- trunk/Source/_javascript_Core/API/JSObjectRef.cpp	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/JSObjectRef.cpp	2016-03-11 02:46:03 UTC (rev 197983)
@@ -29,6 +29,7 @@
 #include "JSObjectRefPrivate.h"
 
 #include "APICast.h"
+#include "APIUtils.h"
 #include "ButterflyInlines.h"
 #include "CodeBlock.h"
 #include "CopiedSpaceInlines.h"
@@ -62,26 +63,6 @@
 
 using namespace JSC;
 
-enum class ExceptionStatus {
-    DidThrow,
-    DidNotThrow
-};
-
-static ExceptionStatus handleExceptionIfNeeded(ExecState* exec, JSValueRef* returnedExceptionRef)
-{
-    if (exec->hadException()) {
-        Exception* exception = exec->exception();
-        if (returnedExceptionRef)
-            *returnedExceptionRef = toRef(exec, exception->value());
-        exec->clearException();
-#if ENABLE(REMOTE_INSPECTOR)
-        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
-#endif
-        return ExceptionStatus::DidThrow;
-    }
-    return ExceptionStatus::DidNotThrow;
-}
-
 JSClassRef JSClassCreate(const JSClassDefinition* definition)
 {
     initializeThreading();

Added: trunk/Source/_javascript_Core/API/JSTypedArray.cpp (0 => 197983)


--- trunk/Source/_javascript_Core/API/JSTypedArray.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSTypedArray.cpp	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2015 Dominic Szablewski (domi...@phoboslab.org)
+ * 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 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 "JSTypedArray.h"
+
+#include "APICast.h"
+#include "APIUtils.h"
+#include "ClassInfo.h"
+#include "Error.h"
+#include "JSArrayBufferViewInlines.h"
+#include "JSCJSValueInlines.h"
+#include "JSDataView.h"
+#include "JSGenericTypedArrayViewInlines.h"
+#include "JSTypedArrays.h"
+
+#include <wtf/RefPtr.h>
+
+using namespace JSC;
+
+// Helper functions.
+
+inline JSTypedArrayType toJSTypedArrayType(TypedArrayType type)
+{
+    switch (type) {
+    case JSC::TypeDataView:
+    case NotTypedArray:
+        return kJSTypedArrayTypeNone;
+    case TypeInt8:
+        return kJSTypedArrayTypeInt8Array;
+    case TypeUint8:
+        return kJSTypedArrayTypeUint8Array;
+    case TypeUint8Clamped:
+        return kJSTypedArrayTypeUint8ClampedArray;
+    case TypeInt16:
+        return kJSTypedArrayTypeInt16Array;
+    case TypeUint16:
+        return kJSTypedArrayTypeUint16Array;
+    case TypeInt32:
+        return kJSTypedArrayTypeInt32Array;
+    case TypeUint32:
+        return kJSTypedArrayTypeUint32Array;
+    case TypeFloat32:
+        return kJSTypedArrayTypeFloat32Array;
+    case TypeFloat64:
+        return kJSTypedArrayTypeFloat64Array;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+inline TypedArrayType toTypedArrayType(JSTypedArrayType type)
+{
+    switch (type) {
+    case kJSTypedArrayTypeArrayBuffer:
+    case kJSTypedArrayTypeNone:
+        return NotTypedArray;
+    case kJSTypedArrayTypeInt8Array:
+        return TypeInt8;
+    case kJSTypedArrayTypeUint8Array:
+        return TypeUint8;
+    case kJSTypedArrayTypeUint8ClampedArray:
+        return TypeUint8Clamped;
+    case kJSTypedArrayTypeInt16Array:
+        return TypeInt16;
+    case kJSTypedArrayTypeUint16Array:
+        return TypeUint16;
+    case kJSTypedArrayTypeInt32Array:
+        return TypeInt32;
+    case kJSTypedArrayTypeUint32Array:
+        return TypeUint32;
+    case kJSTypedArrayTypeFloat32Array:
+        return TypeFloat32;
+    case kJSTypedArrayTypeFloat64Array:
+        return TypeFloat64;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+static JSObject* createTypedArray(ExecState* exec, JSTypedArrayType type, RefPtr<ArrayBuffer>&& buffer, size_t offset, size_t length)
+{
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    if (!buffer) {
+        exec->vm().throwException(exec, createOutOfMemoryError(exec));
+        return nullptr;
+    }
+    switch (type) {
+    case kJSTypedArrayTypeInt8Array:
+        return JSInt8Array::create(exec, globalObject->typedArrayStructure(TypeInt8), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeInt16Array:
+        return JSInt16Array::create(exec, globalObject->typedArrayStructure(TypeInt16), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeInt32Array:
+        return JSInt32Array::create(exec, globalObject->typedArrayStructure(TypeInt32), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeUint8Array:
+        return JSUint8Array::create(exec, globalObject->typedArrayStructure(TypeUint8), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeUint8ClampedArray:
+        return JSUint8ClampedArray::create(exec, globalObject->typedArrayStructure(TypeUint8Clamped), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeUint16Array:
+        return JSUint16Array::create(exec, globalObject->typedArrayStructure(TypeUint16), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeUint32Array:
+        return JSUint32Array::create(exec, globalObject->typedArrayStructure(TypeUint32), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeFloat32Array:
+        return JSFloat32Array::create(exec, globalObject->typedArrayStructure(TypeFloat32), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeFloat64Array:
+        return JSFloat64Array::create(exec, globalObject->typedArrayStructure(TypeFloat64), WTFMove(buffer), offset, length);
+    case kJSTypedArrayTypeArrayBuffer:
+    case kJSTypedArrayTypeNone:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    return nullptr;
+}
+
+// Implementations of the API functions.
+
+JSTypedArrayType JSValueGetTypedArrayType(JSContextRef ctx, JSValueRef valueRef, JSValueRef*)
+{
+
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    JSValue value = toJS(exec, valueRef);
+    if (!value.isObject())
+        return kJSTypedArrayTypeNone;
+    JSObject* object = value.getObject();
+
+    if (jsDynamicCast<JSArrayBuffer*>(object))
+        return kJSTypedArrayTypeArrayBuffer;
+
+    return toJSTypedArrayType(object->classInfo()->typedArrayStorageType);
+}
+
+JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t length, JSValueRef* exception)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer)
+        return nullptr;
+
+    unsigned elementByteSize = elementSize(toTypedArrayType(arrayType));
+
+    RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, elementByteSize);
+    JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, length);
+    if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
+        return nullptr;
+    return toRef(result);
+}
+
+JSObjectRef JSObjectMakeTypedArrayWithBytesNoCopy(JSContextRef ctx, JSTypedArrayType arrayType, void* bytes, size_t length, JSTypedArrayBytesDeallocator destructor, void* destructorContext, JSValueRef* exception)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer)
+        return nullptr;
+
+    unsigned elementByteSize = elementSize(toTypedArrayType(arrayType));
+
+    RefPtr<ArrayBuffer> buffer = ArrayBuffer::createFromBytes(bytes, length, [=](void* p) {
+        if (destructor)
+            destructor(p, destructorContext);
+    });
+    JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, length / elementByteSize);
+    if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
+        return nullptr;
+    return toRef(result);
+}
+
+JSObjectRef JSObjectMakeTypedArrayWithArrayBuffer(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef jsBufferRef, JSValueRef* exception)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer)
+        return nullptr;
+
+    JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(toJS(jsBufferRef));
+    if (!jsBuffer) {
+        setException(exec, exception, createTypeError(exec, "JSObjectMakeTypedArrayWithArrayBuffer expects buffer to be an Array Buffer object"));
+        return nullptr;
+    }
+
+    RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
+    unsigned elementByteSize = elementSize(toTypedArrayType(arrayType));
+
+    JSObject* result = createTypedArray(exec, arrayType, WTFMove(buffer), 0, buffer->byteLength() / elementByteSize);
+    if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
+        return nullptr;
+    return toRef(result);
+}
+
+JSObjectRef JSObjectMakeTypedArrayWithArrayBufferAndOffset(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef jsBufferRef, size_t offset, size_t length, JSValueRef* exception)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    if (arrayType == kJSTypedArrayTypeNone || arrayType == kJSTypedArrayTypeArrayBuffer)
+        return nullptr;
+
+    JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(toJS(jsBufferRef));
+    if (!jsBuffer) {
+        setException(exec, exception, createTypeError(exec, "JSObjectMakeTypedArrayWithArrayBuffer expects buffer to be an Array Buffer object"));
+        return nullptr;
+    }
+
+    JSObject* result = createTypedArray(exec, arrayType, jsBuffer->impl(), offset, length);
+    if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
+        return nullptr;
+    return toRef(result);
+}
+
+void* JSObjectGetTypedArrayBytesPtr(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object)) {
+        ArrayBuffer* buffer = typedArray->buffer();
+        buffer->pinAndLock();
+        return buffer->data();
+    }
+    return nullptr;
+}
+
+size_t JSObjectGetTypedArrayLength(JSContextRef, JSObjectRef objectRef, JSValueRef*)
+{
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object))
+        return typedArray->length();
+
+    return 0;
+}
+
+size_t JSObjectGetTypedArrayByteLength(JSContextRef, JSObjectRef objectRef, JSValueRef*)
+{
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object))
+        return typedArray->length() * elementSize(typedArray->classInfo()->typedArrayStorageType);
+
+    return 0;
+}
+
+size_t JSObjectGetTypedArrayByteOffset(JSContextRef, JSObjectRef objectRef, JSValueRef*)
+{
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object))
+        return typedArray->byteOffset();
+
+    return 0;
+}
+
+JSObjectRef JSObjectGetTypedArrayBuffer(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBufferView* typedArray = jsDynamicCast<JSArrayBufferView*>(object))
+        return toRef(exec->vm().m_typedArrayController->toJS(exec, typedArray->globalObject(), typedArray->buffer()));
+
+    return nullptr;
+}
+
+JSObjectRef JSObjectMakeArrayBufferWithBytesNoCopy(JSContextRef ctx, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+
+    RefPtr<ArrayBuffer> buffer = ArrayBuffer::createFromBytes(bytes, byteLength, [=](void* p) {
+        if (bytesDeallocator)
+            bytesDeallocator(p, deallocatorContext);
+    });
+
+    JSArrayBuffer* jsBuffer = JSArrayBuffer::create(exec->vm(), exec->lexicalGlobalObject()->arrayBufferStructure(), WTFMove(buffer));
+    if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow)
+        return nullptr;
+
+    return toRef(jsBuffer);
+}
+
+void* JSObjectGetArrayBufferBytesPtr(JSContextRef ctx, JSObjectRef objectRef, JSValueRef*)
+{
+    ExecState* exec = toJS(ctx);
+    JSLockHolder locker(exec);
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(object)) {
+        ArrayBuffer* buffer = jsBuffer->impl();
+        buffer->pinAndLock();
+        return buffer->data();
+    }
+    return nullptr;
+}
+
+size_t JSObjectGetArrayBufferByteLength(JSContextRef, JSObjectRef objectRef, JSValueRef*)
+{
+    JSObject* object = toJS(objectRef);
+
+    if (JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(object))
+        return jsBuffer->impl()->byteLength();
+    
+    return 0;
+}

Added: trunk/Source/_javascript_Core/API/JSTypedArray.h (0 => 197983)


--- trunk/Source/_javascript_Core/API/JSTypedArray.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSTypedArray.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2015 Dominic Szablewski (domi...@phoboslab.org)
+ * Copyright (C) 2015-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 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
+
+#include <_javascript_Core/JSBase.h>
+#include <_javascript_Core/JSValueRef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ------------- Typed Array functions --------------
+
+/*!
+ @function
+ @abstract           Creates a _javascript_ Typed Array object with the given number of elements.
+ @param ctx          The execution context to use.
+ @param arrayType    A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
+ @param length       The number of elements to be in the new Typed Array.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             A JSObjectRef that is a Typed Array with all elements set to zero or NULL if there was an error.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t length, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract                 Creates a _javascript_ Typed Array object from an existing pointer.
+ @param ctx                The execution context to use.
+ @param arrayType          A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
+ @param bytes              A pointer to the byte buffer to be used as the backing store of the Typed Array object.
+ @param byteLength         The number of bytes pointed to by the parameter bytes.
+ @param bytesDeallocator   The allocator to use to deallocate the external buffer when the JSTypedArrayData object is deallocated.
+ @param deallocatorContext A pointer to pass back to the deallocator.
+ @param exception          A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result                   A JSObjectRef Typed Array whose backing store is the same as the one pointed to by bytes or NULL if there was an error.
+ @discussion               If an exception is thrown during this function the bytesDeallocator will always be called.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithBytesNoCopy(JSContextRef ctx, JSTypedArrayType arrayType, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Creates a _javascript_ Typed Array object from an existing _javascript_ Array Buffer object.
+ @param ctx          The execution context to use.
+ @param arrayType    A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
+ @param buffer       An Array Buffer object that should be used as the backing store for the created _javascript_ Typed Array object.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             A JSObjectRef that is a Typed Array or NULL if there was an error. The backing store of the Typed Array will be buffer.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithArrayBuffer(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef buffer, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Creates a _javascript_ Typed Array object from an existing _javascript_ Array Buffer object with the given offset and length.
+ @param ctx          The execution context to use.
+ @param arrayType    A value identifying the type of array to create. If arrayType is kJSTypedArrayTypeNone or kJSTypedArrayTypeArrayBuffer then NULL will be returned.
+ @param buffer       An Array Buffer object that should be used as the backing store for the created _javascript_ Typed Array object.
+ @param byteOffset   The byte offset for the created Typed Array. byteOffset should aligned with the element size of arrayType.
+ @param length       The number of elements to include in the Typed Array.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             A JSObjectRef that is a Typed Array or NULL if there was an error. The backing store of the Typed Array will be buffer.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeTypedArrayWithArrayBufferAndOffset(JSContextRef ctx, JSTypedArrayType arrayType, JSObjectRef buffer, size_t byteOffset, size_t length, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Returns a temporary pointer to the backing store of a _javascript_ Typed Array object.
+ @param ctx          The execution context to use.
+ @param object       The Typed Array object whose backing store pointer to return.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             A pointer to the raw data buffer that serves as object's backing store or NULL if object is not a Typed Array object.
+ @discussion         The pointer returned by this function is temporary and is not guaranteed to remain valid across _javascript_Core API calls.
+ */
+JS_EXPORT void* JSObjectGetTypedArrayBytesPtr(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Returns the length of a _javascript_ Typed Array object.
+ @param ctx          The execution context to use.
+ @param object       The Typed Array object whose length to return.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             The length of the Typed Array object or 0 if the object is not a Typed Array object.
+ */
+JS_EXPORT size_t JSObjectGetTypedArrayLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Returns the byte length of a _javascript_ Typed Array object.
+ @param ctx          The execution context to use.
+ @param object       The Typed Array object whose byte length to return.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             The byte length of the Typed Array object or 0 if the object is not a Typed Array object.
+ */
+JS_EXPORT size_t JSObjectGetTypedArrayByteLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Returns the byte offset of a _javascript_ Typed Array object.
+ @param ctx          The execution context to use.
+ @param object       The Typed Array object whose byte offset to return.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             The byte offset of the Typed Array object or 0 if the object is not a Typed Array object.
+ */
+JS_EXPORT size_t JSObjectGetTypedArrayByteOffset(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract           Returns the _javascript_ Array Buffer object that is used as the backing of a _javascript_ Typed Array object.
+ @param ctx          The execution context to use.
+ @param object       The JSObjectRef whose Typed Array type data pointer to obtain.
+ @param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result             A JSObjectRef with a JSTypedArrayType of kJSTypedArrayTypeArrayBuffer or NULL if object is not a Typed Array.
+ */
+JS_EXPORT JSObjectRef JSObjectGetTypedArrayBuffer(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+// ------------- Array Buffer functions -------------
+
+/*!
+ @function
+ @abstract                 Creates a _javascript_ Array Buffer object from an existing pointer.
+ @param ctx                The execution context to use.
+ @param bytes              A pointer to the byte buffer to be used as the backing store of the Typed Array object.
+ @param byteLength         The number of bytes pointed to by the parameter bytes.
+ @param bytesDeallocator   The allocator to use to deallocate the external buffer when the Typed Array data object is deallocated.
+ @param deallocatorContext A pointer to pass back to the deallocator.
+ @param exception          A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result                   A JSObjectRef Array Buffer whose backing store is the same as the one pointed to by bytes or NULL if there was an error.
+ @discussion               If an exception is thrown during this function the bytesDeallocator will always be called.
+ */
+JS_EXPORT JSObjectRef JSObjectMakeArrayBufferWithBytesNoCopy(JSContextRef ctx, void* bytes, size_t byteLength, JSTypedArrayBytesDeallocator bytesDeallocator, void* deallocatorContext, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract         Returns a pointer to the data buffer that serves as the backing store for a _javascript_ Typed Array object.
+ @param buffer     The Array Buffer object whose internal backing store pointer to return.
+ @param exception  A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result           A pointer to the raw data buffer that serves as object's backing store or NULL if object is not an Array Buffer object.
+ @discussion       The pointer returned by this function is temporary and is not guaranteed to remain valid across _javascript_Core API calls.
+ */
+JS_EXPORT void* JSObjectGetArrayBufferBytesPtr(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+/*!
+ @function
+ @abstract         Returns the number of bytes in a _javascript_ data object.
+ @param ctx        The execution context to use.
+ @param object     The JS Arary Buffer object whose length in bytes to return.
+ @param exception  A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+ @result           The number of bytes stored in the data object.
+ */
+JS_EXPORT size_t JSObjectGetArrayBufferByteLength(JSContextRef ctx, JSObjectRef object, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JSTypedArray_h */

Modified: trunk/Source/_javascript_Core/API/JSValueRef.cpp (197982 => 197983)


--- trunk/Source/_javascript_Core/API/JSValueRef.cpp	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/JSValueRef.cpp	2016-03-11 02:46:03 UTC (rev 197983)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 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
@@ -27,6 +27,7 @@
 #include "JSValueRef.h"
 
 #include "APICast.h"
+#include "APIUtils.h"
 #include "DateInstance.h"
 #include "Exception.h"
 #include "JSAPIWrapperObject.h"
@@ -53,26 +54,6 @@
 
 using namespace JSC;
 
-enum class ExceptionStatus {
-    DidThrow,
-    DidNotThrow
-};
-
-static ExceptionStatus handleExceptionIfNeeded(ExecState* exec, JSValueRef* returnedExceptionRef)
-{
-    if (exec->hadException()) {
-        Exception* exception = exec->exception();
-        if (returnedExceptionRef)
-            *returnedExceptionRef = toRef(exec, exception->value());
-        exec->clearException();
-#if ENABLE(REMOTE_INSPECTOR)
-        exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exception);
-#endif
-        return ExceptionStatus::DidThrow;
-    }
-    return ExceptionStatus::DidNotThrow;
-}
-
 #if PLATFORM(MAC)
 static bool evernoteHackNeeded()
 {

Modified: trunk/Source/_javascript_Core/API/JSValueRef.h (197982 => 197983)


--- trunk/Source/_javascript_Core/API/JSValueRef.h	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/JSValueRef.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -52,6 +52,36 @@
     kJSTypeObject
 } JSType;
 
+/*!
+ @enum JSTypedArrayType
+ @abstract     A constant identifying the Typed Array type of a JSObjectRef.
+ @constant     kJSTypedArrayTypeInt8Array            Int8Array
+ @constant     kJSTypedArrayTypeInt16Array           Int16Array
+ @constant     kJSTypedArrayTypeInt32Array           Int32Array
+ @constant     kJSTypedArrayTypeUint8Array           Uint8Array
+ @constant     kJSTypedArrayTypeUint8ClampedArray    Uint8ClampedArray
+ @constant     kJSTypedArrayTypeUint16Array          Uint16Array
+ @constant     kJSTypedArrayTypeUint32Array          Uint32Array
+ @constant     kJSTypedArrayTypeFloat32Array         Float32Array
+ @constant     kJSTypedArrayTypeFloat64Array         Float64Array
+ @constant     kJSTypedArrayTypeArrayBuffer          ArrayBuffer
+ @constant     kJSTypedArrayTypeNone                 Not a Typed Array
+
+ */
+typedef enum {
+    kJSTypedArrayTypeInt8Array,
+    kJSTypedArrayTypeInt16Array,
+    kJSTypedArrayTypeInt32Array,
+    kJSTypedArrayTypeUint8Array,
+    kJSTypedArrayTypeUint8ClampedArray,
+    kJSTypedArrayTypeUint16Array,
+    kJSTypedArrayTypeUint32Array,
+    kJSTypedArrayTypeFloat32Array,
+    kJSTypedArrayTypeFloat64Array,
+    kJSTypedArrayTypeArrayBuffer,
+    kJSTypedArrayTypeNone,
+} JSTypedArrayType CF_ENUM_AVAILABLE(10_12, 10_0);
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -147,6 +177,16 @@
 */
 JS_EXPORT bool JSValueIsDate(JSContextRef ctx, JSValueRef value) CF_AVAILABLE(10_11, 9_0);
 
+/*!
+@function
+@abstract           Returns a _javascript_ value's Typed Array type.
+@param ctx          The execution context to use.
+@param value        The JSValue whose Typed Array type to return.
+@param exception    A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception.
+@result             A value of type JSTypedArrayType that identifies value's Typed Array type, or kJSTypedArrayTypeNone if the value is not a Typed Array object.
+ */
+JS_EXPORT JSTypedArrayType JSValueGetTypedArrayType(JSContextRef ctx, JSValueRef value, JSValueRef* exception) CF_AVAILABLE(10_12, 10_0);
+
 /* Comparing values */
 
 /*!

Modified: trunk/Source/_javascript_Core/API/_javascript_.h (197982 => 197983)


--- trunk/Source/_javascript_Core/API/_javascript_.h	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/_javascript_.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -31,6 +31,7 @@
 #include <_javascript_Core/JSContextRef.h>
 #include <_javascript_Core/JSStringRef.h>
 #include <_javascript_Core/JSObjectRef.h>
+#include <_javascript_Core/JSTypedArray.h>
 #include <_javascript_Core/JSValueRef.h>
 
 #endif /* _javascript__h */

Modified: trunk/Source/_javascript_Core/API/WebKitAvailability.h (197982 => 197983)


--- trunk/Source/_javascript_Core/API/WebKitAvailability.h	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/WebKitAvailability.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -67,10 +67,13 @@
 #if defined(BUILDING_GTK__)
 #undef CF_AVAILABLE
 #define CF_AVAILABLE(_mac, _ios)
+#undef CF_ENUM_AVAILABLE
+#define CF_ENUM_AVAILABLE(_mac, _ios)
 #endif
 
 #else
 #define CF_AVAILABLE(_mac, _ios)
+#define CF_ENUM_AVAILABLE(_mac, _ios)
 #endif
 
 #endif /* __WebKitAvailability__ */

Added: trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.cpp (0 => 197983)


--- trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.cpp	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "TypedArrayCTest.h"
+
+#include "_javascript_Core.h"
+#include <wtf/Assertions.h>
+
+extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
+
+static void id(void*, void*) { }
+static void freePtr(void* ptr, void*)
+{
+    free(ptr);
+}
+
+static const unsigned numLengths = 3;
+
+static const unsigned lengths[numLengths] =
+{
+    0,
+    1,
+    10,
+};
+
+static const unsigned byteSizes[kJSTypedArrayTypeNone] =
+{
+    1, // kJSTypedArrayTypeInt8Array
+    2, // kJSTypedArrayTypeInt16Array
+    4, // kJSTypedArrayTypeInt32Array
+    1, // kJSTypedArrayTypeUint8Array
+    1, // kJSTypedArrayTypeUint8ClampedArray
+    2, // kJSTypedArrayTypeUint16Array
+    4, // kJSTypedArrayTypeUint32Array
+    4, // kJSTypedArrayTypeFloat32Array
+    8, // kJSTypedArrayTypeFloat64Array
+};
+
+static const char* typeToString[kJSTypedArrayTypeNone] =
+{
+
+    "kJSTypedArrayTypeInt8Array",
+    "kJSTypedArrayTypeInt16Array",
+    "kJSTypedArrayTypeInt32Array",
+    "kJSTypedArrayTypeUint8Array",
+    "kJSTypedArrayTypeUint8ClampedArray",
+    "kJSTypedArrayTypeUint16Array",
+    "kJSTypedArrayTypeUint32Array",
+    "kJSTypedArrayTypeFloat32Array",
+    "kJSTypedArrayTypeFloat64Array",
+};
+
+inline int unexpectedException(const char* name)
+{
+    fprintf(stderr, "%s FAILED: unexpected exception\n", name);
+    return 1;
+}
+
+static int assertEqualsAsNumber(JSGlobalContextRef context, JSValueRef value, double expectedValue)
+{
+    double number = JSValueToNumber(context, value, nullptr);
+    if (number != expectedValue && !(isnan(number) && isnan(expectedValue))) {
+        fprintf(stderr, "assertEqualsAsNumber FAILED: %p, %lf\n", value, expectedValue);
+        return 1;
+    }
+    return 0;
+}
+
+static int testAccess(JSGlobalContextRef context, JSObjectRef typedArray, JSTypedArrayType type, unsigned elementLength, void* expectedPtr = nullptr, JSObjectRef expectedBuffer = nullptr, unsigned expectedOffset = 0)
+{
+    JSValueRef exception;
+    // Test typedArray basic functions.
+    JSTypedArrayType actualType = JSValueGetTypedArrayType(context, typedArray, &exception);
+    if (type != actualType || exception) {
+        fprintf(stderr, "TypedArray type FAILED: %p, got: %s, expected: %s\n", typedArray, typeToString[actualType], typeToString[type]);
+        return 1;
+    }
+
+    unsigned length = JSObjectGetTypedArrayLength(context, typedArray, &exception);
+    if (elementLength != length || exception) {
+        fprintf(stderr, "TypedArray length FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], length, elementLength);
+        return 1;
+    }
+
+    unsigned byteLength = JSObjectGetTypedArrayByteLength(context, typedArray, &exception);
+    unsigned expectedLength = byteSizes[type] * elementLength;
+    if (byteLength != expectedLength || exception) {
+        fprintf(stderr, "TypedArray byteLength FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], byteLength, expectedLength);
+        return 1;
+    }
+
+    unsigned offset = JSObjectGetTypedArrayByteOffset(context, typedArray, &exception);
+    if (expectedOffset != offset || exception) {
+        fprintf(stderr, "TypedArray byteOffset FAILED: %p (%s), got: %d, expected: %d\n", typedArray, typeToString[type], offset, expectedOffset);
+        return 1;
+    }
+
+    void* ptr = JSObjectGetTypedArrayBytesPtr(context, typedArray, &exception);
+    if (exception)
+        return unexpectedException("TypedArray get bytes ptr");
+
+    JSObjectRef buffer = JSObjectGetTypedArrayBuffer(context, typedArray, &exception);
+    if (exception)
+        return unexpectedException("TypedArray get buffer");
+
+    void* bufferPtr = JSObjectGetArrayBufferBytesPtr(context, buffer, &exception);
+    if (exception)
+        return unexpectedException("ArrayBuffer get bytes ptr");
+
+    if (bufferPtr != ptr) {
+        fprintf(stderr, "FAIL: TypedArray bytes ptr and ArrayBuffer byte ptr were not the same: %p (%s) TypedArray: %p, ArrayBuffer: %p\n", typedArray, typeToString[type], ptr, bufferPtr);
+        return 1;
+    }
+
+    if (expectedPtr && ptr != expectedPtr) {
+        fprintf(stderr, "FAIL: TypedArray bytes ptr and the ptr used to construct the array were not the same: %p (%s) TypedArray: %p, bytes ptr: %p\n", typedArray, typeToString[type], ptr, expectedPtr);
+        return 1;
+    }
+
+    if (expectedBuffer && expectedBuffer != buffer) {
+        fprintf(stderr, "FAIL: TypedArray buffer and the ArrayBuffer buffer used to construct the array were not the same: %p (%s) TypedArray buffer: %p, data: %p\n", typedArray, typeToString[type], buffer, expectedBuffer);
+        return 1;
+    }
+
+    return 0;
+}
+
+static int testConstructors(JSGlobalContextRef context, JSTypedArrayType type, unsigned length)
+{
+    int failed = 0;
+    JSValueRef exception;
+    JSObjectRef typedArray;
+
+    // Test create with length.
+    typedArray = JSObjectMakeTypedArray(context, type, length, &exception);
+    failed = failed || exception || testAccess(context, typedArray, type, length);
+
+    void* ptr = calloc(length, byteSizes[type]); // This is to be freed by data
+    JSObjectRef data = "" ptr, length * byteSizes[type], freePtr, nullptr, &exception);
+    failed = failed || exception;
+
+    // Test create with existing ptr.
+    typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, type, ptr, length * byteSizes[type], id, nullptr, &exception);
+    failed = failed || exception || testAccess(context, typedArray, type, length, ptr);
+
+    // Test create with existing ArrayBuffer.
+    typedArray = JSObjectMakeTypedArrayWithArrayBuffer(context, type, data, &exception);
+    failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data);
+
+    // Test create with existing ArrayBuffer and offset.
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 0, length, &exception);
+    failed = failed || exception || testAccess(context, typedArray, type, length, ptr, data);
+
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length-1, &exception);
+    if (!length)
+        failed = failed || !exception;
+    else
+        failed = failed || testAccess(context, typedArray, type, length-1, ptr, data, byteSizes[type]) || exception;
+
+    exception = nullptr;
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 3, &exception);
+    if (length < 2)
+        failed = failed || !exception;
+    else
+        failed = failed || testAccess(context, typedArray, type, 3, ptr, data, byteSizes[type]) || exception;
+
+    if (byteSizes[type] > 1) {
+        exception = nullptr;
+        typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, 1, length-1, &exception);
+        failed = failed || !exception;
+    }
+
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], length, &exception);
+    failed = failed || !exception;
+
+    exception = nullptr;
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, type, data, byteSizes[type], 0, &exception);
+    if (!length)
+        failed = failed || !exception;
+    else
+        failed = failed || testAccess(context, typedArray, type, 0, ptr, data, byteSizes[type]) || exception;
+
+    return failed;
+}
+
+template <typename Functor>
+static int forEachTypedArrayType(const Functor& functor)
+{
+    int failed = 0;
+    for (unsigned i = 0; i < kJSTypedArrayTypeNone; i++)
+        failed = failed || functor(static_cast<JSTypedArrayType>(i));
+    return failed;
+}
+
+int testTypedArrayCAPI()
+{
+    int failed = 0;
+    JSGlobalContextRef context = JSGlobalContextCreate(nullptr);
+
+    failed = failed || forEachTypedArrayType([&](JSTypedArrayType type) {
+        int failed = 0;
+        for (unsigned i = 0; i < numLengths; i++)
+            failed = failed || testConstructors(context, type, lengths[i]);
+        return failed;
+    });
+
+    // Test making a typedArray from scratch length.
+    volatile JSObjectRef typedArray = JSObjectMakeTypedArray(context, kJSTypedArrayTypeUint32Array, 10, nullptr);
+    JSObjectRef data = "" typedArray, nullptr);
+    unsigned* buffer = static_cast<unsigned*>(JSObjectGetArrayBufferBytesPtr(context, data, nullptr));
+
+    ASSERT(JSObjectGetTypedArrayLength(context, typedArray, nullptr) == 10);
+
+    // Test buffer is connected to typedArray.
+    buffer[1] = 1;
+    JSValueRef v = JSObjectGetPropertyAtIndex(context, typedArray, 1, nullptr);
+    failed = failed || assertEqualsAsNumber(context, v, 1);
+
+    // Test passing a buffer from a new array to an old array
+    typedArray = JSObjectMakeTypedArrayWithBytesNoCopy(context, kJSTypedArrayTypeUint32Array, buffer, 40, id, nullptr, nullptr);
+    buffer = static_cast<unsigned*>(JSObjectGetTypedArrayBytesPtr(context, typedArray, nullptr));
+    ASSERT(buffer[1] == 1);
+    buffer[1] = 20;
+    ASSERT(((unsigned*)JSObjectGetArrayBufferBytesPtr(context, data, nullptr))[1] == 20);
+
+    // Test constructing with data and the data returned are the same even with an offset.
+    typedArray = JSObjectMakeTypedArrayWithArrayBufferAndOffset(context, kJSTypedArrayTypeUint32Array, data, 4, 9, nullptr);
+    failed = failed || assertEqualsAsNumber(context, JSObjectGetPropertyAtIndex(context, typedArray, 0, nullptr), 20);
+    ASSERT(data == JSObjectGetTypedArrayBuffer(context, typedArray, nullptr));
+
+    // Test attempting to allocate an array too big for memory.
+    forEachTypedArrayType([&](JSTypedArrayType type) {
+        JSValueRef exception = nullptr;
+        JSObjectMakeTypedArray(context, type, UINT_MAX, &exception);
+        return !exception;
+    });
+
+    JSGlobalContextRelease(context);
+
+    if (!failed)
+        printf("PASS: Typed Array C API Tests.\n");
+
+    return failed;
+}

Added: trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.h (0 => 197983)


--- trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/TypedArrayCTest.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+
+#ifndef TypedArrayCTest_h
+#define TypedArrayCTest_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int testTypedArrayCAPI(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* TypedArrayCTest_h */

Modified: trunk/Source/_javascript_Core/API/tests/testapi.c (197982 => 197983)


--- trunk/Source/_javascript_Core/API/tests/testapi.c	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/API/tests/testapi.c	2016-03-11 02:46:03 UTC (rev 197983)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2015 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006, 2015-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
@@ -44,13 +44,13 @@
 #include "ExecutionTimeLimitTest.h"
 #include "GlobalContextWithFinalizerTest.h"
 #include "PingPongStackOverflowTest.h"
+#include "TypedArrayCTest.h"
 
 #if JSC_OBJC_API_ENABLED
 void testObjectiveCAPI(void);
 #endif
 
 bool assertTrue(bool value, const char* message);
-extern void JSSynchronousGarbageCollectForDebugging(JSContextRef);
 
 static JSGlobalContextRef context;
 int failed;
@@ -1113,7 +1113,6 @@
     val.name = "something";
 }
 
-
 int main(int argc, char* argv[])
 {
 #if OS(WINDOWS)
@@ -1138,6 +1137,8 @@
     testObjectiveCAPI();
 #endif
 
+
+
     const char *scriptPath = "testapi.js";
     if (argc > 1) {
         scriptPath = argv[1];
@@ -1891,6 +1892,7 @@
         JSGlobalContextRelease(context);
     }
 
+    failed = testTypedArrayCAPI() || failed;
     failed = testExecutionTimeLimit() || failed;
     failed = testGlobalContextWithFinalizer() || failed;
     failed = testPingPongStackOverflow() || failed;

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (197982 => 197983)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2016-03-11 02:46:03 UTC (rev 197983)
@@ -54,6 +54,7 @@
     API/JSContextRef.cpp
     API/JSObjectRef.cpp
     API/JSProfilerPrivate.cpp
+    API/JSTypedArray.cpp
     API/JSScriptRef.cpp
     API/JSStringRef.cpp
     API/JSValueRef.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (197982 => 197983)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-11 02:46:03 UTC (rev 197983)
@@ -1,3 +1,117 @@
+2016-03-10  Keith Miller  <keith_mil...@apple.com>
+
+        Typed Arrays have no public facing API
+        https://bugs.webkit.org/show_bug.cgi?id=120112
+
+        Reviewed by Geoffrey Garen.
+
+        This patch adds a new C-API (an Obj-C API will follow in the future) for Typed Arrays. The API has two sets of
+        functions. One for Typed Arrays and another for Array Buffers. This API is intended to reflect the use of Typed
+        Array objects in JS code. There is a method for each of the core TypedArray and Array Buffer methods.
+        Originally, we were planning on using a separate non-JS object as the backing store instead of a JS Array Buffer
+        but we decide to defer that idea since there was no good CF/NS API that met all the constraints we needed
+        (Discussed further below). We also wanted to want until Shared Array Buffers had reached a more finished state
+        to see what impact they might have on an API.
+
+        The API has the following Typed Array construction methods:
+        1) Create with length (the backing buffer is zero initialized). -- JSObjectMakeTypedArray
+        2) Create with an existing pointer and a destructor. -- JSObjectMakeTypedArrayFromBytesNoCopy
+        3) Create with an Array Buffer object. -- JSObjectMakeTypedArrayFromArrayBuffer
+        4) Create with an Array Buffer object with a given offset and length. -- JSObjectMakeTypedArrayFromArrayBufferWithOffset
+
+        The API has the following functions on Typed Array JSObjectRefs:
+        5) Get access to a temporary void* of the backing store's data. -- JSObjectGetTypedArrayBytesPtr
+        6) Get the length of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayLength
+        7) Get the byte length of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayByteLength
+        8) Get the byte offset of a Typed Array object (returns 0 if it is not a Typed Array object). -- JSObjectGetTypedArrayByteOffset
+        9) Get a Typed Array object's Array Buffer  backing store. -- JSObjectGetTypedArrayBuffer
+
+        The API has the following Array Buffer construction method:
+        10) Create with an existing pointer and a destructor. -- JSObjectMakeArrayBufferWithBytesNoCopy
+
+        The API has the following functions on Array Buffer JSObjectRefs:
+        11) Get access to a temporary void* of the backing store's data. -- JSObjectGetArrayBufferBytesPtr
+        12) Get the byte length of an Array Buffer object (returns 0 if it is not an Array Buffer object). -- JSObjectGetArrayBufferByteLength
+
+        The API adds the following new typedefs and enumerations:
+        13) A typedef representing the function pointer type used to deallocate byte pointers provided to constructors. -- JSTypedArrayByesDeallocator
+        14) An enumeration indicating the Typed Array API type of a JSValueRef. -- JSTypedArrayType
+
+        Finally, The API has the following function to get Typed Array Types:
+        15)  Get the Typed Array type of a JS value. -- JSValueGetTypedArrayType
+
+        There are a couple of things to note about these functions. Calling JSObjectGetTypedArrayBytesPtr (5) or
+        JSObjectGetArrayBufferBytesPtr (12) will pin and lock the ArrayBuffer's data for the remaining lifetime of that
+        ArrayBuffer. This is because, currently, we do not have finalizers for our Array Buffers or Typed Arrays with a
+        backing ArrayBuffer and adding one would likely incur a non-trivial cost to GC. Also, we do not have a direct
+        way to make a Typed Array from a pointer with an offset as we do not expect using offsets to be a common use
+        case of the API.
+
+        While it would have been nice to integrate our backing store with CFData or one of its subclasses, it is not
+        possible to force a CFData/CFMutableData to be both writable and have a fixed size/backing store pointer.
+        NSData is not writable and CFMutableData can have a fixed pointer if it is allocated with a non-zero capacity
+        but there is no way for us to force an existing CFMutableData into this state.
+
+        * API/APIUtils.h: Copied from Source/_javascript_Core/runtime/ArrayBuffer.cpp.
+        (handleExceptionIfNeeded):
+        (setException):
+        * API/JSBase.h:
+        * API/JSObjectRef.cpp:
+        (handleExceptionIfNeeded): Deleted.
+        * API/JSTypedArray.cpp: Added.
+        (toJSTypedArrayType):
+        (toTypedArrayType):
+        (createTypedArray):
+        (JSValueGetTypedArrayType):
+        (JSObjectMakeTypedArray):
+        (JSObjectMakeTypedArrayWithBytesNoCopy):
+        (JSObjectMakeTypedArrayWithArrayBuffer):
+        (JSObjectMakeTypedArrayWithArrayBufferAndOffset):
+        (JSObjectGetTypedArrayBytesPtr):
+        (JSObjectGetTypedArrayLength):
+        (JSObjectGetTypedArrayByteLength):
+        (JSObjectGetTypedArrayByteOffset):
+        (JSObjectGetTypedArrayBuffer):
+        (JSObjectMakeArrayBufferWithBytesNoCopy):
+        (JSObjectGetArrayBufferBytesPtr):
+        (JSObjectGetArrayBufferByteLength):
+        * API/JSTypedArray.h: Added.
+        * API/JSValueRef.cpp:
+        (handleExceptionIfNeeded): Deleted.
+        * API/JSValueRef.h:
+        * API/_javascript_.h:
+        * API/WebKitAvailability.h:
+        * API/tests/TypedArrayCTest.cpp: Added.
+        (id):
+        (freePtr):
+        (assertEqualsAsNumber):
+        (testAccess):
+        (testConstructors):
+        (forEachTypedArrayType):
+        (testTypedArrayCAPI):
+        * API/tests/TypedArrayCTest.h: Added.
+        * API/tests/testapi.c:
+        (main):
+        * CMakeLists.txt:
+        * ForwardingHeaders/_javascript_Core/JSTypedArray.h: Added.
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * PlatformEfl.cmake:
+        * PlatformGTK.cmake:
+        * runtime/ArrayBuffer.cpp:
+        (JSC::ArrayBuffer::transfer):
+        * runtime/ArrayBuffer.h:
+        (JSC::arrayBufferDestructorNull):
+        (JSC::arrayBufferDestructorDefault):
+        (JSC::ArrayBufferContents::ArrayBufferContents):
+        (JSC::ArrayBufferContents::transfer):
+        (JSC::ArrayBuffer::createAdopted):
+        (JSC::ArrayBuffer::createFromBytes):
+        (JSC::ArrayBuffer::ArrayBuffer):
+        (JSC::ArrayBuffer::pinAndLock):
+        (JSC::ArrayBufferContents::tryAllocate):
+        (JSC::ArrayBufferContents::~ArrayBufferContents):
+        * shell/PlatformWin.cmake:
+
 2016-03-10  Saam barati  <sbar...@apple.com>
 
         [ES6] Instanceof isn't spec compliant when the RHS is a Proxy with a target that is a function

Added: trunk/Source/_javascript_Core/ForwardingHeaders/_javascript_Core/JSTypedArray.h (0 => 197983)


--- trunk/Source/_javascript_Core/ForwardingHeaders/_javascript_Core/JSTypedArray.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/ForwardingHeaders/_javascript_Core/JSTypedArray.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -0,0 +1 @@
+#include <API/JSTypedArray.h>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (197982 => 197983)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2016-03-11 02:46:03 UTC (rev 197983)
@@ -1177,8 +1177,12 @@
 		52C0611F1AA51E1C00B4ADBA /* RuntimeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		52C952B719A289850069B386 /* TypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 52C952B619A289850069B386 /* TypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52C952B819A28A1C0069B386 /* TypeProfiler.cpp */; };
+		53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; };
+		534902851C7276B70012BCB8 /* TypedArrayCTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534902821C7242C80012BCB8 /* TypedArrayCTest.cpp */; };
 		534C457C1BC72411007476A7 /* JSTypedArrayViewConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 534C457B1BC72411007476A7 /* JSTypedArrayViewConstructor.h */; };
 		534C457E1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */; };
+		53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 53529A4B1C457B75000B49C6 /* APIUtils.h */; };
 		5370B4F51BF26202005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */; };
 		5370B4F61BF26205005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */; };
 		53917E7B1B7906FA000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */; };
@@ -3300,9 +3304,14 @@
 		52C0611D1AA51E1B00B4ADBA /* RuntimeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeType.h; sourceTree = "<group>"; };
 		52C952B619A289850069B386 /* TypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeProfiler.h; sourceTree = "<group>"; };
 		52C952B819A28A1C0069B386 /* TypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeProfiler.cpp; sourceTree = "<group>"; };
+		53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = "<group>"; };
+		53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = "<group>"; };
+		534902821C7242C80012BCB8 /* TypedArrayCTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypedArrayCTest.cpp; path = API/tests/TypedArrayCTest.cpp; sourceTree = "<group>"; };
+		534902831C7242C80012BCB8 /* TypedArrayCTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypedArrayCTest.h; path = API/tests/TypedArrayCTest.h; sourceTree = "<group>"; };
 		534C457A1BC703DC007476A7 /* TypedArrayConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = TypedArrayConstructor.js; sourceTree = "<group>"; };
 		534C457B1BC72411007476A7 /* JSTypedArrayViewConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArrayViewConstructor.h; sourceTree = "<group>"; };
 		534C457D1BC72549007476A7 /* JSTypedArrayViewConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewConstructor.cpp; sourceTree = "<group>"; };
+		53529A4B1C457B75000B49C6 /* APIUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIUtils.h; sourceTree = "<group>"; };
 		5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdaptiveInferredPropertyValueWatchpointBase.cpp; sourceTree = "<group>"; };
 		5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdaptiveInferredPropertyValueWatchpointBase.h; sourceTree = "<group>"; };
 		53917E7A1B7906E4000EBD33 /* JSGenericTypedArrayViewPrototypeFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGenericTypedArrayViewPrototypeFunctions.h; sourceTree = "<group>"; };
@@ -4896,6 +4905,8 @@
 				FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */,
 				FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */,
 				C29ECB021804D0ED00D2CBB4 /* CurrentThisInsideBlockGetterTest.h */,
+				534902821C7242C80012BCB8 /* TypedArrayCTest.cpp */,
+				534902831C7242C80012BCB8 /* TypedArrayCTest.h */,
 				C29ECB011804D0ED00D2CBB4 /* CurrentThisInsideBlockGetterTest.mm */,
 				C203281E1981979D0088B499 /* CustomGlobalObjectClassTest.c */,
 				C203281F1981979D0088B499 /* CustomGlobalObjectClassTest.h */,
@@ -5183,6 +5194,7 @@
 			children = (
 				C211B574176A224D000E2A23 /* APICallbackFunction.h */,
 				1482B78A0A4305AB00517CFC /* APICast.h */,
+				53529A4B1C457B75000B49C6 /* APIUtils.h */,
 				1CAA8B4A0D32C39A0041BCFF /* _javascript_.h */,
 				1CAA8B4B0D32C39A0041BCFF /* _javascript_Core.h */,
 				BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */,
@@ -5231,6 +5243,8 @@
 				146AAB370B66A94400E55F16 /* JSStringRefCF.cpp */,
 				146AAB2A0B66A84900E55F16 /* JSStringRefCF.h */,
 				1A28D4A7177B71C80007FA3C /* JSStringRefPrivate.h */,
+				53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */,
+				53486BB61C1795C300F6F3AF /* JSTypedArray.h */,
 				86E3C606167BAB87006D760A /* JSValue.h */,
 				86E3C60D167BAB87006D760A /* JSValue.mm */,
 				86E3C60E167BAB87006D760A /* JSValueInternal.h */,
@@ -7110,6 +7124,7 @@
 				0F7C11AD1BC3862C00C74CDB /* CopyBarrier.h in Headers */,
 				0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */,
 				C2239D1816262BDD005AC5FD /* CopyVisitor.h in Headers */,
+				53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */,
 				C2239D1916262BDD005AC5FD /* CopyVisitorInlines.h in Headers */,
 				C218D1401655CFD50062BB81 /* CopyWorkList.h in Headers */,
 				C4F4B6F41A05C944005CAB76 /* cpp_generator.py in Headers */,
@@ -7183,6 +7198,7 @@
 				0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
 				0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */,
 				0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
+				53529A4C1C457B75000B49C6 /* APIUtils.h in Headers */,
 				0FEA0A32170D40BF00BB722C /* DFGCommonData.h in Headers */,
 				0F725CB01C506D3B00AD943A /* B3FoldPathConstants.h in Headers */,
 				0F38B01817CFE75500B144D3 /* DFGCompilationKey.h in Headers */,
@@ -8558,6 +8574,7 @@
 				FE7C41961B97FC4B00F4D598 /* PingPongStackOverflowTest.cpp in Sources */,
 				65570F5A1AA4C3EA009B3C23 /* Regress141275.mm in Sources */,
 				FEB51F6C1A97B688001F921C /* Regress141809.mm in Sources */,
+				534902851C7276B70012BCB8 /* TypedArrayCTest.cpp in Sources */,
 				1440F6100A4F85670005F061 /* testapi.c in Sources */,
 				86D2221A167EF9440024C804 /* testapi.mm in Sources */,
 			);
@@ -8588,6 +8605,7 @@
 				43AB26C71C1A535C00D82AE6 /* B3MathExtras.cpp in Sources */,
 				0FEC85781BDACDC70080FF74 /* AirGenerate.cpp in Sources */,
 				0FEC85931BDB1E100080FF74 /* AirGenerated.cpp in Sources */,
+				53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */,
 				0FEC857B1BDACDC70080FF74 /* AirHandleCalleeSaves.cpp in Sources */,
 				0FEC857D1BDACDC70080FF74 /* AirInsertionSet.cpp in Sources */,
 				0FEC857F1BDACDC70080FF74 /* AirInst.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/PlatformEfl.cmake (197982 => 197983)


--- trunk/Source/_javascript_Core/PlatformEfl.cmake	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/PlatformEfl.cmake	2016-03-11 02:46:03 UTC (rev 197983)
@@ -15,6 +15,7 @@
               API/JSObjectRef.h
               API/JSStringRef.h
               API/JSValueRef.h
+              API/JSTypedArray.h
               API/WebKitAvailability.h
         DESTINATION "${HEADER_INSTALL_DIR}/_javascript_Core"
 )

Modified: trunk/Source/_javascript_Core/PlatformGTK.cmake (197982 => 197983)


--- trunk/Source/_javascript_Core/PlatformGTK.cmake	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/PlatformGTK.cmake	2016-03-11 02:46:03 UTC (rev 197983)
@@ -24,6 +24,7 @@
               API/JSContextRef.h
               API/JSObjectRef.h
               API/JSStringRef.h
+              API/JSTypedArray.h
               API/JSValueRef.h
               API/WebKitAvailability.h
         DESTINATION "${WEBKITGTK_HEADER_INSTALL_DIR}/_javascript_Core"

Modified: trunk/Source/_javascript_Core/runtime/ArrayBuffer.cpp (197982 => 197983)


--- trunk/Source/_javascript_Core/runtime/ArrayBuffer.cpp	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/runtime/ArrayBuffer.cpp	2016-03-11 02:46:03 UTC (rev 197983)
@@ -42,7 +42,7 @@
         return false;
     }
 
-    bool isNeuterable = !m_pinCount;
+    bool isNeuterable = !m_pinCount && !m_locked;
 
     if (!isNeuterable) {
         m_contents.copyTo(result);

Modified: trunk/Source/_javascript_Core/runtime/ArrayBuffer.h (197982 => 197983)


--- trunk/Source/_javascript_Core/runtime/ArrayBuffer.h	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/runtime/ArrayBuffer.h	2016-03-11 02:46:03 UTC (rev 197983)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2013, 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
@@ -28,6 +28,7 @@
 
 #include "GCIncomingRefCounted.h"
 #include "Weak.h"
+#include <functional>
 #include <wtf/PassRefPtr.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
@@ -38,11 +39,16 @@
 class ArrayBufferView;
 class JSArrayBuffer;
 
+typedef std::function<void(void*)> ArrayBufferDestructorFunction;
+static void arrayBufferDestructorNull(void*) { }
+static void arrayBufferDestructorDefault(void* p) { fastFree(p); }
+
 class ArrayBufferContents {
     WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
 public:
     ArrayBufferContents() 
-        : m_data(0)
+        : m_destructor(arrayBufferDestructorNull)
+        , m_data(nullptr)
         , m_sizeInBytes(0)
     { }
 
@@ -52,10 +58,12 @@
     unsigned sizeInBytes() { return m_sizeInBytes; }
 
 private:
-    ArrayBufferContents(void* data, unsigned sizeInBytes) 
+    ArrayBufferContents(void* data, unsigned sizeInBytes, ArrayBufferDestructorFunction&& destructor)
         : m_data(data)
         , m_sizeInBytes(sizeInBytes)
-    { }
+    {
+        m_destructor = WTFMove(destructor);
+    }
 
     friend class ArrayBuffer;
 
@@ -68,10 +76,9 @@
     void transfer(ArrayBufferContents& other)
     {
         ASSERT(!other.m_data);
-        other.m_data = m_data;
-        other.m_sizeInBytes = m_sizeInBytes;
-        m_data = 0;
-        m_sizeInBytes = 0;
+        std::swap(m_data, other.m_data);
+        std::swap(m_sizeInBytes, other.m_sizeInBytes);
+        std::swap(m_destructor, other.m_destructor);
     }
 
     void copyTo(ArrayBufferContents& other)
@@ -84,6 +91,7 @@
         other.m_sizeInBytes = m_sizeInBytes;
     }
 
+    ArrayBufferDestructorFunction m_destructor;
     void* m_data;
     unsigned m_sizeInBytes;
 };
@@ -95,6 +103,7 @@
     static inline PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
     static inline PassRefPtr<ArrayBuffer> create(ArrayBufferContents&);
     static inline PassRefPtr<ArrayBuffer> createAdopted(const void* data, unsigned byteLength);
+    static inline PassRefPtr<ArrayBuffer> createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&&);
 
     // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::createArrayBuffer.
     static inline PassRefPtr<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
@@ -110,6 +119,7 @@
     
     inline void pin();
     inline void unpin();
+    inline void pinAndLock();
 
     JS_EXPORT_PRIVATE bool transfer(ArrayBufferContents&);
     bool isNeutered() { return !m_contents.m_data; }
@@ -126,8 +136,9 @@
     inline unsigned clampIndex(int index) const;
     static inline int clampValue(int x, int left, int right);
 
-    unsigned m_pinCount;
     ArrayBufferContents m_contents;
+    unsigned m_pinCount : 31;
+    bool m_locked : 1; // m_locked == true means that some API user fetched m_contents directly from a TypedArray object.
 
 public:
     Weak<JSArrayBuffer> m_wrapper;
@@ -172,7 +183,12 @@
 
 PassRefPtr<ArrayBuffer> ArrayBuffer::createAdopted(const void* data, unsigned byteLength)
 {
-    ArrayBufferContents contents(const_cast<void*>(data), byteLength);
+    return createFromBytes(data, byteLength, WTFMove(arrayBufferDestructorDefault));
+}
+
+PassRefPtr<ArrayBuffer> ArrayBuffer::createFromBytes(const void* data, unsigned byteLength, ArrayBufferDestructorFunction&& destructor)
+{
+    ArrayBufferContents contents(const_cast<void*>(data), byteLength, WTFMove(destructor));
     return create(contents);
 }
 
@@ -192,6 +208,7 @@
 
 ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents)
     : m_pinCount(0)
+    , m_locked(false)
 {
     contents.transfer(m_contents);
 }
@@ -250,6 +267,11 @@
     m_pinCount--;
 }
 
+void ArrayBuffer::pinAndLock()
+{
+    m_locked = true;
+}
+
 void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy, ArrayBufferContents& result)
 {
     // Do not allow 31-bit overflow of the total size.
@@ -271,6 +293,7 @@
 
     if (allocationSucceeded) {
         result.m_sizeInBytes = numElements * elementByteSize;
+        result.m_destructor = arrayBufferDestructorDefault;
         return;
     }
     result.m_data = 0;
@@ -278,7 +301,7 @@
 
 ArrayBufferContents::~ArrayBufferContents()
 {
-    WTF::fastFree(m_data);
+    m_destructor(m_data);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/shell/PlatformWin.cmake (197982 => 197983)


--- trunk/Source/_javascript_Core/shell/PlatformWin.cmake	2016-03-11 02:37:46 UTC (rev 197982)
+++ trunk/Source/_javascript_Core/shell/PlatformWin.cmake	2016-03-11 02:46:03 UTC (rev 197983)
@@ -34,6 +34,7 @@
     ../API/tests/GlobalContextWithFinalizerTest.cpp
     ../API/tests/PingPongStackOverflowTest.cpp
     ../API/tests/testapi.c
+   ../API/tests/TypedArrayCTest.cpp
 )
 set_source_files_properties(../API/tests/CustomGlobalObjectClassTest.c PROPERTIES COMPILE_FLAGS "/TP /MT")
 set_source_files_properties(../API/tests/testapi.c PROPERTIES COMPILE_FLAGS "/TP /MT")
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to