Skip to content

Commit 700df39

Browse files
KevinEadyjuanarbol
authored andcommitted
node-api: support SharedArrayBuffer in napi_create_dataview
PR-URL: #60473 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 71e857f commit 700df39

5 files changed

Lines changed: 70 additions & 23 deletions

File tree

doc/api/n-api.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,10 @@ exceeds the size of the `ArrayBuffer`, a `RangeError` exception is raised.
28042804
<!-- YAML
28052805
added: v8.3.0
28062806
napiVersion: 1
2807+
changes:
2808+
- version: REPLACEME
2809+
pr-url: https://github.com/nodejs/node/pull/60473
2810+
description: Added support for `SharedArrayBuffer`.
28072811
-->
28082812

28092813
```c
@@ -2816,16 +2820,18 @@ napi_status napi_create_dataview(napi_env env,
28162820

28172821
* `[in] env`: The environment that the API is invoked under.
28182822
* `[in] length`: Number of elements in the `DataView`.
2819-
* `[in] arraybuffer`: `ArrayBuffer` underlying the `DataView`.
2823+
* `[in] arraybuffer`: `ArrayBuffer` or `SharedArrayBuffer` underlying the
2824+
`DataView`.
28202825
* `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to
28212826
start projecting the `DataView`.
28222827
* `[out] result`: A `napi_value` representing a JavaScript `DataView`.
28232828

28242829
Returns `napi_ok` if the API succeeded.
28252830

2826-
This API creates a JavaScript `DataView` object over an existing `ArrayBuffer`.
2827-
`DataView` objects provide an array-like view over an underlying data buffer,
2828-
but one which allows items of different size and type in the `ArrayBuffer`.
2831+
This API creates a JavaScript `DataView` object over an existing `ArrayBuffer`
2832+
or `SharedArrayBuffer`. `DataView` objects provide an array-like view over an
2833+
underlying data buffer, but one which allows items of different size and type in
2834+
the `ArrayBuffer` or `SharedArrayBuffer`.
28292835

28302836
It is required that `byte_length + byte_offset` is less than or equal to the
28312837
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
@@ -3341,21 +3341,30 @@ napi_status NAPI_CDECL napi_create_dataview(napi_env env,
33413341
CHECK_ARG(env, result);
33423342

33433343
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(arraybuffer);
3344-
RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg);
33453344

3346-
v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>();
3347-
if (byte_length + byte_offset > buffer->ByteLength()) {
3348-
napi_throw_range_error(env,
3349-
"ERR_NAPI_INVALID_DATAVIEW_ARGS",
3350-
"byte_offset + byte_length should be less than or "
3351-
"equal to the size in bytes of the array passed in");
3352-
return napi_set_last_error(env, napi_pending_exception);
3353-
}
3354-
v8::Local<v8::DataView> DataView =
3355-
v8::DataView::New(buffer, byte_offset, byte_length);
3345+
auto create_dataview = [&](auto buffer) -> napi_status {
3346+
if (byte_length + byte_offset > buffer->ByteLength()) {
3347+
napi_throw_range_error(
3348+
env,
3349+
"ERR_NAPI_INVALID_DATAVIEW_ARGS",
3350+
"byte_offset + byte_length should be less than or "
3351+
"equal to the size in bytes of the array passed in");
3352+
return napi_set_last_error(env, napi_pending_exception);
3353+
}
33563354

3357-
*result = v8impl::JsValueFromV8LocalValue(DataView);
3358-
return GET_RETURN_STATUS(env);
3355+
v8::Local<v8::DataView> data_view =
3356+
v8::DataView::New(buffer, byte_offset, byte_length);
3357+
*result = v8impl::JsValueFromV8LocalValue(data_view);
3358+
return GET_RETURN_STATUS(env);
3359+
};
3360+
3361+
if (value->IsArrayBuffer()) {
3362+
return create_dataview(value.As<v8::ArrayBuffer>());
3363+
} else if (value->IsSharedArrayBuffer()) {
3364+
return create_dataview(value.As<v8::SharedArrayBuffer>());
3365+
} else {
3366+
return napi_set_last_error(env, napi_invalid_arg);
3367+
}
33593368
}
33603369

33613370
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 = new 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)