Skip to content

Commit 68ea53e

Browse files
committed
node-api: support SharedArrayBuffer in napi_create_dataview
1 parent dec0213 commit 68ea53e

File tree

5 files changed

+70
-23
lines changed

5 files changed

+70
-23
lines changed

doc/api/n-api.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,10 @@ exceeds the size of the `ArrayBuffer`, a `RangeError` exception is raised.
27692769
<!-- YAML
27702770
added: v8.3.0
27712771
napiVersion: 1
2772+
changes:
2773+
- version: REPLACEME
2774+
pr-url: https://github.com/nodejs/node/pull/60473
2775+
description: Added support for `SharedArrayBuffer`.
27722776
-->
27732777

27742778
```c
@@ -2781,16 +2785,18 @@ napi_status napi_create_dataview(napi_env env,
27812785

27822786
* `[in] env`: The environment that the API is invoked under.
27832787
* `[in] length`: Number of elements in the `DataView`.
2784-
* `[in] arraybuffer`: `ArrayBuffer` underlying the `DataView`.
2788+
* `[in] arraybuffer`: `ArrayBuffer` or `SharedArrayBuffer` underlying the
2789+
`DataView`.
27852790
* `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to
27862791
start projecting the `DataView`.
27872792
* `[out] result`: A `napi_value` representing a JavaScript `DataView`.
27882793

27892794
Returns `napi_ok` if the API succeeded.
27902795

2791-
This API creates a JavaScript `DataView` object over an existing `ArrayBuffer`.
2792-
`DataView` objects provide an array-like view over an underlying data buffer,
2793-
but one which allows items of different size and type in the `ArrayBuffer`.
2796+
This API creates a JavaScript `DataView` object over an existing `ArrayBuffer`
2797+
or `SharedArrayBuffer`. `DataView` objects provide an array-like view over an
2798+
underlying data buffer, but one which allows items of different size and type in
2799+
the `ArrayBuffer` or `SharedArrayBuffer`.
27942800

27952801
It is required that `byte_length + byte_offset` is less than or equal to the
27962802
size in bytes of the array passed in. If not, a `RangeError` exception is

src/js_native_api_v8.cc

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3298,21 +3298,30 @@ napi_status NAPI_CDECL napi_create_dataview(napi_env env,
32983298
CHECK_ARG(env, result);
32993299

33003300
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3301-
RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
33023301

3303-
v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
3304-
if (byte_length + byte_offset > buffer->ByteLength()) {
3305-
napi_throw_range_error(env,
3306-
"ERR_NAPI_INVALID_DATAVIEW_ARGS",
3307-
"byte_offset + byte_length should be less than or "
3308-
"equal to the size in bytes of the array passed in");
3309-
return napi_set_last_error(env, napi_pending_exception);
3310-
}
3311-
v8::Local<v8::DataView> DataView =
3312-
v8::DataView::New(buffer, byte_offset, byte_length);
3302+
auto create_dataview = [&](auto buffer) -> napi_status {
3303+
if (byte_length + byte_offset > buffer->ByteLength()) {
3304+
napi_throw_range_error(
3305+
env,
3306+
"ERR_NAPI_INVALID_DATAVIEW_ARGS",
3307+
"byte_offset + byte_length should be less than or "
3308+
"equal to the size in bytes of the array passed in");
3309+
return napi_set_last_error(env, napi_pending_exception);
3310+
}
33133311

3314-
*result = v8impl::JsValueFromV8LocalValue(DataView);
3315-
return GET_RETURN_STATUS(env);
3312+
v8::Local<v8::DataView> data_view =
3313+
v8::DataView::New(buffer, byte_offset, byte_length);
3314+
*result = v8impl::JsValueFromV8LocalValue(data_view);
3315+
return GET_RETURN_STATUS(env);
3316+
};
3317+
3318+
if (value->IsArrayBuffer()) {
3319+
return create_dataview(value.As<v8::ArrayBuffer>());
3320+
} else if (value->IsSharedArrayBuffer()) {
3321+
return create_dataview(value.As<v8::SharedArrayBuffer>());
3322+
} else {
3323+
return napi_set_last_error(env, napi_invalid_arg);
3324+
}
33163325
}
33173326

33183327
napi_status NAPI_CDECL napi_is_dataview(napi_env env,

test/js-native-api/test_dataview/binding.gyp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
"target_name": "test_dataview",
55
"sources": [
66
"test_dataview.c"
7-
]
7+
],
8+
9+
# For node_api_is_sharedarraybuffer
10+
'defines': [ 'NAPI_EXPERIMENTAL', 'NODE_API_EXPERIMENTAL_NO_WARNING' ]
811
}
912
]
1013
}

test/js-native-api/test_dataview/test.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const assert = require('assert');
55
// Testing api calls for arrays
66
const test_dataview = require(`./build/${common.buildType}/test_dataview`);
77

8-
// Test for creating dataview
8+
// Test for creating dataview with ArrayBuffer
99
{
1010
const buffer = new ArrayBuffer(128);
1111
const template = Reflect.construct(DataView, [buffer]);
@@ -15,10 +15,30 @@ const test_dataview = require(`./build/${common.buildType}/test_dataview`);
1515
`Expect ${theDataview} to be a DataView`);
1616
}
1717

18-
// Test for creating dataview with invalid range
18+
// Test for creating dataview with SharedArrayBuffer
19+
{
20+
const buffer = new SharedArrayBuffer(128);
21+
const template = Reflect.construct(DataView, [buffer]);
22+
23+
const theDataview = test_dataview.CreateDataViewFromJSDataView(template);
24+
assert.ok(theDataview instanceof DataView,
25+
`Expect ${theDataview} to be a DataView`);
26+
27+
assert.strictEqual(template.buffer, theDataview.buffer);
28+
}
29+
30+
// Test for creating dataview with ArrayBuffer and invalid range
1931
{
2032
const buffer = new ArrayBuffer(128);
2133
assert.throws(() => {
2234
test_dataview.CreateDataView(buffer, 10, 200);
2335
}, RangeError);
2436
}
37+
38+
// Test for creating dataview with SharedArrayBuffer and invalid range
39+
{
40+
const buffer = new SharedArrayBuffer(128);
41+
assert.throws(() => {
42+
test_dataview.CreateDataView(buffer, 10, 200);
43+
}, RangeError);
44+
}

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) {
2020

2121
bool is_arraybuffer;
2222
NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer));
23-
NODE_API_ASSERT(env, is_arraybuffer,
24-
"Wrong type of arguments. Expects a ArrayBuffer as the first "
25-
"argument.");
23+
24+
if (!is_arraybuffer) {
25+
bool is_sharedarraybuffer;
26+
NODE_API_CALL(
27+
env,
28+
node_api_is_sharedarraybuffer(env, arraybuffer, &is_sharedarraybuffer));
29+
NODE_API_ASSERT(env,
30+
is_sharedarraybuffer,
31+
"Wrong type of arguments. Expects a SharedArrayBuffer or "
32+
"ArrayBuffer as the first "
33+
"argument.");
34+
}
2635

2736
napi_valuetype valuetype1;
2837
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));

0 commit comments

Comments
 (0)