nodex_api/value/
object.rs

1use crate::{api, prelude::*};
2use std::{ffi::CString, mem::MaybeUninit, os::raw::c_char};
3
4#[derive(Copy, Clone, Debug)]
5pub struct JsObject(pub(crate) JsValue);
6
7impl JsObject {
8    pub(crate) fn from_value(value: JsValue) -> JsObject {
9        JsObject(value)
10    }
11
12    pub fn new(env: NapiEnv) -> NapiResult<JsObject> {
13        let value = napi_call!(=napi_create_object, env);
14        Ok(JsObject(JsValue::from_raw(env, value)))
15    }
16
17    /// This method is equivalent to calling napi_get_property with a napi_value created from the
18    /// string passed in as utf8Name.
19    pub fn set_named_property(
20        &mut self,
21        key: impl AsRef<str>,
22        value: impl NapiValueT,
23    ) -> NapiResult<()> {
24        let name = CString::new(key.as_ref()).map_err(|_| NapiStatus::StringExpected)?;
25        napi_call!(
26            napi_set_named_property,
27            self.env(),
28            self.raw(),
29            name.as_ptr(),
30            value.raw(),
31        )
32    }
33
34    /// This API returns the names of the enumerable properties of object as an array of strings.
35    /// The properties of object whose key is a symbol will not be included.
36    pub fn get_property_names(&self) -> NapiResult<JsArray> {
37        let names = napi_call!(=napi_get_property_names, self.env(), self.raw());
38        Ok(JsArray::from_raw(self.env(), names))
39    }
40
41    #[cfg(feature = "v6")]
42    /// This API returns an array containing the names of the available properties of this object.
43    pub fn get_all_property_names(
44        &self,
45        mode: NapiKeyCollectionMode,
46        filter: NapiKeyFilter,
47        conversion: NapiKeyConversion,
48    ) -> NapiResult<JsArray> {
49        let names = napi_call!(
50            =napi_get_all_property_names,
51            self.env(),
52            self.raw(),
53            mode as _,
54            filter,
55            conversion as _,
56        );
57        Ok(JsArray::from_raw(self.env(), names))
58    }
59
60    /// Set value by string-like key.
61    pub fn set<T: NapiValueT>(&mut self, key: impl AsRef<str>, value: T) -> NapiResult<()> {
62        let name = self.env().string(key.as_ref())?;
63        self.set_property(name, value)?;
64        Ok(())
65    }
66
67    /// This API set a property on the Object passed in.
68    pub fn set_property(&mut self, key: impl NapiValueT, value: impl NapiValueT) -> NapiResult<()> {
69        napi_call!(
70            napi_set_property,
71            self.env(),
72            self.raw(),
73            key.raw(),
74            value.raw(),
75        )
76    }
77
78    /// This API gets the requested property from the Object passed in.
79    pub fn get_property(&self, key: impl NapiValueT) -> NapiResult<JsValue> {
80        let value = napi_call!(=napi_get_property, self.env(), self.raw(), key.raw());
81        Ok(JsValue::from_raw(self.env(), value))
82    }
83
84    /// Get value by string-like key.
85    ///
86    /// # Safety
87    ///
88    /// This function *just* put napi handle in struct `T` without any check. It is your duty to
89    /// make sure the origin value is really type of `T`.
90    pub unsafe fn get_unchecked<T: NapiValueT>(&self, key: impl AsRef<str>) -> NapiResult<T> {
91        let name = self.env().string(key.as_ref())?;
92        Ok(self.get_property(name)?.cast::<T>())
93    }
94
95    /// Get value by string-like key.
96    pub fn get<T: NapiValueT>(&self, key: impl AsRef<str>) -> NapiResult<T> {
97        let name = self.env().string(key.as_ref())?;
98        self.get_property(name)?.cast_checked::<T>()
99    }
100
101    /// This API checks if the Object passed in has the named property.
102    pub fn has_property(&self, key: impl NapiValueT) -> NapiResult<bool> {
103        Ok(napi_call!(=napi_has_property, self.env(), self.raw(), key.raw()))
104    }
105
106    /// This API attempts to delete the key own property from object.
107    pub fn delete_property(&self, key: impl NapiValueT) -> NapiResult<bool> {
108        Ok(napi_call!(=napi_delete_property, self.env(), self.raw(), key.raw()))
109    }
110
111    /// This API checks if the Object passed in has the named own property. key must be a string or
112    /// a symbol, or an error will be thrown. Node-API will not perform any conversion between data
113    /// types.
114    pub fn has_own_property(
115        &mut self,
116        key: impl NapiValueT,
117        value: impl NapiValueT,
118    ) -> NapiResult<bool> {
119        Ok(napi_call!(
120            =napi_has_own_property,
121            self.env(),
122            self.raw(),
123            key.raw(),
124        ))
125    }
126
127    /// This method is equivalent to calling napi_get_property with a napi_value created
128    /// from the string passed in as utf8Name.
129    pub fn get_named_property(&self, key: impl AsRef<str>) -> NapiResult<JsValue> {
130        let name = napi_s!(key.as_ref())?;
131        let value = napi_call!(
132            =napi_get_named_property,
133            self.env(),
134            self.raw(),
135            name.as_ptr(),
136        );
137        Ok(JsValue::from_raw(self.env(), value))
138    }
139
140    /// This method is equivalent to calling napi_has_property with a napi_value created from the
141    /// string passed in as utf8Name.
142    pub fn has_named_property(&self, key: impl AsRef<str>) -> NapiResult<bool> {
143        let name = napi_s!(key.as_ref())?;
144        Ok(napi_call!(
145            =napi_has_named_property,
146            self.env(),
147            self.raw(),
148            name.as_ptr(),
149        ))
150    }
151
152    /// This API sets an element on the Object passed in.
153    pub fn set_element(&mut self, index: u32, value: impl NapiValueT) -> NapiResult<()> {
154        napi_call!(napi_set_element, self.env(), self.raw(), index, value.raw())
155    }
156
157    /// This API gets the element at the requested index.
158    pub fn get_element(&mut self, index: u32) -> NapiResult<JsValue> {
159        let result = napi_call!(
160            =napi_get_element,
161            self.env(),
162            self.raw(),
163            index,
164        );
165
166        Ok(JsValue::from_raw(self.env(), result))
167    }
168
169    /// This API returns if the Object passed in has an element at the requested index.
170    pub fn has_element(&mut self, index: u32) -> NapiResult<bool> {
171        Ok(napi_call!(
172            =napi_has_element,
173            self.env(),
174            self.raw(),
175            index,
176        ))
177    }
178
179    /// This API attempts to delete the specified index from object.
180    pub fn delete_element(&mut self, index: u32) -> NapiResult<bool> {
181        Ok(napi_call!(
182            =napi_delete_element,
183            self.env(),
184            self.raw(),
185            index,
186        ))
187    }
188
189    #[cfg(feature = "v8")]
190    #[doc = "Object.freeze()"]
191    pub fn freeze(&mut self) -> NapiResult<()> {
192        napi_call!(napi_object_freeze, self.env(), self.raw())
193    }
194
195    #[cfg(feature = "v8")]
196    #[doc = "Object.seal()"]
197    pub fn seal(&mut self) -> NapiResult<()> {
198        napi_call!(napi_object_seal, self.env(), self.raw())
199    }
200}
201
202napi_value_t!(JsObject);
203
204impl NapiValueCheck for JsObject {
205    fn check(&self) -> NapiResult<bool> {
206        Ok(self.kind()? == NapiValuetype::Object)
207    }
208}