From c621986ce590b98f77aa4ddb63a1fa5c2fc6209b Mon Sep 17 00:00:00 2001 From: LongYinan Date: Wed, 16 Dec 2020 23:23:04 +0800 Subject: [PATCH] feat(napi): implement add_finalizer for JsObject --- napi/src/js_values/object.rs | 83 +++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/napi/src/js_values/object.rs b/napi/src/js_values/object.rs index e3827a33..81df628d 100644 --- a/napi/src/js_values/object.rs +++ b/napi/src/js_values/object.rs @@ -1,13 +1,86 @@ -use super::Value; -#[cfg(feature = "napi6")] -use crate::sys; -#[cfg(feature = "napi6")] -use crate::{Error, Result}; #[cfg(feature = "napi6")] use std::convert::TryFrom; +#[cfg(feature = "napi5")] +use std::ffi::c_void; +#[cfg(feature = "napi5")] +use std::ptr; + +#[cfg(feature = "napi5")] +use super::check_status; +use super::Value; +#[cfg(feature = "napi5")] +use crate::sys; +#[cfg(feature = "napi5")] +use crate::Env; +#[cfg(feature = "napi6")] +use crate::{Error, Result}; pub struct JsObject(pub(crate) Value); +#[cfg(feature = "napi5")] +pub struct FinalizeContext { + pub env: Env, + pub value: T, + pub hint: Hint, +} + +#[cfg(feature = "napi5")] +impl JsObject { + pub fn add_finalizer( + &mut self, + native: T, + finalize_hint: Hint, + finalize_cb: F, + ) -> Result<()> + where + T: 'static, + Hint: 'static, + F: FnOnce(FinalizeContext), + { + let mut maybe_ref = ptr::null_mut(); + check_status!(unsafe { + sys::napi_add_finalizer( + self.0.env, + self.0.value, + Box::leak(Box::new((native, finalize_cb, maybe_ref))) as *mut _ as *mut c_void, + Some( + finalize_callback:: + as unsafe extern "C" fn( + env: sys::napi_env, + finalize_data: *mut c_void, + finalize_hint: *mut c_void, + ), + ), + Box::leak(Box::new(finalize_hint)) as *mut _ as *mut c_void, + &mut maybe_ref, + ) + }) + } +} + +#[cfg(feature = "napi5")] +unsafe extern "C" fn finalize_callback( + raw_env: sys::napi_env, + finalize_data: *mut c_void, + finalize_hint: *mut c_void, +) where + T: 'static, + Hint: 'static, + F: FnOnce(FinalizeContext), +{ + let (value, callback, raw_ref) = *Box::from_raw(finalize_data as *mut (T, F, sys::napi_ref)); + let hint = *Box::from_raw(finalize_hint as *mut Hint); + let env = Env::from_raw(raw_env); + callback(FinalizeContext { value, hint, env }); + if !raw_ref.is_null() { + let status = sys::napi_delete_reference(raw_env, raw_ref); + debug_assert!( + status == sys::Status::napi_ok, + "Delete reference in finalize callback failed" + ); + } +} + #[cfg(feature = "napi6")] pub enum KeyCollectionMode { IncludePrototypes,