michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "jsfriendapi.h" michael@0: michael@0: #include "jsapi-tests/tests.h" michael@0: michael@0: using namespace js; michael@0: michael@0: BEGIN_TEST(testTypedArrays) michael@0: { michael@0: bool ok = true; michael@0: michael@0: ok = ok && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx) && michael@0: TestPlainTypedArray(cx); michael@0: michael@0: size_t nbytes = sizeof(double) * 8; michael@0: RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes)); michael@0: CHECK(JS_IsArrayBufferObject(buffer)); michael@0: michael@0: RootedObject proto(cx); michael@0: JS_GetPrototype(cx, buffer, &proto); michael@0: CHECK(!JS_IsArrayBufferObject(proto)); michael@0: RootedObject dummy(cx, JS_GetParent(proto)); michael@0: CHECK(!JS_IsArrayBufferObject(dummy)); michael@0: michael@0: CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer), nbytes); michael@0: memset(JS_GetStableArrayBufferData(cx, buffer), 1, nbytes); michael@0: michael@0: ok = ok && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx) && michael@0: TestArrayFromBuffer(cx); michael@0: michael@0: return ok; michael@0: } michael@0: michael@0: template michael@0: bool michael@0: TestPlainTypedArray(JSContext *cx) michael@0: { michael@0: { michael@0: RootedObject notArray(cx, Create(cx, UINT32_MAX)); michael@0: CHECK(!notArray); michael@0: } michael@0: michael@0: RootedObject array(cx, Create(cx, 7)); michael@0: CHECK(JS_IsTypedArrayObject(array)); michael@0: RootedObject proto(cx); michael@0: JS_GetPrototype(cx, array, &proto); michael@0: CHECK(!JS_IsTypedArrayObject(proto)); michael@0: RootedObject dummy(cx, JS_GetParent(proto)); michael@0: CHECK(!JS_IsTypedArrayObject(dummy)); michael@0: michael@0: CHECK_EQUAL(JS_GetTypedArrayLength(array), 7); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteLength(array), sizeof(Element) * 7); michael@0: michael@0: Element *data; michael@0: CHECK(data = GetData(array)); michael@0: *data = 13; michael@0: RootedValue v(cx); michael@0: CHECK(JS_GetElement(cx, array, 0, &v)); michael@0: CHECK_SAME(v, INT_TO_JSVAL(13)); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: bool michael@0: TestArrayFromBuffer(JSContext *cx) michael@0: { michael@0: size_t elts = 8; michael@0: size_t nbytes = elts * sizeof(Element); michael@0: RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes)); michael@0: uint8_t *bufdata; michael@0: CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer)); michael@0: memset(bufdata, 1, nbytes); michael@0: michael@0: { michael@0: RootedObject notArray(cx, CreateWithBuffer(cx, buffer, UINT32_MAX, -1)); michael@0: CHECK(!notArray); michael@0: } michael@0: michael@0: RootedObject array(cx, CreateWithBuffer(cx, buffer, 0, -1)); michael@0: CHECK_EQUAL(JS_GetTypedArrayLength(array), elts); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteLength(array), nbytes); michael@0: CHECK_EQUAL(JS_GetArrayBufferViewBuffer(cx, array), (JSObject*) buffer); michael@0: michael@0: Element *data; michael@0: CHECK(data = GetData(array)); michael@0: CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer)); michael@0: CHECK_EQUAL((void*) data, (void*) bufdata); michael@0: michael@0: CHECK_EQUAL(*bufdata, 1); michael@0: CHECK_EQUAL(*reinterpret_cast(data), 1); michael@0: michael@0: RootedObject shortArray(cx, CreateWithBuffer(cx, buffer, 0, elts / 2)); michael@0: CHECK_EQUAL(JS_GetTypedArrayLength(shortArray), elts / 2); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray), 0); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray), nbytes / 2); michael@0: michael@0: RootedObject ofsArray(cx, CreateWithBuffer(cx, buffer, nbytes / 2, -1)); michael@0: CHECK_EQUAL(JS_GetTypedArrayLength(ofsArray), elts / 2); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteOffset(ofsArray), nbytes / 2); michael@0: CHECK_EQUAL(JS_GetTypedArrayByteLength(ofsArray), nbytes / 2); michael@0: michael@0: // Make sure all 3 views reflect the same buffer at the expected locations michael@0: JS::RootedValue v(cx, INT_TO_JSVAL(39)); michael@0: JS_SetElement(cx, array, 0, v); michael@0: JS::RootedValue v2(cx); michael@0: CHECK(JS_GetElement(cx, array, 0, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK(JS_GetElement(cx, shortArray, 0, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast(data)[0])); michael@0: michael@0: v = INT_TO_JSVAL(40); michael@0: JS_SetElement(cx, array, elts / 2, v); michael@0: CHECK(JS_GetElement(cx, array, elts / 2, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK(JS_GetElement(cx, ofsArray, 0, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast(data)[elts / 2])); michael@0: michael@0: v = INT_TO_JSVAL(41); michael@0: JS_SetElement(cx, array, elts - 1, v); michael@0: CHECK(JS_GetElement(cx, array, elts - 1, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK(JS_GetElement(cx, ofsArray, elts / 2 - 1, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast(data)[elts - 1])); michael@0: michael@0: JS::RootedObject copy(cx, CreateFromArray(cx, array)); michael@0: CHECK(JS_GetElement(cx, array, 0, &v)); michael@0: CHECK(JS_GetElement(cx, copy, 0, &v2)); michael@0: CHECK_SAME(v, v2); michael@0: michael@0: /* The copy should not see changes in the original */ michael@0: v2 = INT_TO_JSVAL(42); michael@0: JS_SetElement(cx, array, 0, v2); michael@0: CHECK(JS_GetElement(cx, copy, 0, &v2)); michael@0: CHECK_SAME(v2, v); /* v is still the original value from 'array' */ michael@0: michael@0: return true; michael@0: } michael@0: michael@0: END_TEST(testTypedArrays)