#[cfg(feature = "napi6")] use std::convert::TryFrom; #[cfg(feature = "napi5")] use std::ffi::c_void; #[cfg(feature = "napi5")] use std::ptr; #[cfg(feature = "napi5")] use super::check_status; use super::Value; #[cfg(feature = "napi5")] use crate::sys; #[cfg(feature = "napi5")] use crate::Env; #[cfg(feature = "napi6")] use crate::Error; #[cfg(feature = "napi5")] use crate::Result; pub struct JsObject(pub(crate) Value); #[cfg(feature = "napi5")] pub struct FinalizeContext { pub env: Env, pub value: T, pub hint: Hint, } #[cfg(feature = "napi5")] impl JsObject { pub fn add_finalizer( &mut self, native: T, finalize_hint: Hint, finalize_cb: F, ) -> Result<()> where T: 'static, Hint: 'static, F: FnOnce(FinalizeContext), { 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:: 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, // Note: this does not point to the boxed oneā€¦ ) })?; wrap_context.2 = maybe_ref; Ok(()) } } #[cfg(feature = "napi5")] unsafe extern "C" fn finalize_callback( raw_env: sys::napi_env, finalize_data: *mut c_void, finalize_hint: *mut c_void, ) where T: 'static, Hint: 'static, F: FnOnce(FinalizeContext), { 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 = unsafe { 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" ); } } #[cfg(feature = "napi6")] pub enum KeyCollectionMode { IncludePrototypes, OwnOnly, } #[cfg(feature = "napi6")] impl TryFrom for KeyCollectionMode { type Error = Error; fn try_from(value: sys::napi_key_collection_mode) -> Result { match value { sys::KeyCollectionMode::include_prototypes => Ok(Self::IncludePrototypes), sys::KeyCollectionMode::own_only => Ok(Self::OwnOnly), _ => Err(Error::new( crate::Status::InvalidArg, format!("Invalid key collection mode: {}", value), )), } } } #[cfg(feature = "napi6")] impl From for sys::napi_key_collection_mode { fn from(value: KeyCollectionMode) -> Self { match value { KeyCollectionMode::IncludePrototypes => sys::KeyCollectionMode::include_prototypes, KeyCollectionMode::OwnOnly => sys::KeyCollectionMode::own_only, } } } #[cfg(feature = "napi6")] pub enum KeyFilter { AllProperties, Writable, Enumerable, Configurable, SkipStrings, SkipSymbols, } #[cfg(feature = "napi6")] impl TryFrom for KeyFilter { type Error = Error; fn try_from(value: sys::napi_key_filter) -> Result { match value { sys::KeyFilter::all_properties => Ok(Self::AllProperties), sys::KeyFilter::writable => Ok(Self::Writable), sys::KeyFilter::enumerable => Ok(Self::Enumerable), sys::KeyFilter::configurable => Ok(Self::Configurable), sys::KeyFilter::skip_strings => Ok(Self::SkipStrings), sys::KeyFilter::skip_symbols => Ok(Self::SkipSymbols), _ => Err(Error::new( crate::Status::InvalidArg, format!("Invalid key filter [{}]", value), )), } } } #[cfg(feature = "napi6")] impl From for sys::napi_key_filter { fn from(value: KeyFilter) -> Self { match value { KeyFilter::AllProperties => sys::KeyFilter::all_properties, KeyFilter::Writable => sys::KeyFilter::writable, KeyFilter::Enumerable => sys::KeyFilter::enumerable, KeyFilter::Configurable => sys::KeyFilter::configurable, KeyFilter::SkipStrings => sys::KeyFilter::skip_strings, KeyFilter::SkipSymbols => sys::KeyFilter::skip_symbols, } } } #[cfg(feature = "napi6")] pub enum KeyConversion { KeepNumbers, NumbersToStrings, } #[cfg(feature = "napi6")] impl TryFrom for KeyConversion { type Error = Error; fn try_from(value: sys::napi_key_conversion) -> Result { match value { sys::KeyConversion::keep_numbers => Ok(Self::KeepNumbers), sys::KeyConversion::numbers_to_strings => Ok(Self::NumbersToStrings), _ => Err(Error::new( crate::Status::InvalidArg, format!("Invalid key conversion [{}]", value), )), } } } #[cfg(feature = "napi6")] impl From for sys::napi_key_conversion { fn from(value: KeyConversion) -> Self { match value { KeyConversion::KeepNumbers => sys::KeyConversion::keep_numbers, KeyConversion::NumbersToStrings => sys::KeyConversion::numbers_to_strings, } } }