diff options
author | Divy Srivastava <dj.srivastava23@gmail.com> | 2023-05-18 19:15:47 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-18 19:15:47 +0530 |
commit | c3f7e6ed6ea2da6b8be5c7b29619eb51e0c9a6e3 (patch) | |
tree | dee07dbadf9dfe69bbfac707dde344f9528ef05a /ext/napi | |
parent | 695b5de6cb0cb4a10b95cbae99f2f19e5621a9eb (diff) |
fix(cli/napi): handle finalizers (#19168)
Fixes https://github.com/denoland/deno/issues/17325
Diffstat (limited to 'ext/napi')
-rw-r--r-- | ext/napi/lib.rs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index 2e7ceed67..8365a5692 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -592,6 +592,50 @@ pub trait NapiPermissions { -> std::result::Result<(), AnyError>; } +/// # Safety +/// +/// This function is unsafe because it dereferences raw pointer Env. +/// - The caller must ensure that the pointer is valid. +/// - The caller must ensure that the pointer is not freed. +pub unsafe fn weak_local( + env_ptr: *mut Env, + value: v8::Local<v8::Value>, + data: *mut c_void, + finalize_cb: napi_finalize, + finalize_hint: *mut c_void, +) -> Option<v8::Local<v8::Value>> { + use std::cell::Cell; + + let env = &mut *env_ptr; + + let weak_ptr = Rc::new(Cell::new(None)); + let scope = &mut env.scope(); + + let weak = v8::Weak::with_finalizer( + scope, + value, + Box::new({ + let weak_ptr = weak_ptr.clone(); + move |isolate| { + finalize_cb(env_ptr as _, data as _, finalize_hint as _); + + // Self-deleting weak. + if let Some(weak_ptr) = weak_ptr.get() { + let weak: v8::Weak<v8::Value> = + unsafe { v8::Weak::from_raw(isolate, Some(weak_ptr)) }; + drop(weak); + } + } + }), + ); + + let value = weak.to_local(scope); + let raw = weak.into_raw(); + weak_ptr.set(raw); + + value +} + #[op(v8)] fn op_napi_open<NP, 'scope>( scope: &mut v8::HandleScope<'scope>, |