diff --git a/napi/src/env.rs b/napi/src/env.rs index 7a270583..26ffac17 100644 --- a/napi/src/env.rs +++ b/napi/src/env.rs @@ -494,10 +494,10 @@ impl Env { result } - pub fn get_global(&self) -> Result { + pub fn get_global(&self) -> Result { let mut raw_global = ptr::null_mut(); check_status(unsafe { sys::napi_get_global(self.0, &mut raw_global) })?; - Ok(JsObject::from_raw_unchecked(self.0, raw_global)) + Ok(JsGlobal::from_raw_unchecked(self.0, raw_global)) } pub fn get_napi_version(&self) -> Result { diff --git a/napi/src/js_values/arraybuffer.rs b/napi/src/js_values/arraybuffer.rs index 0e257696..c49a807f 100644 --- a/napi/src/js_values/arraybuffer.rs +++ b/napi/src/js_values/arraybuffer.rs @@ -4,7 +4,7 @@ use std::ptr; use super::Value; use crate::error::check_status; -use crate::{sys, JsUnknown, Ref, Result}; +use crate::{sys, JsUnknown, NapiValue, Ref, Result}; #[repr(transparent)] #[derive(Debug, Clone, Copy)] @@ -49,8 +49,8 @@ impl JsArrayBufferValue { self.value } - pub fn into_unknown(self) -> Result { - self.value.into_unknown() + pub fn into_unknown(self) -> JsUnknown { + JsUnknown::from_raw_unchecked(self.value.0.env, self.value.0.value) } } diff --git a/napi/src/js_values/buffer.rs b/napi/src/js_values/buffer.rs index 110d6ba6..b0eac81d 100644 --- a/napi/src/js_values/buffer.rs +++ b/napi/src/js_values/buffer.rs @@ -6,7 +6,7 @@ use super::Value; #[cfg(feature = "serde-json")] use super::ValueType; use crate::error::check_status; -use crate::{sys, JsUnknown, Ref, Result}; +use crate::{sys, JsUnknown, NapiValue, Ref, Result}; #[repr(transparent)] #[derive(Debug, Clone, Copy)] @@ -68,8 +68,8 @@ impl JsBufferValue { self.value } - pub fn into_unknown(self) -> Result { - self.value.into_unknown() + pub fn into_unknown(self) -> JsUnknown { + JsUnknown::from_raw_unchecked(self.value.0.env, self.value.0.value) } } diff --git a/napi/src/js_values/function.rs b/napi/src/js_values/function.rs index 66b35884..6d456260 100644 --- a/napi/src/js_values/function.rs +++ b/napi/src/js_values/function.rs @@ -1,4 +1,3 @@ -use std::mem; use std::ptr; use super::Value; @@ -38,10 +37,10 @@ impl JsFunction { Status::Unknown, "Get raw this failed".to_owned(), ))?; - let mut raw_args = unsafe { mem::MaybeUninit::<[sys::napi_value; 8]>::uninit().assume_init() }; - for (i, arg) in args.into_iter().enumerate() { - raw_args[i] = arg.0.value; - } + let raw_args = args + .iter() + .map(|arg| arg.0.value) + .collect::>(); let mut return_value = ptr::null_mut(); check_status(unsafe { sys::napi_call_function( @@ -49,7 +48,7 @@ impl JsFunction { raw_this, self.0.value, args.len() as u64, - &raw_args[0], + raw_args.as_ptr(), &mut return_value, ) })?; diff --git a/napi/src/js_values/global.rs b/napi/src/js_values/global.rs new file mode 100644 index 00000000..0d1f880b --- /dev/null +++ b/napi/src/js_values/global.rs @@ -0,0 +1,29 @@ +use std::convert::TryInto; + +use super::*; +use crate::Env; + +#[repr(transparent)] +#[derive(Debug)] +pub struct JsGlobal(pub(crate) Value); + +#[repr(transparent)] +#[derive(Debug)] +pub struct JsTimeout(pub(crate) Value); + +impl JsGlobal { + pub fn set_interval(&self, handler: JsFunction, interval: f64) -> Result { + let func: JsFunction = self.get_named_property("setInterval")?; + func + .call( + None, + &[ + handler.into_unknown(), + Env::from_raw(self.0.env) + .create_double(interval)? + .into_unknown(), + ], + ) + .and_then(|ret| ret.try_into()) + } +} diff --git a/napi/src/js_values/mod.rs b/napi/src/js_values/mod.rs index 5075f4ae..1eb7f065 100644 --- a/napi/src/js_values/mod.rs +++ b/napi/src/js_values/mod.rs @@ -1,4 +1,5 @@ use std::convert::{From, TryFrom}; +use std::ffi::CString; use std::ptr; use crate::error::check_status; @@ -17,6 +18,7 @@ mod buffer; mod either; mod escapable_handle_scope; mod function; +mod global; mod number; mod object; mod object_property; @@ -37,6 +39,7 @@ pub(crate) use de::De; pub use either::Either; pub use escapable_handle_scope::EscapableHandleScope; pub use function::JsFunction; +pub use global::*; pub use number::JsNumber; pub use object::JsObject; pub use object_property::Property; @@ -120,8 +123,8 @@ macro_rules! impl_js_value_methods { ($js_value:ident) => { impl $js_value { #[inline] - pub fn into_unknown(self) -> Result { - JsUnknown::from_raw(self.0.env, self.0.value) + pub fn into_unknown(self) -> JsUnknown { + JsUnknown::from_raw_unchecked(self.0.env, self.0.value) } #[inline] @@ -219,6 +222,206 @@ macro_rules! impl_js_value_methods { }; } +macro_rules! impl_object_methods { + ($js_value:ident) => { + impl $js_value { + pub fn set_property(&mut self, key: JsString, value: V) -> Result<()> + where + V: NapiValue, + { + check_status(unsafe { + sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw()) + }) + } + pub fn get_property(&self, key: &K) -> Result + where + K: NapiValue, + T: NapiValue, + { + let mut raw_value = ptr::null_mut(); + check_status(unsafe { + sys::napi_get_property(self.0.env, self.0.value, key.raw(), &mut raw_value) + })?; + T::from_raw(self.0.env, raw_value) + } + pub fn set_named_property(&mut self, name: &str, value: T) -> Result<()> + where + T: NapiValue, + { + let key = CString::new(name)?; + check_status(unsafe { + sys::napi_set_named_property(self.0.env, self.0.value, key.as_ptr(), value.raw()) + }) + } + pub fn get_named_property(&self, name: &str) -> Result + where + T: NapiValue, + { + let key = CString::new(name)?; + let mut raw_value = ptr::null_mut(); + check_status(unsafe { + sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) + })?; + T::from_raw(self.0.env, raw_value) + } + pub fn has_named_property(&self, name: S) -> Result + where + S: AsRef, + { + let mut result = false; + let key = CString::new(name.as_ref())?; + check_status(unsafe { + sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) + })?; + Ok(result) + } + pub fn delete_property(&mut self, name: S) -> Result + where + S: NapiValue, + { + let mut result = false; + check_status(unsafe { + sys::napi_delete_property(self.0.env, self.0.value, name.raw(), &mut result) + })?; + Ok(result) + } + pub fn delete_named_property(&mut self, name: &str) -> Result { + let mut result = false; + let key_str = CString::new(name)?; + let mut js_key = ptr::null_mut(); + check_status(unsafe { + sys::napi_create_string_utf8(self.0.env, key_str.as_ptr(), name.len() as _, &mut js_key) + })?; + check_status(unsafe { + sys::napi_delete_property(self.0.env, self.0.value, js_key, &mut result) + })?; + Ok(result) + } + pub fn has_own_property(&self, key: &str) -> Result { + let mut result = false; + let string = CString::new(key)?; + let mut js_key = ptr::null_mut(); + check_status(unsafe { + sys::napi_create_string_utf8(self.0.env, string.as_ptr(), key.len() as _, &mut js_key) + })?; + check_status(unsafe { + sys::napi_has_own_property(self.0.env, self.0.value, js_key, &mut result) + })?; + Ok(result) + } + pub fn has_own_property_js(&self, key: K) -> Result + where + K: NapiValue, + { + let mut result = false; + check_status(unsafe { + sys::napi_has_own_property(self.0.env, self.0.value, key.raw(), &mut result) + })?; + Ok(result) + } + pub fn has_property(&self, name: &str) -> Result { + let string = CString::new(name)?; + let mut js_key = ptr::null_mut(); + let mut result = false; + check_status(unsafe { + sys::napi_create_string_utf8(self.0.env, string.as_ptr(), name.len() as _, &mut js_key) + })?; + check_status(unsafe { + sys::napi_has_property(self.0.env, self.0.value, js_key, &mut result) + })?; + Ok(result) + } + pub fn has_property_js(&self, name: K) -> Result + where + K: NapiValue, + { + let mut result = false; + check_status(unsafe { + sys::napi_has_property(self.0.env, self.0.value, name.raw(), &mut result) + })?; + Ok(result) + } + pub fn get_property_names(&self) -> Result + where + T: NapiValue, + { + let mut raw_value = ptr::null_mut(); + let status = + unsafe { sys::napi_get_property_names(self.0.env, self.0.value, &mut raw_value) }; + check_status(status)?; + T::from_raw(self.0.env, raw_value) + } + pub fn get_prototype(&self) -> Result + where + T: NapiValue, + { + let mut result = ptr::null_mut(); + check_status(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?; + T::from_raw(self.0.env, result) + } + pub fn set_element(&mut self, index: u32, value: T) -> Result<()> + where + T: NapiValue, + { + check_status(unsafe { sys::napi_set_element(self.0.env, self.0.value, index, value.raw()) }) + } + pub fn has_element(&self, index: u32) -> Result { + let mut result = false; + check_status(unsafe { + sys::napi_has_element(self.0.env, self.0.value, index, &mut result) + })?; + Ok(result) + } + pub fn delete_element(&mut self, index: u32) -> Result { + let mut result = false; + check_status(unsafe { + sys::napi_delete_element(self.0.env, self.0.value, index, &mut result) + })?; + Ok(result) + } + pub fn get_element(&self, index: u32) -> Result + where + T: NapiValue, + { + let mut raw_value = ptr::null_mut(); + check_status(unsafe { + sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) + })?; + T::from_raw(self.0.env, raw_value) + } + pub fn define_properties(&mut self, properties: &[Property]) -> Result<()> { + check_status(unsafe { + sys::napi_define_properties( + self.0.env, + self.0.value, + properties.len() as _, + properties + .iter() + .map(|property| property.raw()) + .collect::>() + .as_ptr(), + ) + }) + } + pub fn get_array_length(&self) -> Result { + if self.is_array()? != true { + return Err(Error::new( + Status::ArrayExpected, + "Object is not array".to_owned(), + )); + } + self.get_array_length_unchecked() + } + #[inline] + pub fn get_array_length_unchecked(&self) -> Result { + let mut length: u32 = 0; + check_status(unsafe { sys::napi_get_array_length(self.0.env, self.raw(), &mut length) })?; + Ok(length) + } + } + }; +} + pub trait NapiValue: Sized { fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result; @@ -236,9 +439,16 @@ impl_js_value_methods!(JsBuffer); impl_js_value_methods!(JsNumber); impl_js_value_methods!(JsString); impl_js_value_methods!(JsObject); +impl_js_value_methods!(JsGlobal); impl_js_value_methods!(JsFunction); impl_js_value_methods!(JsExternal); impl_js_value_methods!(JsSymbol); +impl_js_value_methods!(JsTimeout); + +impl_object_methods!(JsObject); +impl_object_methods!(JsBuffer); +impl_object_methods!(JsArrayBuffer); +impl_object_methods!(JsGlobal); use ValueType::*; @@ -250,6 +460,8 @@ impl_napi_value_trait!(JsArrayBuffer, Object); impl_napi_value_trait!(JsNumber, Number); impl_napi_value_trait!(JsString, String); impl_napi_value_trait!(JsObject, Object); +impl_napi_value_trait!(JsGlobal, Object); +impl_napi_value_trait!(JsTimeout, Object); impl_napi_value_trait!(JsFunction, Function); impl_napi_value_trait!(JsExternal, External); impl_napi_value_trait!(JsSymbol, Symbol); diff --git a/napi/src/js_values/object.rs b/napi/src/js_values/object.rs index 0a248f0a..319b45ac 100644 --- a/napi/src/js_values/object.rs +++ b/napi/src/js_values/object.rs @@ -1,220 +1,5 @@ -use std::ffi::CString; -use std::ptr; - use super::Value; -use crate::error::check_status; -use crate::{sys, Error, JsString, NapiValue, Property, Result, Status}; #[repr(transparent)] #[derive(Debug)] pub struct JsObject(pub(crate) Value); - -impl JsObject { - pub fn set_property(&mut self, key: JsString, value: V) -> Result<()> - where - V: NapiValue, - { - check_status(unsafe { - sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw()) - }) - } - - pub fn get_property(&self, key: &K) -> Result - where - K: NapiValue, - T: NapiValue, - { - let mut raw_value = ptr::null_mut(); - check_status(unsafe { - sys::napi_get_property(self.0.env, self.0.value, key.raw(), &mut raw_value) - })?; - T::from_raw(self.0.env, raw_value) - } - - pub fn set_named_property(&mut self, name: &str, value: T) -> Result<()> - where - T: NapiValue, - { - let key = CString::new(name)?; - check_status(unsafe { - sys::napi_set_named_property(self.0.env, self.0.value, key.as_ptr(), value.raw()) - }) - } - - pub fn get_named_property(&self, name: &str) -> Result - where - T: NapiValue, - { - let key = CString::new(name)?; - let mut raw_value = ptr::null_mut(); - check_status(unsafe { - sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) - })?; - T::from_raw(self.0.env, raw_value) - } - - pub fn has_named_property(&self, name: S) -> Result - where - S: AsRef, - { - let mut result = false; - let key = CString::new(name.as_ref())?; - check_status(unsafe { - sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) - })?; - Ok(result) - } - - pub fn delete_property(&mut self, name: S) -> Result - where - S: NapiValue, - { - let mut result = false; - check_status(unsafe { - sys::napi_delete_property(self.0.env, self.0.value, name.raw(), &mut result) - })?; - Ok(result) - } - - pub fn delete_named_property(&mut self, name: &str) -> Result { - let mut result = false; - let key_str = CString::new(name)?; - let mut js_key = ptr::null_mut(); - check_status(unsafe { - sys::napi_create_string_utf8(self.0.env, key_str.as_ptr(), name.len() as _, &mut js_key) - })?; - check_status(unsafe { - sys::napi_delete_property(self.0.env, self.0.value, js_key, &mut result) - })?; - Ok(result) - } - - pub fn has_own_property(&self, key: &str) -> Result { - let mut result = false; - let string = CString::new(key)?; - let mut js_key = ptr::null_mut(); - check_status(unsafe { - sys::napi_create_string_utf8(self.0.env, string.as_ptr(), key.len() as _, &mut js_key) - })?; - check_status(unsafe { - sys::napi_has_own_property(self.0.env, self.0.value, js_key, &mut result) - })?; - Ok(result) - } - - pub fn has_own_property_js(&self, key: K) -> Result - where - K: NapiValue, - { - let mut result = false; - check_status(unsafe { - sys::napi_has_own_property(self.0.env, self.0.value, key.raw(), &mut result) - })?; - Ok(result) - } - - pub fn has_property(&self, name: &str) -> Result { - let string = CString::new(name)?; - let mut js_key = ptr::null_mut(); - let mut result = false; - check_status(unsafe { - sys::napi_create_string_utf8(self.0.env, string.as_ptr(), name.len() as _, &mut js_key) - })?; - check_status(unsafe { sys::napi_has_property(self.0.env, self.0.value, js_key, &mut result) })?; - Ok(result) - } - - pub fn has_property_js(&self, name: K) -> Result - where - K: NapiValue, - { - let mut result = false; - check_status(unsafe { - sys::napi_has_property(self.0.env, self.0.value, name.raw(), &mut result) - })?; - Ok(result) - } - - pub fn get_property_names(&self) -> Result - where - T: NapiValue, - { - let mut raw_value = ptr::null_mut(); - let status = unsafe { sys::napi_get_property_names(self.0.env, self.0.value, &mut raw_value) }; - check_status(status)?; - T::from_raw(self.0.env, raw_value) - } - - pub fn get_prototype(&self) -> Result - where - T: NapiValue, - { - let mut result = ptr::null_mut(); - check_status(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?; - T::from_raw(self.0.env, result) - } - - pub fn set_element(&mut self, index: u32, value: T) -> Result<()> - where - T: NapiValue, - { - check_status(unsafe { sys::napi_set_element(self.0.env, self.0.value, index, value.raw()) }) - } - - pub fn has_element(&self, index: u32) -> Result { - let mut result = false; - check_status(unsafe { sys::napi_has_element(self.0.env, self.0.value, index, &mut result) })?; - Ok(result) - } - - pub fn delete_element(&mut self, index: u32) -> Result { - let mut result = false; - check_status(unsafe { - sys::napi_delete_element(self.0.env, self.0.value, index, &mut result) - })?; - Ok(result) - } - - pub fn get_element(&self, index: u32) -> Result - where - T: NapiValue, - { - let mut raw_value = ptr::null_mut(); - check_status(unsafe { - sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) - })?; - T::from_raw(self.0.env, raw_value) - } - - pub fn define_properties(&mut self, properties: &[Property]) -> Result<()> { - check_status(unsafe { - sys::napi_define_properties( - self.0.env, - self.0.value, - properties.len() as _, - properties - .iter() - .map(|property| property.raw()) - .collect::>() - .as_ptr(), - ) - }) - } - - pub fn get_array_length(&self) -> Result { - if self.is_array()? != true { - return Err(Error::new( - Status::ArrayExpected, - "Object is not array".to_owned(), - )); - } - self.get_array_length_unchecked() - } - - #[inline] - pub fn get_array_length_unchecked(&self) -> Result { - let mut length: u32 = 0; - check_status(unsafe { sys::napi_get_array_length(self.0.env, self.raw(), &mut length) })?; - Ok(length) - } -}