#[cfg(feature = "napi5")]
use std::ffi::c_void;
#[cfg(feature = "napi5")]
use std::ptr;
#[cfg(feature = "napi5")]
use super::check_status;
use crate::{
bindgen_prelude::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
sys, Result, Value, ValueType,
};
#[cfg(feature = "napi5")]
use crate::{bindgen_runtime::FinalizeContext, Env};
#[deprecated(since = "3.0.0", note = "Use `napi::bindgen_prelude::Object` instead")]
#[derive(Clone, Copy)]
pub struct JsObject(pub(crate) Value);
impl TypeName for JsObject {
fn type_name() -> &'static str {
"Object"
}
fn value_type() -> ValueType {
ValueType::Object
}
}
impl ValidateNapiValue for JsObject {}
impl FromNapiValue for JsObject {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
Ok(Self(Value {
env,
value: napi_val,
value_type: ValueType::Object,
}))
}
}
impl ToNapiValue for JsObject {
unsafe fn to_napi_value(_: sys::napi_env, value: Self) -> Result<sys::napi_value> {
Ok(value.0.value)
}
}
impl From<Value> for JsObject {
fn from(value: Value) -> Self {
Self(value)
}
}
#[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>) + 'static,
{
let mut maybe_ref = ptr::null_mut();
let wrap_context = Box::leak(Box::new((native, finalize_cb, ptr::null_mut())));
check_status!(unsafe {
sys::napi_add_finalizer(
self.0.env,
self.0.value,
wrap_context 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, )
})?;
wrap_context.2 = maybe_ref;
Ok(())
}
}
#[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) =
unsafe { *Box::from_raw(finalize_data as *mut (T, F, sys::napi_ref)) };
let hint = unsafe { *Box::from_raw(finalize_hint as *mut Hint) };
let env = Env::from_raw(raw_env);
callback(FinalizeContext { env, value, hint });
if !raw_ref.is_null() {
let status = unsafe { sys::napi_delete_reference(raw_env, raw_ref) };
debug_assert!(
status == sys::Status::napi_ok,
"Delete reference in finalize callback failed"
);
}
}