1#[cfg(feature = "napi5")]
2use std::ffi::c_void;
3#[cfg(feature = "napi5")]
4use std::ptr;
5
6#[cfg(feature = "napi5")]
7use super::check_status;
8use crate::{
9 bindgen_prelude::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue},
10 sys, Result, Value, ValueType,
11};
12#[cfg(feature = "napi5")]
13use crate::{bindgen_runtime::FinalizeContext, Env};
14
15#[deprecated(since = "3.0.0", note = "Use `napi::bindgen_prelude::Object` instead")]
16#[derive(Clone, Copy)]
17pub struct JsObject(pub(crate) Value);
18
19impl TypeName for JsObject {
20 fn type_name() -> &'static str {
21 "Object"
22 }
23
24 fn value_type() -> ValueType {
25 ValueType::Object
26 }
27}
28
29impl ValidateNapiValue for JsObject {}
30
31impl FromNapiValue for JsObject {
32 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
33 Ok(Self(Value {
34 env,
35 value: napi_val,
36 value_type: ValueType::Object,
37 }))
38 }
39}
40
41impl ToNapiValue for JsObject {
42 unsafe fn to_napi_value(_: sys::napi_env, value: Self) -> Result<sys::napi_value> {
43 Ok(value.0.value)
44 }
45}
46
47impl From<Value> for JsObject {
48 fn from(value: Value) -> Self {
49 Self(value)
50 }
51}
52
53#[cfg(feature = "napi5")]
54impl JsObject {
55 pub fn add_finalizer<T, Hint, F>(
56 &mut self,
57 native: T,
58 finalize_hint: Hint,
59 finalize_cb: F,
60 ) -> Result<()>
61 where
62 T: 'static,
63 Hint: 'static,
64 F: FnOnce(FinalizeContext<T, Hint>) + 'static,
65 {
66 let mut maybe_ref = ptr::null_mut();
67 let wrap_context = Box::leak(Box::new((native, finalize_cb, ptr::null_mut())));
68 check_status!(unsafe {
69 sys::napi_add_finalizer(
70 self.0.env,
71 self.0.value,
72 wrap_context as *mut _ as *mut c_void,
73 Some(
74 finalize_callback::<T, Hint, F>
75 as unsafe extern "C" fn(
76 env: sys::napi_env,
77 finalize_data: *mut c_void,
78 finalize_hint: *mut c_void,
79 ),
80 ),
81 Box::leak(Box::new(finalize_hint)) as *mut _ as *mut c_void,
82 &mut maybe_ref, )
84 })?;
85 wrap_context.2 = maybe_ref;
86 Ok(())
87 }
88}
89
90#[cfg(feature = "napi5")]
91unsafe extern "C" fn finalize_callback<T, Hint, F>(
92 raw_env: sys::napi_env,
93 finalize_data: *mut c_void,
94 finalize_hint: *mut c_void,
95) where
96 T: 'static,
97 Hint: 'static,
98 F: FnOnce(FinalizeContext<T, Hint>),
99{
100 let (value, callback, raw_ref) =
101 unsafe { *Box::from_raw(finalize_data as *mut (T, F, sys::napi_ref)) };
102 let hint = unsafe { *Box::from_raw(finalize_hint as *mut Hint) };
103 let env = Env::from_raw(raw_env);
104 callback(FinalizeContext { env, value, hint });
105 if !raw_ref.is_null() {
106 let status = unsafe { sys::napi_delete_reference(raw_env, raw_ref) };
107 debug_assert!(
108 status == sys::Status::napi_ok,
109 "Delete reference in finalize callback failed"
110 );
111 }
112}