1 | use std::ffi::c_void; |
2 | use std::rc::Rc; |
3 | |
4 | pub use callback_info::*; |
5 | pub use ctor::ctor; |
6 | pub use env::*; |
7 | pub use iterator::Generator; |
8 | pub use js_values::*; |
9 | pub use module_register::*; |
10 | |
11 | use super::sys; |
12 | use crate::{JsError, Result, Status}; |
13 | |
14 | mod callback_info; |
15 | mod env; |
16 | mod error; |
17 | pub mod iterator; |
18 | mod js_values; |
19 | mod module_register; |
20 | |
21 | pub trait ObjectFinalize: Sized { |
22 | #[allow (unused)] |
23 | fn finalize(self, env: Env) -> Result<()> { |
24 | Ok(()) |
25 | } |
26 | } |
27 | |
28 | /// # Safety |
29 | /// |
30 | /// called when node wrapper objects destroyed |
31 | #[doc (hidden)] |
32 | pub unsafe extern "C" fn raw_finalize_unchecked<T: ObjectFinalize>( |
33 | env: sys::napi_env, |
34 | finalize_data: *mut c_void, |
35 | _finalize_hint: *mut c_void, |
36 | ) { |
37 | let data: Box<T> = unsafe { Box::from_raw(finalize_data.cast()) }; |
38 | if let Err(err) = data.finalize(unsafe { Env::from_raw(env) }) { |
39 | let e: JsError = err.into(); |
40 | unsafe { e.throw_into(env) }; |
41 | return; |
42 | } |
43 | if let Some((_, ref_val, finalize_callbacks_ptr)) = |
44 | REFERENCE_MAP.with(|reference_map| reference_map.borrow_mut().remove(&finalize_data)) |
45 | { |
46 | let finalize_callbacks_rc = unsafe { Rc::from_raw(finalize_callbacks_ptr) }; |
47 | |
48 | #[cfg (all(debug_assertions, not(target_family = "wasm" )))] |
49 | { |
50 | let rc_strong_count = Rc::strong_count(&finalize_callbacks_rc); |
51 | // If `Rc` strong count is 2, it means the finalize of referenced `Object` is called before the `fn drop` of the `Reference` |
52 | // It always happened on exiting process |
53 | // In general, the `fn drop` would happen first |
54 | assert!( |
55 | rc_strong_count == 1 || rc_strong_count == 2, |
56 | "Rc strong count is: {}, it should be 1 or 2" , |
57 | rc_strong_count |
58 | ); |
59 | } |
60 | let finalize = unsafe { Box::from_raw(finalize_callbacks_rc.get()) }; |
61 | finalize(); |
62 | let delete_reference_status = unsafe { sys::napi_delete_reference(env, ref_val) }; |
63 | debug_assert!( |
64 | delete_reference_status == sys::Status::napi_ok, |
65 | "Delete reference in finalize callback failed {}" , |
66 | Status::from(delete_reference_status) |
67 | ); |
68 | } |
69 | } |
70 | |
71 | /// # Safety |
72 | /// |
73 | /// called when node buffer is ready for gc |
74 | #[doc (hidden)] |
75 | pub unsafe extern "C" fn drop_buffer( |
76 | _env: sys::napi_env, |
77 | #[allow (unused)] finalize_data: *mut c_void, |
78 | finalize_hint: *mut c_void, |
79 | ) { |
80 | #[cfg (all(debug_assertions, not(windows)))] |
81 | { |
82 | js_values::BUFFER_DATA.with(|buffer_data: &Mutex>| { |
83 | let mut buffer: MutexGuard<'_, HashSet<*mut …>> = buffer_data.lock().expect(msg:"Unlock Buffer data failed" ); |
84 | buffer.remove(&(finalize_data as *mut u8)); |
85 | }); |
86 | } |
87 | unsafe { |
88 | drop(Box::from_raw(finalize_hint as *mut Buffer)); |
89 | } |
90 | } |
91 | |