napi_calm_down/js_values/
object.rs

1#[cfg(feature = "napi6")]
2use std::convert::TryFrom;
3#[cfg(feature = "napi5")]
4use std::ffi::c_void;
5#[cfg(feature = "napi5")]
6use std::ptr;
7
8#[cfg(feature = "napi5")]
9use super::check_status;
10use super::Value;
11#[cfg(feature = "napi5")]
12use crate::sys;
13#[cfg(feature = "napi5")]
14use crate::Env;
15#[cfg(feature = "napi6")]
16use crate::Error;
17#[cfg(feature = "napi5")]
18use crate::Result;
19
20pub struct JsObject(pub(crate) Value);
21impl From<Value> for JsObject {
22  fn from(value: Value) -> Self {
23    Self(value)
24  }
25}
26
27#[cfg(feature = "napi5")]
28pub struct FinalizeContext<T: 'static, Hint: 'static> {
29  pub env: Env,
30  pub value: T,
31  pub hint: Hint,
32}
33
34#[cfg(feature = "napi5")]
35impl 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")]
72unsafe 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, callback, raw_ref) =
82    unsafe { *Box::from_raw(finalize_data as *mut (T, F, sys::napi_ref)) };
83  let hint = unsafe { *Box::from_raw(finalize_hint as *mut Hint) };
84  let env = unsafe { Env::from_raw(raw_env) };
85  callback(FinalizeContext { env, value, hint });
86  if !raw_ref.is_null() {
87    let status = unsafe { sys::napi_delete_reference(raw_env, 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")]
96pub enum KeyCollectionMode {
97  IncludePrototypes,
98  OwnOnly,
99}
100
101#[cfg(feature = "napi6")]
102impl 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        format!("Invalid key collection mode: {}", value),
112      )),
113    }
114  }
115}
116
117#[cfg(feature = "napi6")]
118impl 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")]
128pub enum KeyFilter {
129  AllProperties,
130  Writable,
131  Enumerable,
132  Configurable,
133  SkipStrings,
134  SkipSymbols,
135}
136
137#[cfg(feature = "napi6")]
138impl 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        format!("Invalid key filter [{}]", value),
152      )),
153    }
154  }
155}
156
157#[cfg(feature = "napi6")]
158impl 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")]
172pub enum KeyConversion {
173  KeepNumbers,
174  NumbersToStrings,
175}
176
177#[cfg(feature = "napi6")]
178impl 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        format!("Invalid key conversion [{}]", value),
188      )),
189    }
190  }
191}
192
193#[cfg(feature = "napi6")]
194impl 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}