diff --git a/ext/napi/js_native_api.rs b/ext/napi/js_native_api.rs index e5b25c391b..f02103c899 100644 --- a/ext/napi/js_native_api.rs +++ b/ext/napi/js_native_api.rs @@ -2938,7 +2938,7 @@ fn napi_create_external_arraybuffer<'s>( env: &'s mut Env, data: *mut c_void, byte_length: usize, - finalize_cb: napi_finalize, + finalize_cb: Option, finalize_hint: *mut c_void, result: *mut napi_value<'s>, ) -> napi_status { diff --git a/ext/napi/node_api.rs b/ext/napi/node_api.rs index 9d60fdf1ea..f70521de11 100644 --- a/ext/napi/node_api.rs +++ b/ext/napi/node_api.rs @@ -319,7 +319,7 @@ fn napi_create_external_buffer<'s>( env: &'s mut Env, length: usize, data: *mut c_void, - finalize_cb: napi_finalize, + finalize_cb: Option, finalize_hint: *mut c_void, result: *mut napi_value<'s>, ) -> napi_status { diff --git a/ext/napi/util.rs b/ext/napi/util.rs index 8b95672472..78e85d8a1b 100644 --- a/ext/napi/util.rs +++ b/ext/napi/util.rs @@ -25,15 +25,17 @@ pub fn get_array_buffer_ptr(ab: v8::Local) -> *mut c_void { struct BufferFinalizer { env: *mut Env, - finalize_cb: napi_finalize, + finalize_cb: Option, finalize_data: *mut c_void, finalize_hint: *mut c_void, } impl Drop for BufferFinalizer { fn drop(&mut self) { - unsafe { - (self.finalize_cb)(self.env as _, self.finalize_data, self.finalize_hint); + if let Some(finalize_cb) = self.finalize_cb { + unsafe { + finalize_cb(self.env as _, self.finalize_data, self.finalize_hint); + } } } } @@ -56,7 +58,7 @@ pub(crate) fn make_external_backing_store( data: *mut c_void, byte_length: usize, finalize_data: *mut c_void, - finalize_cb: napi_finalize, + finalize_cb: Option, finalize_hint: *mut c_void, ) -> v8::UniqueRef { let finalizer = Box::new(BufferFinalizer { diff --git a/tests/napi/arraybuffer_test.js b/tests/napi/arraybuffer_test.js index a11f761130..6f4115e6de 100644 --- a/tests/napi/arraybuffer_test.js +++ b/tests/napi/arraybuffer_test.js @@ -1,6 +1,7 @@ // Copyright 2018-2025 the Deno authors. MIT license. import { assert, assertEquals, loadTestLibrary } from "./common.js"; +import { Buffer } from "node:buffer"; const typedarray = loadTestLibrary(); @@ -22,3 +23,8 @@ Deno.test("napi arraybuffer is detached", function () { assert(!typedarray.is_detached(value)); }); }); + +Deno.test("napi buffer finalizer may be null", () => { + const buf = typedarray.test_static_external_buffer(); + assertEquals(buf, Buffer.from([1, 2, 3])); +}); diff --git a/tests/napi/src/finalizer.rs b/tests/napi/src/finalizer.rs index a310946fd1..f3b6bb9c10 100644 --- a/tests/napi/src/finalizer.rs +++ b/tests/napi/src/finalizer.rs @@ -107,6 +107,24 @@ extern "C" fn test_external_buffer( result } +extern "C" fn test_static_external_buffer( + env: napi_env, + _: napi_callback_info, +) -> napi_value { + let mut result = ptr::null_mut(); + static BUF: &[u8] = &[1, 2, 3]; + assert_napi_ok!(napi_create_external_buffer( + env, + BUF.len(), + BUF.as_ptr() as _, + None, + ptr::null_mut(), + &mut result + )); + + result +} + extern "C" fn test_external_arraybuffer( env: napi_env, _: napi_callback_info, @@ -136,6 +154,11 @@ pub fn init(env: napi_env, exports: napi_value) { "test_external_arraybuffer", test_external_arraybuffer ), + napi_new_property!( + env, + "test_static_external_buffer", + test_static_external_buffer + ), ]; assert_napi_ok!(napi_define_properties(