From 7238bc2de1976e9132cbfb3234c406bf1844a9eb Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Sun, 29 Mar 2026 21:39:05 +0530 Subject: [PATCH 1/3] feat: port test_dataview to CTS Ports [https://github.com/nodejs/node/tree/main/test/js-native-api/test_dataview](test_dataview) from Node.js test suite to the CTS. This test contains an experimental feature `SharedArrayBuffer`, resulting in usage of `add_node_api_cts_experimental_addon()`. Signed-off-by: Balakrishna Avulapati --- PORTING.md | 2 +- .../test_dataview/CMakeLists.txt | 1 + tests/js-native-api/test_dataview/test.js | 48 ++++++++ .../test_dataview/test_dataview.c | 111 ++++++++++++++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 tests/js-native-api/test_dataview/CMakeLists.txt create mode 100644 tests/js-native-api/test_dataview/test.js create mode 100644 tests/js-native-api/test_dataview/test_dataview.c diff --git a/PORTING.md b/PORTING.md index 23bdc0b..5a63cf6 100644 --- a/PORTING.md +++ b/PORTING.md @@ -52,7 +52,7 @@ Tests covering the engine-specific part of Node-API, defined in `js_native_api.h | `test_cannot_run_js` | Not ported | Medium | | `test_constructor` | Ported ✅ | Medium | | `test_conversions` | Ported ✅ | Medium | -| `test_dataview` | Not ported | Medium | +| `test_dataview` | Ported ✅ | Medium | | `test_date` | Ported ✅ | Easy | | `test_error` | Ported ✅ | Medium | | `test_exception` | Not ported | Medium | diff --git a/tests/js-native-api/test_dataview/CMakeLists.txt b/tests/js-native-api/test_dataview/CMakeLists.txt new file mode 100644 index 0000000..052900e --- /dev/null +++ b/tests/js-native-api/test_dataview/CMakeLists.txt @@ -0,0 +1 @@ +add_node_api_cts_experimental_addon(test_dataview test_dataview.c) diff --git a/tests/js-native-api/test_dataview/test.js b/tests/js-native-api/test_dataview/test.js new file mode 100644 index 0000000..5de5494 --- /dev/null +++ b/tests/js-native-api/test_dataview/test.js @@ -0,0 +1,48 @@ +"use strict"; + +if (experimentalFeatures.sharedArrayBuffer) { + // Testing api calls for arrays + const test_dataview = loadAddon("test_dataview"); + + // Test for creating dataview with ArrayBuffer + { + const buffer = new ArrayBuffer(128); + const template = Reflect.construct(DataView, [buffer]); + + const theDataview = test_dataview.CreateDataViewFromJSDataView(template); + assert.ok( + theDataview instanceof DataView, + `Expect ${theDataview} to be a DataView`, + ); + } + + // 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); + } +} diff --git a/tests/js-native-api/test_dataview/test_dataview.c b/tests/js-native-api/test_dataview/test_dataview.c new file mode 100644 index 0000000..ec564e6 --- /dev/null +++ b/tests/js-native-api/test_dataview/test_dataview.c @@ -0,0 +1,111 @@ +#include +#include +#include "../common.h" +#include "../entry_point.h" + +static napi_value CreateDataView(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args [3]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc == 3, "Wrong number of arguments"); + + napi_valuetype valuetype0; + napi_value arraybuffer = args[0]; + + NODE_API_CALL(env, napi_typeof(env, arraybuffer, &valuetype0)); + NODE_API_ASSERT(env, valuetype0 == napi_object, + "Wrong type of arguments. Expects a ArrayBuffer as the first " + "argument."); + + bool is_arraybuffer; + NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer)); + + 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)); + + NODE_API_ASSERT(env, valuetype1 == napi_number, + "Wrong type of arguments. Expects a number as second argument."); + + size_t byte_offset = 0; + NODE_API_CALL(env, napi_get_value_uint32(env, args[1], (uint32_t*)(&byte_offset))); + + napi_valuetype valuetype2; + NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype2)); + + NODE_API_ASSERT(env, valuetype2 == napi_number, + "Wrong type of arguments. Expects a number as third argument."); + + size_t length = 0; + NODE_API_CALL(env, napi_get_value_uint32(env, args[2], (uint32_t*)(&length))); + + napi_value output_dataview; + NODE_API_CALL(env, + napi_create_dataview(env, length, arraybuffer, + byte_offset, &output_dataview)); + + return output_dataview; +} + +static napi_value CreateDataViewFromJSDataView(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args [1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc == 1, "Wrong number of arguments"); + + napi_valuetype valuetype; + napi_value input_dataview = args[0]; + + NODE_API_CALL(env, napi_typeof(env, input_dataview, &valuetype)); + NODE_API_ASSERT(env, valuetype == napi_object, + "Wrong type of arguments. Expects a DataView as the first " + "argument."); + + bool is_dataview; + NODE_API_CALL(env, napi_is_dataview(env, input_dataview, &is_dataview)); + NODE_API_ASSERT(env, is_dataview, + "Wrong type of arguments. Expects a DataView as the first " + "argument."); + size_t byte_offset = 0; + size_t length = 0; + napi_value buffer; + NODE_API_CALL(env, + napi_get_dataview_info(env, input_dataview, &length, NULL, + &buffer, &byte_offset)); + + napi_value output_dataview; + NODE_API_CALL(env, + napi_create_dataview(env, length, buffer, + byte_offset, &output_dataview)); + + + return output_dataview; +} + +EXTERN_C_START +napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor descriptors[] = { + DECLARE_NODE_API_PROPERTY("CreateDataView", CreateDataView), + DECLARE_NODE_API_PROPERTY("CreateDataViewFromJSDataView", + CreateDataViewFromJSDataView) + }; + + NODE_API_CALL(env, napi_define_properties( + env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); + + return exports; +} +EXTERN_C_END From 1770fbb7ebabe98a7a593d6e5b1f029844fadcaa Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Thu, 9 Apr 2026 21:26:02 +0530 Subject: [PATCH 2/3] remove the type check in CreateDataView Signed-off-by: Balakrishna Avulapati --- .../test_dataview/CMakeLists.txt | 2 +- tests/js-native-api/test_dataview/test.js | 88 +++++++++---------- .../test_dataview/test_dataview.c | 15 ---- 3 files changed, 44 insertions(+), 61 deletions(-) diff --git a/tests/js-native-api/test_dataview/CMakeLists.txt b/tests/js-native-api/test_dataview/CMakeLists.txt index 052900e..4411f2e 100644 --- a/tests/js-native-api/test_dataview/CMakeLists.txt +++ b/tests/js-native-api/test_dataview/CMakeLists.txt @@ -1 +1 @@ -add_node_api_cts_experimental_addon(test_dataview test_dataview.c) +add_node_api_cts_addon(test_dataview test_dataview.c) diff --git a/tests/js-native-api/test_dataview/test.js b/tests/js-native-api/test_dataview/test.js index 5de5494..2953a42 100644 --- a/tests/js-native-api/test_dataview/test.js +++ b/tests/js-native-api/test_dataview/test.js @@ -1,48 +1,46 @@ "use strict"; -if (experimentalFeatures.sharedArrayBuffer) { - // Testing api calls for arrays - const test_dataview = loadAddon("test_dataview"); - - // Test for creating dataview with ArrayBuffer - { - const buffer = new ArrayBuffer(128); - const template = Reflect.construct(DataView, [buffer]); - - const theDataview = test_dataview.CreateDataViewFromJSDataView(template); - assert.ok( - theDataview instanceof DataView, - `Expect ${theDataview} to be a DataView`, - ); - } - - // 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); - } +// Testing api calls for dataview +const test_dataview = loadAddon("test_dataview"); + +// Test for creating dataview with ArrayBuffer +{ + const buffer = new ArrayBuffer(128); + const template = Reflect.construct(DataView, [buffer]); + + const theDataview = test_dataview.CreateDataViewFromJSDataView(template); + assert.ok( + theDataview instanceof DataView, + `Expect ${theDataview} to be a DataView`, + ); +} + +// 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); } diff --git a/tests/js-native-api/test_dataview/test_dataview.c b/tests/js-native-api/test_dataview/test_dataview.c index ec564e6..d6a85db 100644 --- a/tests/js-native-api/test_dataview/test_dataview.c +++ b/tests/js-native-api/test_dataview/test_dataview.c @@ -18,21 +18,6 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) { "Wrong type of arguments. Expects a ArrayBuffer as the first " "argument."); - bool is_arraybuffer; - NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer)); - - 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)); From 70aa53afdc1907442139226ccf3a4a54ee00f8a8 Mon Sep 17 00:00:00 2001 From: Balakrishna Avulapati Date: Fri, 5 Jun 2026 20:10:50 +0530 Subject: [PATCH 3/3] split test_dataview SharedArrayBuffer cases behind a feature flag --- implementors/node/features.js | 9 +++++- tests/js-native-api/test_dataview/test.js | 22 ------------- .../test_dataview/test_sharedarraybuffer.js | 32 +++++++++++++++++++ 3 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 tests/js-native-api/test_dataview/test_sharedarraybuffer.js diff --git a/implementors/node/features.js b/implementors/node/features.js index cd46f82..a50f614 100644 --- a/implementors/node/features.js +++ b/implementors/node/features.js @@ -2,7 +2,7 @@ // Each key corresponds to a NODE_API_EXPERIMENTAL_HAS_* compile-time macro. // Other implementors should set unsupported features to false or omit them. -const [major, minor] = process.version.slice(1).split('.').map(Number); +const [major, minor, patch] = process.version.slice(1).split(".").map(Number); globalThis.experimentalFeatures = { // node_api_is_sharedarraybuffer and node_api_create_sharedarraybuffer were @@ -12,4 +12,11 @@ globalThis.experimentalFeatures = { createObjectWithProperties: true, setPrototype: true, postFinalizer: true, + // napi_create_dataview accepts a SharedArrayBuffer-backed buffer only since + // Node.js v24.13.1 and v25.4.0 (nodejs/node#60473). It was not backported to + // v20.x or v22.x, where such calls fail with "invalid argument". + dataviewSharedArrayBuffer: + major > 25 || + (major === 25 && minor >= 4) || + (major === 24 && (minor > 13 || (minor === 13 && patch >= 1))), }; diff --git a/tests/js-native-api/test_dataview/test.js b/tests/js-native-api/test_dataview/test.js index 2953a42..12fd9c6 100644 --- a/tests/js-native-api/test_dataview/test.js +++ b/tests/js-native-api/test_dataview/test.js @@ -15,20 +15,6 @@ const test_dataview = loadAddon("test_dataview"); ); } -// 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); @@ -36,11 +22,3 @@ const test_dataview = loadAddon("test_dataview"); 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); -} diff --git a/tests/js-native-api/test_dataview/test_sharedarraybuffer.js b/tests/js-native-api/test_dataview/test_sharedarraybuffer.js new file mode 100644 index 0000000..3218008 --- /dev/null +++ b/tests/js-native-api/test_dataview/test_sharedarraybuffer.js @@ -0,0 +1,32 @@ +"use strict"; + +// napi_create_dataview accepts a SharedArrayBuffer-backed buffer only on newer +// Node.js releases (see implementors/node/features.js). +if (!experimentalFeatures.dataviewSharedArrayBuffer) { + skipTest(); +} + +// Testing api calls for dataview backed by a SharedArrayBuffer +const test_dataview = loadAddon("test_dataview"); + +// 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 SharedArrayBuffer and invalid range +{ + const buffer = new SharedArrayBuffer(128); + assert.throws(() => { + test_dataview.CreateDataView(buffer, 10, 200); + }, RangeError); +}