diff --git a/src/guest/napi.rs b/src/guest/napi.rs index 3baeeaf..3d18e28 100644 --- a/src/guest/napi.rs +++ b/src/guest/napi.rs @@ -4746,17 +4746,19 @@ fn guest_napi_wrap( e: i32, obj: i32, native_data: i32, - _finalize_cb: i32, + finalize_cb: i32, _finalize_hint: i32, ref_ptr: i32, ) -> i32 { let mut ref_out: u32 = 0; + let has_finalize_cb = (finalize_cb != 0) as i32; let s = if ref_ptr > 0 { unsafe { snapi_bridge_wrap( snapi_env(&env, e), obj as u32, native_data as u64, + has_finalize_cb, &mut ref_out, ) } @@ -4766,6 +4768,7 @@ fn guest_napi_wrap( snapi_env(&env, e), obj as u32, native_data as u64, + has_finalize_cb, std::ptr::null_mut(), ) } @@ -4799,14 +4802,21 @@ fn guest_napi_add_finalizer( e: i32, obj: i32, data: i32, - _finalize_cb: i32, + finalize_cb: i32, _finalize_hint: i32, ref_ptr: i32, ) -> i32 { let mut ref_out: u32 = 0; + let has_finalize_cb = if finalize_cb != 0 { 1 } else { 0 }; let s = if ref_ptr > 0 { unsafe { - snapi_bridge_add_finalizer(snapi_env(&env, e), obj as u32, data as u64, &mut ref_out) + snapi_bridge_add_finalizer( + snapi_env(&env, e), + obj as u32, + data as u64, + has_finalize_cb, + &mut ref_out, + ) } } else { unsafe { @@ -4814,6 +4824,7 @@ fn guest_napi_add_finalizer( snapi_env(&env, e), obj as u32, data as u64, + has_finalize_cb, std::ptr::null_mut(), ) } diff --git a/src/napi_bridge_init.cc b/src/napi_bridge_init.cc index f147722..ae8462b 100644 --- a/src/napi_bridge_init.cc +++ b/src/napi_bridge_init.cc @@ -2044,16 +2044,20 @@ extern "C" int snapi_bridge_get_node_version(SnapiEnvState* env_state, uint32_t* // Object wrapping // ============================================================ +void NAPI_CDECL NoopGuestFinalizer(node_api_nogc_env /*env*/, void* /*data*/, void* /*hint*/) {} + extern "C" int snapi_bridge_wrap(SnapiEnvState* env_state, uint32_t obj_id, uint64_t native_data, - uint32_t* ref_out) { + int has_finalize_cb, uint32_t* ref_out) { auto* bridge_state = RequireEnvState(env_state); if (bridge_state == nullptr) return napi_invalid_arg; napi_env env = bridge_state->env; napi_value obj = LoadValue(*bridge_state, obj_id); if (!obj) return napi_invalid_arg; + node_api_basic_finalize finalize_cb = + has_finalize_cb ? NoopGuestFinalizer : nullptr; napi_ref ref = nullptr; napi_status s = napi_wrap(env, obj, (void*)(uintptr_t)native_data, - nullptr, nullptr, ref_out ? &ref : nullptr); + finalize_cb, nullptr, ref_out ? &ref : nullptr); if (s != napi_ok) return s; if (ref_out) *ref_out = StoreRef(*bridge_state, ref); return napi_ok; @@ -2086,16 +2090,16 @@ extern "C" int snapi_bridge_remove_wrap(SnapiEnvState* env_state, uint32_t obj_i } extern "C" int snapi_bridge_add_finalizer(SnapiEnvState* env_state, uint32_t obj_id, uint64_t data_val, - uint32_t* ref_out) { + int has_finalize_cb, uint32_t* ref_out) { auto* bridge_state = RequireEnvState(env_state); if (bridge_state == nullptr) return napi_invalid_arg; napi_env env = bridge_state->env; napi_value obj = LoadValue(*bridge_state, obj_id); if (!obj) return napi_invalid_arg; - // No actual WASM callback for finalizer; just register with nullptr callback + if (!has_finalize_cb) return napi_invalid_arg; napi_ref ref = nullptr; napi_status s = napi_add_finalizer(env, obj, (void*)(uintptr_t)data_val, - nullptr, nullptr, ref_out ? &ref : nullptr); + NoopGuestFinalizer, nullptr, ref_out ? &ref : nullptr); if (s != napi_ok) return s; if (ref_out) *ref_out = StoreRef(*bridge_state, ref); return napi_ok; diff --git a/src/snapi.rs b/src/snapi.rs index 373d4ef..2721c51 100644 --- a/src/snapi.rs +++ b/src/snapi.rs @@ -876,6 +876,7 @@ unsafe extern "C" { env: SnapiEnv, obj_id: u32, native_data: u64, + has_finalize_cb: i32, ref_out: *mut u32, ) -> i32; pub fn snapi_bridge_unwrap(env: SnapiEnv, obj_id: u32, data_out: *mut u64) -> i32; @@ -884,6 +885,7 @@ unsafe extern "C" { env: SnapiEnv, obj_id: u32, data_val: u64, + has_finalize_cb: i32, ref_out: *mut u32, ) -> i32; // Constructor