Skip to content

Commit df6d255

Browse files
committed
doc,test: improve SharedArrayBuffer typedarray test and docs
Signed-off-by: umuoy1 <burningdian@gmail.com>
1 parent 265fa6f commit df6d255

File tree

3 files changed

+104
-94
lines changed

3 files changed

+104
-94
lines changed

doc/api/n-api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2748,6 +2748,10 @@ Language Specification.
27482748
<!-- YAML
27492749
added: v8.0.0
27502750
napiVersion: 1
2751+
changes:
2752+
- version: REPLACEME
2753+
pr-url: https://github.com/nodejs/node/pull/62710
2754+
description: Added support for `SharedArrayBuffer`.
27512755
-->
27522756

27532757
```c
@@ -2779,6 +2783,9 @@ It is required that `(length * size_of_element) + byte_offset` is less than or
27792783
equal to the size in bytes of the `ArrayBuffer` or `SharedArrayBuffer` passed
27802784
in. If not, a `RangeError` exception is raised.
27812785

2786+
For element sizes greater than 1, `byte_offset` is required to be a multiple
2787+
of the element size. If not, a `RangeError` exception is raised.
2788+
27822789
JavaScript `TypedArray` objects are described in
27832790
[Section TypedArray objects][] of the ECMAScript Language Specification.
27842791

test/js-native-api/test_typedarray_sharedarraybuffer/test.js

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -9,102 +9,102 @@ const assert = require('assert');
99
const test_typedarray_sharedarraybuffer =
1010
require(`./build/${common.buildType}/test_typedarray_sharedarraybuffer`);
1111

12-
// Test for creating Uint8Array with ArrayBuffer
13-
{
14-
const buffer = new ArrayBuffer(16);
15-
const theArray =
16-
test_typedarray_sharedarraybuffer.CreateUint8Array(buffer, 4, 6);
17-
const theArrayBuffer =
18-
test_typedarray_sharedarraybuffer.GetArrayBuffer(theArray);
19-
20-
assert.ok(theArray instanceof Uint8Array);
21-
assert.strictEqual(theArray.buffer, buffer);
22-
assert.ok(theArrayBuffer instanceof ArrayBuffer);
23-
assert.strictEqual(theArrayBuffer, buffer);
24-
assert.strictEqual(theArray.byteOffset, 4);
25-
assert.strictEqual(theArray.length, 6);
12+
const typedArrayCases = [
13+
{ type: Int8Array, values: [-1, 0, 127] },
14+
{ type: Uint8Array, values: [1, 2, 255] },
15+
{ type: Uint8ClampedArray, values: [0, 128, 255] },
16+
{ type: Int16Array, values: [-1, 0, 32767] },
17+
{ type: Uint16Array, values: [1, 2, 65535] },
18+
{ type: Int32Array, values: [-1, 0, 123456789] },
19+
{ type: Uint32Array, values: [1, 2, 4294967295] },
20+
{ type: Float16Array, values: [0.5, -1.5, 42.25] },
21+
{ type: Float32Array, values: [0.5, -1.5, 42.25] },
22+
{ type: Float64Array, values: [0.5, -1.5, 42.25] },
23+
{ type: BigInt64Array, values: [1n, -2n, 123456789n] },
24+
{ type: BigUint64Array, values: [1n, 2n, 123456789n] },
25+
];
26+
27+
function createBuffer(Type, BufferType, length) {
28+
const byteOffset = Type.BYTES_PER_ELEMENT;
29+
const byteLength = byteOffset + (length * Type.BYTES_PER_ELEMENT);
30+
return {
31+
buffer: new BufferType(byteLength),
32+
byteOffset,
33+
};
34+
}
2635

27-
theArray.set([1, 2, 3, 4, 5, 6]);
28-
assert.deepStrictEqual(Array.from(new Uint8Array(buffer, 4, 6)),
29-
[1, 2, 3, 4, 5, 6]);
36+
function createTypedArray(Type, buffer, byteOffset, length) {
37+
const template = new Type(buffer, byteOffset, length);
38+
return test_typedarray_sharedarraybuffer.CreateTypedArray(template, buffer);
3039
}
3140

32-
// Test for creating Uint8Array with SharedArrayBuffer
33-
{
34-
const buffer = new SharedArrayBuffer(16);
35-
const theArray =
36-
test_typedarray_sharedarraybuffer.CreateUint8Array(buffer, 4, 6);
41+
function verifyTypedArray(Type, buffer, byteOffset, values) {
42+
const theArray = createTypedArray(Type, buffer, byteOffset, values.length);
3743
const theArrayBuffer =
3844
test_typedarray_sharedarraybuffer.GetArrayBuffer(theArray);
3945

40-
assert.ok(theArray instanceof Uint8Array);
46+
assert.ok(theArray instanceof Type);
4147
assert.strictEqual(theArray.buffer, buffer);
42-
assert.ok(theArrayBuffer instanceof SharedArrayBuffer);
4348
assert.strictEqual(theArrayBuffer, buffer);
44-
assert.strictEqual(theArray.byteOffset, 4);
45-
assert.strictEqual(theArray.length, 6);
49+
assert.strictEqual(theArray.byteOffset, byteOffset);
50+
assert.strictEqual(theArray.length, values.length);
4651

47-
theArray.set([6, 5, 4, 3, 2, 1]);
48-
assert.deepStrictEqual(Array.from(new Uint8Array(buffer, 4, 6)),
49-
[6, 5, 4, 3, 2, 1]);
52+
theArray.set(values);
53+
assert.deepStrictEqual(Array.from(new Type(buffer, byteOffset, values.length)),
54+
values);
5055
}
5156

52-
// Test for creating Uint16Array with SharedArrayBuffer
57+
// Keep the existing ArrayBuffer behavior covered while focusing this test
58+
// on SharedArrayBuffer-backed TypedArray creation.
5359
{
54-
const buffer = new SharedArrayBuffer(24);
55-
const theArray =
56-
test_typedarray_sharedarraybuffer.CreateUint16Array(buffer, 4, 4);
57-
58-
assert.ok(theArray instanceof Uint16Array);
59-
assert.strictEqual(theArray.buffer, buffer);
60-
assert.strictEqual(theArray.byteOffset, 4);
61-
assert.strictEqual(theArray.length, 4);
62-
63-
theArray.set([1, 2, 3, 65535]);
64-
assert.deepStrictEqual(Array.from(new Uint16Array(buffer, 4, 4)),
65-
[1, 2, 3, 65535]);
60+
const { buffer, byteOffset } = createBuffer(Uint8Array, ArrayBuffer, 3);
61+
verifyTypedArray(Uint8Array, buffer, byteOffset, [1, 2, 3]);
6662
}
6763

68-
// Test for creating Int32Array with SharedArrayBuffer
69-
{
70-
const buffer = new SharedArrayBuffer(32);
71-
const theArray =
72-
test_typedarray_sharedarraybuffer.CreateInt32Array(buffer, 8, 3);
73-
74-
assert.ok(theArray instanceof Int32Array);
75-
assert.strictEqual(theArray.buffer, buffer);
76-
assert.strictEqual(theArray.byteOffset, 8);
77-
assert.strictEqual(theArray.length, 3);
64+
// Verify all TypedArray variants can be created from SharedArrayBuffer.
65+
typedArrayCases.forEach(({ type, values }) => {
66+
const { buffer, byteOffset } = createBuffer(type, SharedArrayBuffer,
67+
values.length);
68+
verifyTypedArray(type, buffer, byteOffset, values);
69+
});
7870

79-
theArray.set([-1, 0, 123456789]);
80-
assert.deepStrictEqual(Array.from(new Int32Array(buffer, 8, 3)),
81-
[-1, 0, 123456789]);
82-
}
83-
84-
// Test for creating TypedArrays with SharedArrayBuffer and invalid range
85-
{
86-
const buffer = new SharedArrayBuffer(8);
71+
// Test for creating TypedArrays with SharedArrayBuffer and invalid range.
72+
for (const { type, values } of typedArrayCases) {
73+
const { buffer, byteOffset } = createBuffer(type, SharedArrayBuffer,
74+
values.length);
75+
const template = new type(buffer, byteOffset, values.length);
8776

8877
assert.throws(() => {
89-
test_typedarray_sharedarraybuffer.CreateUint8Array(buffer, 9, 0);
78+
test_typedarray_sharedarraybuffer.CreateTypedArray(
79+
template, buffer, values.length + 1, byteOffset);
9080
}, RangeError);
81+
}
9182

92-
assert.throws(() => {
93-
test_typedarray_sharedarraybuffer.CreateUint16Array(buffer, 0, 5);
94-
}, RangeError);
83+
// Test for creating TypedArrays with SharedArrayBuffer and invalid alignment.
84+
for (const { type, values } of typedArrayCases) {
85+
if (type.BYTES_PER_ELEMENT <= 1) {
86+
continue;
87+
}
88+
89+
const { buffer, byteOffset } = createBuffer(type, SharedArrayBuffer,
90+
values.length);
91+
const template = new type(buffer, byteOffset, values.length);
9592

9693
assert.throws(() => {
97-
test_typedarray_sharedarraybuffer.CreateUint16Array(buffer, 1, 1);
94+
test_typedarray_sharedarraybuffer.CreateTypedArray(
95+
template, buffer, 1, byteOffset + 1);
9896
}, RangeError);
9997
}
10098

101-
// Test invalid arguments
99+
// Test invalid arguments.
102100
{
101+
const template = new Uint8Array(1);
102+
103103
assert.throws(() => {
104-
test_typedarray_sharedarraybuffer.CreateUint8Array({}, 0, 1);
104+
test_typedarray_sharedarraybuffer.CreateTypedArray(template, {});
105105
}, { name: 'Error', message: 'Invalid argument' });
106106

107107
assert.throws(() => {
108-
test_typedarray_sharedarraybuffer.CreateUint8Array(1, 0, 1);
108+
test_typedarray_sharedarraybuffer.CreateTypedArray(template, 1);
109109
}, { name: 'Error', message: 'Invalid argument' });
110110
}

test/js-native-api/test_typedarray_sharedarraybuffer/test_typedarray_sharedarraybuffer.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,46 @@
55
#include "../common.h"
66
#include "../entry_point.h"
77

8-
static napi_value CreateTypedArray(napi_env env,
9-
napi_callback_info info,
10-
napi_typedarray_type type) {
11-
size_t argc = 3;
12-
napi_value args[3];
8+
static napi_value CreateTypedArray(napi_env env, napi_callback_info info) {
9+
size_t argc = 4;
10+
napi_value args[4];
1311
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
1412

15-
NODE_API_ASSERT(env, argc == 3, "Wrong number of arguments");
13+
NODE_API_ASSERT(env, argc == 2 || argc == 4, "Wrong number of arguments");
1614

17-
uint32_t byte_offset;
18-
NODE_API_CALL(env, napi_get_value_uint32(env, args[1], &byte_offset));
15+
bool is_typedarray;
16+
NODE_API_CALL(env, napi_is_typedarray(env, args[0], &is_typedarray));
17+
NODE_API_ASSERT(env,
18+
is_typedarray,
19+
"Wrong type of arguments. Expects a typed array as first "
20+
"argument.");
1921

20-
uint32_t length;
21-
NODE_API_CALL(env, napi_get_value_uint32(env, args[2], &length));
22+
napi_typedarray_type type;
23+
size_t length;
24+
size_t byte_offset;
25+
NODE_API_CALL(env,
26+
napi_get_typedarray_info(
27+
env, args[0], &type, &length, NULL, NULL, &byte_offset));
28+
29+
if (argc == 4) {
30+
uint32_t uint32_length;
31+
NODE_API_CALL(env, napi_get_value_uint32(env, args[2], &uint32_length));
32+
length = uint32_length;
33+
34+
uint32_t uint32_byte_offset;
35+
NODE_API_CALL(env,
36+
napi_get_value_uint32(env, args[3], &uint32_byte_offset));
37+
byte_offset = uint32_byte_offset;
38+
}
2239

2340
napi_value typedarray;
2441
NODE_API_CALL(env,
2542
napi_create_typedarray(
26-
env, type, length, args[0], byte_offset, &typedarray));
43+
env, type, length, args[1], byte_offset, &typedarray));
2744

2845
return typedarray;
2946
}
3047

31-
static napi_value CreateUint8Array(napi_env env, napi_callback_info info) {
32-
return CreateTypedArray(env, info, napi_uint8_array);
33-
}
34-
35-
static napi_value CreateUint16Array(napi_env env, napi_callback_info info) {
36-
return CreateTypedArray(env, info, napi_uint16_array);
37-
}
38-
39-
static napi_value CreateInt32Array(napi_env env, napi_callback_info info) {
40-
return CreateTypedArray(env, info, napi_int32_array);
41-
}
42-
4348
static napi_value GetArrayBuffer(napi_env env, napi_callback_info info) {
4449
size_t argc = 1;
4550
napi_value args[1];
@@ -58,9 +63,7 @@ static napi_value GetArrayBuffer(napi_env env, napi_callback_info info) {
5863
EXTERN_C_START
5964
napi_value Init(napi_env env, napi_value exports) {
6065
napi_property_descriptor descriptors[] = {
61-
DECLARE_NODE_API_PROPERTY("CreateUint8Array", CreateUint8Array),
62-
DECLARE_NODE_API_PROPERTY("CreateUint16Array", CreateUint16Array),
63-
DECLARE_NODE_API_PROPERTY("CreateInt32Array", CreateInt32Array),
66+
DECLARE_NODE_API_PROPERTY("CreateTypedArray", CreateTypedArray),
6467
DECLARE_NODE_API_PROPERTY("GetArrayBuffer", GetArrayBuffer),
6568
};
6669

0 commit comments

Comments
 (0)