node-api: add napi_create_external_sharedarraybuffer

Creates a SharedArrayBuffer from externally managed memory.

Fixes: https://github.com/nodejs/node/issues/62259
PR-URL: https://github.com/nodejs/node/pull/62623
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Vladimir Morozov <vmorozov@microsoft.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
This commit is contained in:
Ben Noordhuis authored and Juan José Arboleda committed 2026-07-19 17:31:05 -05:00
1 parent e9e73f56fa
commit 0e83bae7cb
7 files changed
+132 -2

No files matched your search

+2 -1
View File
@@ -3,7 +3,8 @@
{
"target_name": "test_buffer",
"defines": [
'NAPI_VERSION=10'
"NAPI_EXPERIMENTAL",
"NODE_API_EXPERIMENTAL_NO_WARNING"
],
"sources": [ "test_buffer.c" ]
},
+13 -1
View File
@@ -4,7 +4,8 @@
const common = require('../../common');
const binding = require(`./build/${common.buildType}/test_buffer`);
const assert = require('assert');
const tick = require('util').promisify(require('../../common/tick'));
const util = require('util');
const tick = util.promisify(require('../../common/tick'));
(async function() {
assert.strictEqual(binding.newBuffer().toString(), binding.theText);
@@ -26,6 +27,17 @@ const tick = require('util').promisify(require('../../common/tick'));
console.log('gc2');
assert.strictEqual(binding.getDeleterCallCount(), 2);
// Caveat emptor: it's indeterminate when the SharedArrayBuffer's backing
// store is reclaimed; at least some of the time it happens even before
// calling gc().
let sab = binding.newExternalSharedArrayBuffer();
assert(util.types.isSharedArrayBuffer(sab));
sab = null;
global.gc();
await tick(10);
console.log('gc3');
assert.strictEqual(binding.getDeleterCallCount(), 3);
// To test this doesn't crash
binding.invalidObjectAsBuffer({});
+26
View File
@@ -58,6 +58,30 @@ static napi_value newExternalBuffer(napi_env env, napi_callback_info info) {
return theBuffer;
}
static char externalSharedArrayBufferData[1];
static void freeExternalSharedArrayBuffer(void* data, void* hint) {
(void)hint;
NODE_API_BASIC_ASSERT_RETURN_VOID(
data == (void*)externalSharedArrayBufferData,
"SharedArrayBuffer points to wrong data");
deleterCallCount++;
}
static napi_value newExternalSharedArrayBuffer(napi_env env,
napi_callback_info info) {
napi_value sab;
NODE_API_CALL(
env,
node_api_create_external_sharedarraybuffer(env,
externalSharedArrayBufferData,
1,
freeExternalSharedArrayBuffer,
NULL,
&sab));
return sab;
}
static napi_value getDeleterCallCount(napi_env env, napi_callback_info info) {
napi_value callCount;
NODE_API_CALL(env, napi_create_int32(env, deleterCallCount, &callCount));
@@ -171,6 +195,8 @@ static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor methods[] = {
DECLARE_NODE_API_PROPERTY("newBuffer", newBuffer),
DECLARE_NODE_API_PROPERTY("newExternalBuffer", newExternalBuffer),
DECLARE_NODE_API_PROPERTY("newExternalSharedArrayBuffer",
newExternalSharedArrayBuffer),
DECLARE_NODE_API_PROPERTY("getDeleterCallCount", getDeleterCallCount),
DECLARE_NODE_API_PROPERTY("copyBuffer", copyBuffer),
DECLARE_NODE_API_PROPERTY("bufferHasInstance", bufferHasInstance),