feat(napi): implement add_finalizer for JsObject

This commit is contained in:
LongYinan 2020-12-16 23:23:04 +08:00
parent 74256bcae7
commit c621986ce5
No known key found for this signature in database
GPG key ID: C3666B7FC82ADAD7

View file

@ -1,13 +1,86 @@
use super::Value;
#[cfg(feature = "napi6")]
use crate::sys;
#[cfg(feature = "napi6")]
use crate::{Error, Result};
#[cfg(feature = "napi6")] #[cfg(feature = "napi6")]
use std::convert::TryFrom; 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); pub struct JsObject(pub(crate) Value);
#[cfg(feature = "napi5")]
pub struct FinalizeContext<T: 'static, Hint: 'static> {
pub env: Env,
pub value: T,
pub hint: Hint,
}
#[cfg(feature = "napi5")]
impl JsObject {
pub fn add_finalizer<T, Hint, F>(
&mut self,
native: T,
finalize_hint: Hint,
finalize_cb: F,
) -> Result<()>
where
T: 'static,
Hint: 'static,
F: FnOnce(FinalizeContext<T, Hint>),
{
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::<T, Hint, F>
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<T, Hint, F>(
raw_env: sys::napi_env,
finalize_data: *mut c_void,
finalize_hint: *mut c_void,
) where
T: 'static,
Hint: 'static,
F: FnOnce(FinalizeContext<T, Hint>),
{
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")] #[cfg(feature = "napi6")]
pub enum KeyCollectionMode { pub enum KeyCollectionMode {
IncludePrototypes, IncludePrototypes,