Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,10 @@ exceeds the size of the `ArrayBuffer`, a `RangeError` exception is raised.
<!-- YAML
added: v8.3.0
napiVersion: 1
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/60473
description: Added support for `SharedArrayBuffer`.
-->

```c
Expand All @@ -2781,16 +2785,18 @@ napi_status napi_create_dataview(napi_env env,

* `[in] env`: The environment that the API is invoked under.
* `[in] length`: Number of elements in the `DataView`.
* `[in] arraybuffer`: `ArrayBuffer` underlying the `DataView`.
* `[in] arraybuffer`: `ArrayBuffer` or `SharedArrayBuffer` underlying the
`DataView`.
* `[in] byte_offset`: The byte offset within the `ArrayBuffer` from which to
start projecting the `DataView`.
* `[out] result`: A `napi_value` representing a JavaScript `DataView`.

Returns `napi_ok` if the API succeeded.

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

It is required that `byte_length + byte_offset` is less than or equal to the
size in bytes of the array passed in. If not, a `RangeError` exception is
Expand Down
35 changes: 22 additions & 13 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3298,21 +3298,30 @@ napi_status NAPI_CDECL napi_create_dataview(napi_env env,
CHECK_ARG(env, result);

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

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

*result = v8impl::JsValueFromV8LocalValue(DataView);
return GET_RETURN_STATUS(env);
v8::Local<v8::DataView> data_view =
v8::DataView::New(buffer, byte_offset, byte_length);
*result = v8impl::JsValueFromV8LocalValue(data_view);
return GET_RETURN_STATUS(env);
};

if (value->IsArrayBuffer()) {
return create_dataview(value.As<v8::ArrayBuffer>());
} else if (value->IsSharedArrayBuffer()) {
return create_dataview(value.As<v8::SharedArrayBuffer>());
} else {
return napi_set_last_error(env, napi_invalid_arg);
}
}

napi_status NAPI_CDECL napi_is_dataview(napi_env env,
Expand Down
5 changes: 4 additions & 1 deletion test/js-native-api/test_dataview/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"target_name": "test_dataview",
"sources": [
"test_dataview.c"
]
],

# For node_api_is_sharedarraybuffer
'defines': [ 'NAPI_EXPERIMENTAL', 'NODE_API_EXPERIMENTAL_NO_WARNING' ]
}
]
}
24 changes: 22 additions & 2 deletions test/js-native-api/test_dataview/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const assert = require('assert');
// Testing api calls for arrays
const test_dataview = require(`./build/${common.buildType}/test_dataview`);

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

// Test for creating dataview with invalid range
// Test for creating dataview with SharedArrayBuffer
{
const buffer = new SharedArrayBuffer(128);
const template = new DataView(buffer);

const theDataview = test_dataview.CreateDataViewFromJSDataView(template);
assert.ok(theDataview instanceof DataView,
`Expect ${theDataview} to be a DataView`);

assert.strictEqual(template.buffer, theDataview.buffer);
}

// Test for creating dataview with ArrayBuffer and invalid range
{
const buffer = new ArrayBuffer(128);
assert.throws(() => {
test_dataview.CreateDataView(buffer, 10, 200);
}, RangeError);
}

// Test for creating dataview with SharedArrayBuffer and invalid range
{
const buffer = new SharedArrayBuffer(128);
assert.throws(() => {
test_dataview.CreateDataView(buffer, 10, 200);
}, RangeError);
}
15 changes: 12 additions & 3 deletions test/js-native-api/test_dataview/test_dataview.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,18 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) {

bool is_arraybuffer;
NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer));
NODE_API_ASSERT(env, is_arraybuffer,
"Wrong type of arguments. Expects a ArrayBuffer as the first "
"argument.");

if (!is_arraybuffer) {
bool is_sharedarraybuffer;
NODE_API_CALL(
env,
node_api_is_sharedarraybuffer(env, arraybuffer, &is_sharedarraybuffer));
NODE_API_ASSERT(env,
is_sharedarraybuffer,
"Wrong type of arguments. Expects a SharedArrayBuffer or "
"ArrayBuffer as the first "
"argument.");
}

napi_valuetype valuetype1;
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
Expand Down
Loading