1 | #[cfg (feature = "napi6" )] |
2 | use std::convert::TryFrom; |
3 | #[cfg (feature = "napi5" )] |
4 | use std::ffi::c_void; |
5 | #[cfg (feature = "napi5" )] |
6 | use std::ptr; |
7 | |
8 | #[cfg (feature = "napi5" )] |
9 | use super::check_status; |
10 | use super::Value; |
11 | #[cfg (feature = "napi5" )] |
12 | use crate::sys; |
13 | #[cfg (feature = "napi5" )] |
14 | use crate::Env; |
15 | #[cfg (feature = "napi6" )] |
16 | use crate::Error; |
17 | #[cfg (feature = "napi5" )] |
18 | use crate::Result; |
19 | |
20 | pub struct JsObject(pub(crate) Value); |
21 | impl From<Value> for JsObject { |
22 | fn from(value: Value) -> Self { |
23 | Self(value) |
24 | } |
25 | } |
26 | |
27 | #[cfg (feature = "napi5" )] |
28 | pub struct FinalizeContext<T: 'static, Hint: 'static> { |
29 | pub env: Env, |
30 | pub value: T, |
31 | pub hint: Hint, |
32 | } |
33 | |
34 | #[cfg (feature = "napi5" )] |
35 | impl JsObject { |
36 | pub fn add_finalizer<T, Hint, F>( |
37 | &mut self, |
38 | native: T, |
39 | finalize_hint: Hint, |
40 | finalize_cb: F, |
41 | ) -> Result<()> |
42 | where |
43 | T: 'static, |
44 | Hint: 'static, |
45 | F: FnOnce(FinalizeContext<T, Hint>) + 'static, |
46 | { |
47 | let mut maybe_ref = ptr::null_mut(); |
48 | let wrap_context = Box::leak(Box::new((native, finalize_cb, ptr::null_mut()))); |
49 | check_status!(unsafe { |
50 | sys::napi_add_finalizer( |
51 | self.0.env, |
52 | self.0.value, |
53 | wrap_context as *mut _ as *mut c_void, |
54 | Some( |
55 | finalize_callback::<T, Hint, F> |
56 | as unsafe extern "C" fn( |
57 | env: sys::napi_env, |
58 | finalize_data: *mut c_void, |
59 | finalize_hint: *mut c_void, |
60 | ), |
61 | ), |
62 | Box::leak(Box::new(finalize_hint)) as *mut _ as *mut c_void, |
63 | &mut maybe_ref, // Note: this does not point to the boxed one⦠|
64 | ) |
65 | })?; |
66 | wrap_context.2 = maybe_ref; |
67 | Ok(()) |
68 | } |
69 | } |
70 | |
71 | #[cfg (feature = "napi5" )] |
72 | unsafe extern "C" fn finalize_callback<T, Hint, F>( |
73 | raw_env: sys::napi_env, |
74 | finalize_data: *mut c_void, |
75 | finalize_hint: *mut c_void, |
76 | ) where |
77 | T: 'static, |
78 | Hint: 'static, |
79 | F: FnOnce(FinalizeContext<T, Hint>), |
80 | { |
81 | let (value: T, callback: F, raw_ref: *mut napi_ref__) = |
82 | unsafe { *Box::from_raw(finalize_data as *mut (T, F, sys::napi_ref)) }; |
83 | let hint: Hint = unsafe { *Box::from_raw(finalize_hint as *mut Hint) }; |
84 | let env: Env = unsafe { Env::from_raw(raw_env) }; |
85 | callback(FinalizeContext { env, value, hint }); |
86 | if !raw_ref.is_null() { |
87 | let status: i32 = unsafe { sys::napi_delete_reference(raw_env, ref_:raw_ref) }; |
88 | debug_assert!( |
89 | status == sys::Status::napi_ok, |
90 | "Delete reference in finalize callback failed" |
91 | ); |
92 | } |
93 | } |
94 | |
95 | #[cfg (feature = "napi6" )] |
96 | pub enum KeyCollectionMode { |
97 | IncludePrototypes, |
98 | OwnOnly, |
99 | } |
100 | |
101 | #[cfg (feature = "napi6" )] |
102 | impl TryFrom<sys::napi_key_collection_mode> for KeyCollectionMode { |
103 | type Error = Error; |
104 | |
105 | fn try_from(value: sys::napi_key_collection_mode) -> Result<Self> { |
106 | match value { |
107 | sys::KeyCollectionMode::include_prototypes => Ok(Self::IncludePrototypes), |
108 | sys::KeyCollectionMode::own_only => Ok(Self::OwnOnly), |
109 | _ => Err(Error::new( |
110 | crate::Status::InvalidArg, |
111 | reason:format!("Invalid key collection mode: {}" , value), |
112 | )), |
113 | } |
114 | } |
115 | } |
116 | |
117 | #[cfg (feature = "napi6" )] |
118 | impl From<KeyCollectionMode> for sys::napi_key_collection_mode { |
119 | fn from(value: KeyCollectionMode) -> Self { |
120 | match value { |
121 | KeyCollectionMode::IncludePrototypes => sys::KeyCollectionMode::include_prototypes, |
122 | KeyCollectionMode::OwnOnly => sys::KeyCollectionMode::own_only, |
123 | } |
124 | } |
125 | } |
126 | |
127 | #[cfg (feature = "napi6" )] |
128 | pub enum KeyFilter { |
129 | AllProperties, |
130 | Writable, |
131 | Enumerable, |
132 | Configurable, |
133 | SkipStrings, |
134 | SkipSymbols, |
135 | } |
136 | |
137 | #[cfg (feature = "napi6" )] |
138 | impl TryFrom<sys::napi_key_filter> for KeyFilter { |
139 | type Error = Error; |
140 | |
141 | fn try_from(value: sys::napi_key_filter) -> Result<Self> { |
142 | match value { |
143 | sys::KeyFilter::all_properties => Ok(Self::AllProperties), |
144 | sys::KeyFilter::writable => Ok(Self::Writable), |
145 | sys::KeyFilter::enumerable => Ok(Self::Enumerable), |
146 | sys::KeyFilter::configurable => Ok(Self::Configurable), |
147 | sys::KeyFilter::skip_strings => Ok(Self::SkipStrings), |
148 | sys::KeyFilter::skip_symbols => Ok(Self::SkipSymbols), |
149 | _ => Err(Error::new( |
150 | crate::Status::InvalidArg, |
151 | reason:format!("Invalid key filter [ {}]" , value), |
152 | )), |
153 | } |
154 | } |
155 | } |
156 | |
157 | #[cfg (feature = "napi6" )] |
158 | impl From<KeyFilter> for sys::napi_key_filter { |
159 | fn from(value: KeyFilter) -> Self { |
160 | match value { |
161 | KeyFilter::AllProperties => sys::KeyFilter::all_properties, |
162 | KeyFilter::Writable => sys::KeyFilter::writable, |
163 | KeyFilter::Enumerable => sys::KeyFilter::enumerable, |
164 | KeyFilter::Configurable => sys::KeyFilter::configurable, |
165 | KeyFilter::SkipStrings => sys::KeyFilter::skip_strings, |
166 | KeyFilter::SkipSymbols => sys::KeyFilter::skip_symbols, |
167 | } |
168 | } |
169 | } |
170 | |
171 | #[cfg (feature = "napi6" )] |
172 | pub enum KeyConversion { |
173 | KeepNumbers, |
174 | NumbersToStrings, |
175 | } |
176 | |
177 | #[cfg (feature = "napi6" )] |
178 | impl TryFrom<sys::napi_key_conversion> for KeyConversion { |
179 | type Error = Error; |
180 | |
181 | fn try_from(value: sys::napi_key_conversion) -> Result<Self> { |
182 | match value { |
183 | sys::KeyConversion::keep_numbers => Ok(Self::KeepNumbers), |
184 | sys::KeyConversion::numbers_to_strings => Ok(Self::NumbersToStrings), |
185 | _ => Err(Error::new( |
186 | crate::Status::InvalidArg, |
187 | reason:format!("Invalid key conversion [ {}]" , value), |
188 | )), |
189 | } |
190 | } |
191 | } |
192 | |
193 | #[cfg (feature = "napi6" )] |
194 | impl From<KeyConversion> for sys::napi_key_conversion { |
195 | fn from(value: KeyConversion) -> Self { |
196 | match value { |
197 | KeyConversion::KeepNumbers => sys::KeyConversion::keep_numbers, |
198 | KeyConversion::NumbersToStrings => sys::KeyConversion::numbers_to_strings, |
199 | } |
200 | } |
201 | } |
202 | |