|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 */ |
|
4 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "jsfriendapi.h" |
|
9 |
|
10 #include "jsapi-tests/tests.h" |
|
11 |
|
12 using namespace js; |
|
13 |
|
14 BEGIN_TEST(testTypedArrays) |
|
15 { |
|
16 bool ok = true; |
|
17 |
|
18 ok = ok && |
|
19 TestPlainTypedArray<JS_NewInt8Array, int8_t, JS_GetInt8ArrayData>(cx) && |
|
20 TestPlainTypedArray<JS_NewUint8Array, uint8_t, JS_GetUint8ArrayData>(cx) && |
|
21 TestPlainTypedArray<JS_NewUint8ClampedArray, uint8_t, JS_GetUint8ClampedArrayData>(cx) && |
|
22 TestPlainTypedArray<JS_NewInt16Array, int16_t, JS_GetInt16ArrayData>(cx) && |
|
23 TestPlainTypedArray<JS_NewUint16Array, uint16_t, JS_GetUint16ArrayData>(cx) && |
|
24 TestPlainTypedArray<JS_NewInt32Array, int32_t, JS_GetInt32ArrayData>(cx) && |
|
25 TestPlainTypedArray<JS_NewUint32Array, uint32_t, JS_GetUint32ArrayData>(cx) && |
|
26 TestPlainTypedArray<JS_NewFloat32Array, float, JS_GetFloat32ArrayData>(cx) && |
|
27 TestPlainTypedArray<JS_NewFloat64Array, double, JS_GetFloat64ArrayData>(cx); |
|
28 |
|
29 size_t nbytes = sizeof(double) * 8; |
|
30 RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes)); |
|
31 CHECK(JS_IsArrayBufferObject(buffer)); |
|
32 |
|
33 RootedObject proto(cx); |
|
34 JS_GetPrototype(cx, buffer, &proto); |
|
35 CHECK(!JS_IsArrayBufferObject(proto)); |
|
36 RootedObject dummy(cx, JS_GetParent(proto)); |
|
37 CHECK(!JS_IsArrayBufferObject(dummy)); |
|
38 |
|
39 CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer), nbytes); |
|
40 memset(JS_GetStableArrayBufferData(cx, buffer), 1, nbytes); |
|
41 |
|
42 ok = ok && |
|
43 TestArrayFromBuffer<JS_NewInt8ArrayWithBuffer, JS_NewInt8ArrayFromArray, int8_t, JS_GetInt8ArrayData>(cx) && |
|
44 TestArrayFromBuffer<JS_NewUint8ArrayWithBuffer, JS_NewUint8ArrayFromArray, uint8_t, JS_GetUint8ArrayData>(cx) && |
|
45 TestArrayFromBuffer<JS_NewUint8ClampedArrayWithBuffer, JS_NewUint8ClampedArrayFromArray, uint8_t, JS_GetUint8ClampedArrayData>(cx) && |
|
46 TestArrayFromBuffer<JS_NewInt16ArrayWithBuffer, JS_NewInt16ArrayFromArray, int16_t, JS_GetInt16ArrayData>(cx) && |
|
47 TestArrayFromBuffer<JS_NewUint16ArrayWithBuffer, JS_NewUint16ArrayFromArray, uint16_t, JS_GetUint16ArrayData>(cx) && |
|
48 TestArrayFromBuffer<JS_NewInt32ArrayWithBuffer, JS_NewInt32ArrayFromArray, int32_t, JS_GetInt32ArrayData>(cx) && |
|
49 TestArrayFromBuffer<JS_NewUint32ArrayWithBuffer, JS_NewUint32ArrayFromArray, uint32_t, JS_GetUint32ArrayData>(cx) && |
|
50 TestArrayFromBuffer<JS_NewFloat32ArrayWithBuffer, JS_NewFloat32ArrayFromArray, float, JS_GetFloat32ArrayData>(cx) && |
|
51 TestArrayFromBuffer<JS_NewFloat64ArrayWithBuffer, JS_NewFloat64ArrayFromArray, double, JS_GetFloat64ArrayData>(cx); |
|
52 |
|
53 return ok; |
|
54 } |
|
55 |
|
56 template<JSObject *Create(JSContext *, uint32_t), |
|
57 typename Element, |
|
58 Element *GetData(JSObject *)> |
|
59 bool |
|
60 TestPlainTypedArray(JSContext *cx) |
|
61 { |
|
62 { |
|
63 RootedObject notArray(cx, Create(cx, UINT32_MAX)); |
|
64 CHECK(!notArray); |
|
65 } |
|
66 |
|
67 RootedObject array(cx, Create(cx, 7)); |
|
68 CHECK(JS_IsTypedArrayObject(array)); |
|
69 RootedObject proto(cx); |
|
70 JS_GetPrototype(cx, array, &proto); |
|
71 CHECK(!JS_IsTypedArrayObject(proto)); |
|
72 RootedObject dummy(cx, JS_GetParent(proto)); |
|
73 CHECK(!JS_IsTypedArrayObject(dummy)); |
|
74 |
|
75 CHECK_EQUAL(JS_GetTypedArrayLength(array), 7); |
|
76 CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0); |
|
77 CHECK_EQUAL(JS_GetTypedArrayByteLength(array), sizeof(Element) * 7); |
|
78 |
|
79 Element *data; |
|
80 CHECK(data = GetData(array)); |
|
81 *data = 13; |
|
82 RootedValue v(cx); |
|
83 CHECK(JS_GetElement(cx, array, 0, &v)); |
|
84 CHECK_SAME(v, INT_TO_JSVAL(13)); |
|
85 |
|
86 return true; |
|
87 } |
|
88 |
|
89 template<JSObject *CreateWithBuffer(JSContext *, JS::HandleObject, uint32_t, int32_t), |
|
90 JSObject *CreateFromArray(JSContext *, JS::HandleObject), |
|
91 typename Element, |
|
92 Element *GetData(JSObject *)> |
|
93 bool |
|
94 TestArrayFromBuffer(JSContext *cx) |
|
95 { |
|
96 size_t elts = 8; |
|
97 size_t nbytes = elts * sizeof(Element); |
|
98 RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes)); |
|
99 uint8_t *bufdata; |
|
100 CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer)); |
|
101 memset(bufdata, 1, nbytes); |
|
102 |
|
103 { |
|
104 RootedObject notArray(cx, CreateWithBuffer(cx, buffer, UINT32_MAX, -1)); |
|
105 CHECK(!notArray); |
|
106 } |
|
107 |
|
108 RootedObject array(cx, CreateWithBuffer(cx, buffer, 0, -1)); |
|
109 CHECK_EQUAL(JS_GetTypedArrayLength(array), elts); |
|
110 CHECK_EQUAL(JS_GetTypedArrayByteOffset(array), 0); |
|
111 CHECK_EQUAL(JS_GetTypedArrayByteLength(array), nbytes); |
|
112 CHECK_EQUAL(JS_GetArrayBufferViewBuffer(cx, array), (JSObject*) buffer); |
|
113 |
|
114 Element *data; |
|
115 CHECK(data = GetData(array)); |
|
116 CHECK(bufdata = JS_GetStableArrayBufferData(cx, buffer)); |
|
117 CHECK_EQUAL((void*) data, (void*) bufdata); |
|
118 |
|
119 CHECK_EQUAL(*bufdata, 1); |
|
120 CHECK_EQUAL(*reinterpret_cast<uint8_t*>(data), 1); |
|
121 |
|
122 RootedObject shortArray(cx, CreateWithBuffer(cx, buffer, 0, elts / 2)); |
|
123 CHECK_EQUAL(JS_GetTypedArrayLength(shortArray), elts / 2); |
|
124 CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray), 0); |
|
125 CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray), nbytes / 2); |
|
126 |
|
127 RootedObject ofsArray(cx, CreateWithBuffer(cx, buffer, nbytes / 2, -1)); |
|
128 CHECK_EQUAL(JS_GetTypedArrayLength(ofsArray), elts / 2); |
|
129 CHECK_EQUAL(JS_GetTypedArrayByteOffset(ofsArray), nbytes / 2); |
|
130 CHECK_EQUAL(JS_GetTypedArrayByteLength(ofsArray), nbytes / 2); |
|
131 |
|
132 // Make sure all 3 views reflect the same buffer at the expected locations |
|
133 JS::RootedValue v(cx, INT_TO_JSVAL(39)); |
|
134 JS_SetElement(cx, array, 0, v); |
|
135 JS::RootedValue v2(cx); |
|
136 CHECK(JS_GetElement(cx, array, 0, &v2)); |
|
137 CHECK_SAME(v, v2); |
|
138 CHECK(JS_GetElement(cx, shortArray, 0, &v2)); |
|
139 CHECK_SAME(v, v2); |
|
140 CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[0])); |
|
141 |
|
142 v = INT_TO_JSVAL(40); |
|
143 JS_SetElement(cx, array, elts / 2, v); |
|
144 CHECK(JS_GetElement(cx, array, elts / 2, &v2)); |
|
145 CHECK_SAME(v, v2); |
|
146 CHECK(JS_GetElement(cx, ofsArray, 0, &v2)); |
|
147 CHECK_SAME(v, v2); |
|
148 CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[elts / 2])); |
|
149 |
|
150 v = INT_TO_JSVAL(41); |
|
151 JS_SetElement(cx, array, elts - 1, v); |
|
152 CHECK(JS_GetElement(cx, array, elts - 1, &v2)); |
|
153 CHECK_SAME(v, v2); |
|
154 CHECK(JS_GetElement(cx, ofsArray, elts / 2 - 1, &v2)); |
|
155 CHECK_SAME(v, v2); |
|
156 CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[elts - 1])); |
|
157 |
|
158 JS::RootedObject copy(cx, CreateFromArray(cx, array)); |
|
159 CHECK(JS_GetElement(cx, array, 0, &v)); |
|
160 CHECK(JS_GetElement(cx, copy, 0, &v2)); |
|
161 CHECK_SAME(v, v2); |
|
162 |
|
163 /* The copy should not see changes in the original */ |
|
164 v2 = INT_TO_JSVAL(42); |
|
165 JS_SetElement(cx, array, 0, v2); |
|
166 CHECK(JS_GetElement(cx, copy, 0, &v2)); |
|
167 CHECK_SAME(v2, v); /* v is still the original value from 'array' */ |
|
168 |
|
169 return true; |
|
170 } |
|
171 |
|
172 END_TEST(testTypedArrays) |