From 1bbb8f7f885595c910474dbace1057851886459d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20G=C3=BCzel?= Date: Tue, 10 Nov 2026 19:24:10 +0300 Subject: [PATCH] node-api: reject detaching immutable arraybuffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit return napi_detachable_arraybuffer_expected for immutable arraybuffers instead of aborting when v8 rejects the detach operation. Refs: https://github.com/nodejs/node/issues/66346 Signed-off-by: Fatih Güzel --- src/js_native_api_v8.cc | 5 ++-- .../test_typedarray/test-detach-immutable.js | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 test/js-native-api/test_typedarray/test-detach-immutable.js diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index ba1ab6f18511..6fbf33040c52 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -3724,8 +3724,9 @@ napi_status NAPI_CDECL napi_detach_arraybuffer(napi_env env, env, value->IsArrayBuffer(), napi_arraybuffer_expected); v8::Local it = value.As(); - RETURN_STATUS_IF_FALSE( - env, it->IsDetachable(), napi_detachable_arraybuffer_expected); + RETURN_STATUS_IF_FALSE(env, + it->IsDetachable() && !it->IsImmutable(), + napi_detachable_arraybuffer_expected); it->Detach(v8::Local()).Check(); diff --git a/test/js-native-api/test_typedarray/test-detach-immutable.js b/test/js-native-api/test_typedarray/test-detach-immutable.js new file mode 100644 index 000000000000..67402f06e3e3 --- /dev/null +++ b/test/js-native-api/test_typedarray/test-detach-immutable.js @@ -0,0 +1,25 @@ +// Flags: --js-immutable-arraybuffer +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const binding = require(`./build/${common.buildType}/test_typedarray`); + +for (const bytes of [[1, 2, 3, 4], []]) { + const buffer = Uint8Array.from(bytes).buffer.transferToImmutable(); + const view = new Uint8Array(buffer); + + assert.throws(() => binding.Detach(view), { + name: 'Error', + message: 'A detachable arraybuffer was expected', + }); + assert.strictEqual(binding.IsDetached(buffer), false); + assert.strictEqual(buffer.immutable, true); + assert.strictEqual(view.byteLength, bytes.length); + assert.deepStrictEqual([...view], bytes); + + const mutable = Uint8Array.from(bytes); + binding.Detach(mutable); + assert.strictEqual(binding.IsDetached(mutable.buffer), true); + assert.strictEqual(mutable.byteLength, 0); +}