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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}