1 | use std::convert::TryFrom; |
2 | #[cfg (feature = "napi5" )] |
3 | use std::ffi::c_void; |
4 | use std::ffi::CString; |
5 | use std::ptr; |
6 | |
7 | use crate::{ |
8 | bindgen_runtime::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}, |
9 | check_status, sys, type_of, Callback, Error, Result, Status, ValueType, |
10 | }; |
11 | |
12 | #[cfg (feature = "serde-json" )] |
13 | mod de; |
14 | #[cfg (feature = "serde-json" )] |
15 | mod ser; |
16 | |
17 | mod arraybuffer; |
18 | #[cfg (feature = "napi6" )] |
19 | mod bigint; |
20 | mod boolean; |
21 | mod buffer; |
22 | #[cfg (feature = "napi5" )] |
23 | mod date; |
24 | #[cfg (feature = "napi4" )] |
25 | mod deferred; |
26 | mod either; |
27 | mod escapable_handle_scope; |
28 | mod function; |
29 | mod global; |
30 | mod number; |
31 | mod object; |
32 | mod object_property; |
33 | mod string; |
34 | mod tagged_object; |
35 | mod undefined; |
36 | mod value; |
37 | mod value_ref; |
38 | |
39 | pub use arraybuffer::*; |
40 | #[cfg (feature = "napi6" )] |
41 | pub use bigint::JsBigInt; |
42 | pub use boolean::JsBoolean; |
43 | pub use buffer::*; |
44 | #[cfg (feature = "napi5" )] |
45 | pub use date::*; |
46 | #[cfg (feature = "serde-json" )] |
47 | pub(crate) use de::De; |
48 | #[cfg (feature = "napi4" )] |
49 | pub use deferred::*; |
50 | pub use either::Either; |
51 | pub use escapable_handle_scope::EscapableHandleScope; |
52 | pub use function::JsFunction; |
53 | pub use global::*; |
54 | pub use number::JsNumber; |
55 | pub use object::*; |
56 | pub use object_property::*; |
57 | #[cfg (feature = "serde-json" )] |
58 | pub(crate) use ser::Ser; |
59 | pub use string::*; |
60 | pub(crate) use tagged_object::TaggedObject; |
61 | pub use undefined::JsUndefined; |
62 | pub(crate) use value::Value; |
63 | pub use value_ref::*; |
64 | |
65 | // Value types |
66 | |
67 | pub struct JsUnknown(pub(crate) Value); |
68 | |
69 | #[derive (Clone, Copy)] |
70 | pub struct JsNull(pub(crate) Value); |
71 | |
72 | impl TypeName for JsNull { |
73 | fn type_name() -> &'static str { |
74 | "null" |
75 | } |
76 | |
77 | fn value_type() -> ValueType { |
78 | ValueType::Null |
79 | } |
80 | } |
81 | |
82 | impl ValidateNapiValue for JsNull {} |
83 | |
84 | #[derive (Clone, Copy)] |
85 | pub struct JsSymbol(pub(crate) Value); |
86 | |
87 | impl TypeName for JsSymbol { |
88 | fn type_name() -> &'static str { |
89 | "symbol" |
90 | } |
91 | |
92 | fn value_type() -> ValueType { |
93 | ValueType::Symbol |
94 | } |
95 | } |
96 | |
97 | impl ValidateNapiValue for JsSymbol {} |
98 | |
99 | pub struct JsExternal(pub(crate) Value); |
100 | |
101 | impl TypeName for JsExternal { |
102 | fn type_name() -> &'static str { |
103 | "external" |
104 | } |
105 | |
106 | fn value_type() -> ValueType { |
107 | ValueType::External |
108 | } |
109 | } |
110 | |
111 | impl ValidateNapiValue for JsExternal {} |
112 | |
113 | macro_rules! impl_napi_value_trait { |
114 | ($js_value:ident, $value_type:ident) => { |
115 | impl NapiValue for $js_value { |
116 | unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<$js_value> { |
117 | let value_type = type_of!(env, value)?; |
118 | if value_type != $value_type { |
119 | Err(Error::new( |
120 | Status::InvalidArg, |
121 | format!("expect {:?}, got: {:?}" , $value_type, value_type), |
122 | )) |
123 | } else { |
124 | Ok($js_value(Value { |
125 | env, |
126 | value, |
127 | value_type: $value_type, |
128 | })) |
129 | } |
130 | } |
131 | |
132 | unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> $js_value { |
133 | $js_value(Value { |
134 | env, |
135 | value, |
136 | value_type: $value_type, |
137 | }) |
138 | } |
139 | } |
140 | |
141 | impl NapiRaw for $js_value { |
142 | unsafe fn raw(&self) -> sys::napi_value { |
143 | self.0.value |
144 | } |
145 | } |
146 | |
147 | impl<'env> NapiRaw for &'env $js_value { |
148 | unsafe fn raw(&self) -> sys::napi_value { |
149 | self.0.value |
150 | } |
151 | } |
152 | |
153 | impl TryFrom<JsUnknown> for $js_value { |
154 | type Error = Error; |
155 | fn try_from(value: JsUnknown) -> Result<$js_value> { |
156 | unsafe { $js_value::from_raw(value.0.env, value.0.value) } |
157 | } |
158 | } |
159 | }; |
160 | } |
161 | |
162 | macro_rules! impl_js_value_methods { |
163 | ($js_value:ident) => { |
164 | impl $js_value { |
165 | pub fn into_unknown(self) -> JsUnknown { |
166 | unsafe { JsUnknown::from_raw_unchecked(self.0.env, self.0.value) } |
167 | } |
168 | |
169 | pub fn coerce_to_bool(self) -> Result<JsBoolean> { |
170 | let mut new_raw_value = ptr::null_mut(); |
171 | check_status!(unsafe { |
172 | sys::napi_coerce_to_bool(self.0.env, self.0.value, &mut new_raw_value) |
173 | })?; |
174 | Ok(JsBoolean(Value { |
175 | env: self.0.env, |
176 | value: new_raw_value, |
177 | value_type: ValueType::Boolean, |
178 | })) |
179 | } |
180 | |
181 | pub fn coerce_to_number(self) -> Result<JsNumber> { |
182 | let mut new_raw_value = ptr::null_mut(); |
183 | check_status!(unsafe { |
184 | sys::napi_coerce_to_number(self.0.env, self.0.value, &mut new_raw_value) |
185 | })?; |
186 | Ok(JsNumber(Value { |
187 | env: self.0.env, |
188 | value: new_raw_value, |
189 | value_type: ValueType::Number, |
190 | })) |
191 | } |
192 | |
193 | pub fn coerce_to_string(self) -> Result<JsString> { |
194 | let mut new_raw_value = ptr::null_mut(); |
195 | check_status!(unsafe { |
196 | sys::napi_coerce_to_string(self.0.env, self.0.value, &mut new_raw_value) |
197 | })?; |
198 | Ok(JsString(Value { |
199 | env: self.0.env, |
200 | value: new_raw_value, |
201 | value_type: ValueType::String, |
202 | })) |
203 | } |
204 | |
205 | pub fn coerce_to_object(self) -> Result<JsObject> { |
206 | let mut new_raw_value = ptr::null_mut(); |
207 | check_status!(unsafe { |
208 | sys::napi_coerce_to_object(self.0.env, self.0.value, &mut new_raw_value) |
209 | })?; |
210 | Ok(JsObject(Value { |
211 | env: self.0.env, |
212 | value: new_raw_value, |
213 | value_type: ValueType::Object, |
214 | })) |
215 | } |
216 | |
217 | #[cfg(feature = "napi5" )] |
218 | pub fn is_date(&self) -> Result<bool> { |
219 | let mut is_date = true; |
220 | check_status!(unsafe { sys::napi_is_date(self.0.env, self.0.value, &mut is_date) })?; |
221 | Ok(is_date) |
222 | } |
223 | |
224 | pub fn is_promise(&self) -> Result<bool> { |
225 | let mut is_promise = true; |
226 | check_status!(unsafe { sys::napi_is_promise(self.0.env, self.0.value, &mut is_promise) })?; |
227 | Ok(is_promise) |
228 | } |
229 | |
230 | pub fn is_error(&self) -> Result<bool> { |
231 | let mut result = false; |
232 | check_status!(unsafe { sys::napi_is_error(self.0.env, self.0.value, &mut result) })?; |
233 | Ok(result) |
234 | } |
235 | |
236 | pub fn is_typedarray(&self) -> Result<bool> { |
237 | let mut result = false; |
238 | check_status!(unsafe { sys::napi_is_typedarray(self.0.env, self.0.value, &mut result) })?; |
239 | Ok(result) |
240 | } |
241 | |
242 | pub fn is_dataview(&self) -> Result<bool> { |
243 | let mut result = false; |
244 | check_status!(unsafe { sys::napi_is_dataview(self.0.env, self.0.value, &mut result) })?; |
245 | Ok(result) |
246 | } |
247 | |
248 | pub fn is_array(&self) -> Result<bool> { |
249 | let mut is_array = false; |
250 | check_status!(unsafe { sys::napi_is_array(self.0.env, self.0.value, &mut is_array) })?; |
251 | Ok(is_array) |
252 | } |
253 | |
254 | pub fn is_buffer(&self) -> Result<bool> { |
255 | let mut is_buffer = false; |
256 | check_status!(unsafe { sys::napi_is_buffer(self.0.env, self.0.value, &mut is_buffer) })?; |
257 | Ok(is_buffer) |
258 | } |
259 | |
260 | pub fn instanceof<Constructor>(&self, constructor: Constructor) -> Result<bool> |
261 | where |
262 | Constructor: NapiRaw, |
263 | { |
264 | let mut result = false; |
265 | check_status!(unsafe { |
266 | sys::napi_instanceof(self.0.env, self.0.value, constructor.raw(), &mut result) |
267 | })?; |
268 | Ok(result) |
269 | } |
270 | } |
271 | }; |
272 | } |
273 | |
274 | macro_rules! impl_object_methods { |
275 | ($js_value:ident) => { |
276 | impl $js_value { |
277 | pub fn set_property<K, V>(&mut self, key: K, value: V) -> Result<()> |
278 | where |
279 | K: NapiRaw, |
280 | V: NapiRaw, |
281 | { |
282 | check_status!(unsafe { |
283 | sys::napi_set_property(self.0.env, self.0.value, key.raw(), value.raw()) |
284 | }) |
285 | } |
286 | |
287 | pub fn get_property<K, T>(&self, key: K) -> Result<T> |
288 | where |
289 | K: NapiRaw, |
290 | T: NapiValue, |
291 | { |
292 | let mut raw_value = ptr::null_mut(); |
293 | check_status!(unsafe { |
294 | sys::napi_get_property(self.0.env, self.0.value, key.raw(), &mut raw_value) |
295 | })?; |
296 | unsafe { T::from_raw(self.0.env, raw_value) } |
297 | } |
298 | |
299 | pub fn get_property_unchecked<K, T>(&self, key: K) -> Result<T> |
300 | where |
301 | K: NapiRaw, |
302 | T: NapiValue, |
303 | { |
304 | let mut raw_value = ptr::null_mut(); |
305 | check_status!(unsafe { |
306 | sys::napi_get_property(self.0.env, self.0.value, key.raw(), &mut raw_value) |
307 | })?; |
308 | Ok(unsafe { T::from_raw_unchecked(self.0.env, raw_value) }) |
309 | } |
310 | |
311 | pub fn set_named_property<T>(&mut self, name: &str, value: T) -> Result<()> |
312 | where |
313 | T: ToNapiValue, |
314 | { |
315 | let key = CString::new(name)?; |
316 | check_status!(unsafe { |
317 | sys::napi_set_named_property( |
318 | self.0.env, |
319 | self.0.value, |
320 | key.as_ptr(), |
321 | T::to_napi_value(self.0.env, value)?, |
322 | ) |
323 | }) |
324 | } |
325 | |
326 | pub fn create_named_method(&mut self, name: &str, function: Callback) -> Result<()> { |
327 | let mut js_function = ptr::null_mut(); |
328 | let len = name.len(); |
329 | let name = CString::new(name)?; |
330 | check_status!(unsafe { |
331 | sys::napi_create_function( |
332 | self.0.env, |
333 | name.as_ptr(), |
334 | len, |
335 | Some(function), |
336 | ptr::null_mut(), |
337 | &mut js_function, |
338 | ) |
339 | })?; |
340 | check_status!( |
341 | unsafe { |
342 | sys::napi_set_named_property(self.0.env, self.0.value, name.as_ptr(), js_function) |
343 | }, |
344 | "create_named_method error" |
345 | ) |
346 | } |
347 | |
348 | pub fn get_named_property<T>(&self, name: &str) -> Result<T> |
349 | where |
350 | T: FromNapiValue + ValidateNapiValue, |
351 | { |
352 | let key = CString::new(name)?; |
353 | let mut raw_value = ptr::null_mut(); |
354 | check_status!( |
355 | unsafe { |
356 | sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) |
357 | }, |
358 | "get_named_property error" |
359 | )?; |
360 | unsafe { <T as ValidateNapiValue>::validate(self.0.env, raw_value) }.map_err( |
361 | |mut err| { |
362 | err.reason = format!("Object property '{name}' type mismatch. {}" , err.reason); |
363 | err |
364 | }, |
365 | )?; |
366 | unsafe { <T as FromNapiValue>::from_napi_value(self.0.env, raw_value) } |
367 | } |
368 | |
369 | pub fn get_named_property_unchecked<T: FromNapiValue>(&self, name: &str) -> Result<T> |
370 | where |
371 | T: FromNapiValue, |
372 | { |
373 | let key = CString::new(name)?; |
374 | let mut raw_value = ptr::null_mut(); |
375 | check_status!( |
376 | unsafe { |
377 | sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) |
378 | }, |
379 | "get_named_property_unchecked error" |
380 | )?; |
381 | unsafe { <T as FromNapiValue>::from_napi_value(self.0.env, raw_value) } |
382 | } |
383 | |
384 | pub fn has_named_property<N: AsRef<str>>(&self, name: N) -> Result<bool> { |
385 | let mut result = false; |
386 | let key = CString::new(name.as_ref())?; |
387 | check_status!( |
388 | unsafe { |
389 | sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) |
390 | }, |
391 | "napi_has_named_property error" |
392 | )?; |
393 | Ok(result) |
394 | } |
395 | |
396 | pub fn delete_property<S>(&mut self, name: S) -> Result<bool> |
397 | where |
398 | S: NapiRaw, |
399 | { |
400 | let mut result = false; |
401 | check_status!(unsafe { |
402 | sys::napi_delete_property(self.0.env, self.0.value, name.raw(), &mut result) |
403 | })?; |
404 | Ok(result) |
405 | } |
406 | |
407 | pub fn delete_named_property(&mut self, name: &str) -> Result<bool> { |
408 | let mut result = false; |
409 | let key_str = CString::new(name)?; |
410 | let mut js_key = ptr::null_mut(); |
411 | check_status!(unsafe { |
412 | sys::napi_create_string_utf8(self.0.env, key_str.as_ptr(), name.len(), &mut js_key) |
413 | })?; |
414 | check_status!(unsafe { |
415 | sys::napi_delete_property(self.0.env, self.0.value, js_key, &mut result) |
416 | })?; |
417 | Ok(result) |
418 | } |
419 | |
420 | pub fn has_own_property(&self, key: &str) -> Result<bool> { |
421 | let mut result = false; |
422 | let string = CString::new(key)?; |
423 | let mut js_key = ptr::null_mut(); |
424 | check_status!(unsafe { |
425 | sys::napi_create_string_utf8(self.0.env, string.as_ptr(), key.len(), &mut js_key) |
426 | })?; |
427 | check_status!(unsafe { |
428 | sys::napi_has_own_property(self.0.env, self.0.value, js_key, &mut result) |
429 | })?; |
430 | Ok(result) |
431 | } |
432 | |
433 | pub fn has_own_property_js<K>(&self, key: K) -> Result<bool> |
434 | where |
435 | K: NapiRaw, |
436 | { |
437 | let mut result = false; |
438 | check_status!(unsafe { |
439 | sys::napi_has_own_property(self.0.env, self.0.value, key.raw(), &mut result) |
440 | })?; |
441 | Ok(result) |
442 | } |
443 | |
444 | pub fn has_property(&self, name: &str) -> Result<bool> { |
445 | let string = CString::new(name)?; |
446 | let mut js_key = ptr::null_mut(); |
447 | let mut result = false; |
448 | check_status!(unsafe { |
449 | sys::napi_create_string_utf8(self.0.env, string.as_ptr(), name.len(), &mut js_key) |
450 | })?; |
451 | check_status!(unsafe { |
452 | sys::napi_has_property(self.0.env, self.0.value, js_key, &mut result) |
453 | })?; |
454 | Ok(result) |
455 | } |
456 | |
457 | pub fn has_property_js<K>(&self, name: K) -> Result<bool> |
458 | where |
459 | K: NapiRaw, |
460 | { |
461 | let mut result = false; |
462 | check_status!(unsafe { |
463 | sys::napi_has_property(self.0.env, self.0.value, name.raw(), &mut result) |
464 | })?; |
465 | Ok(result) |
466 | } |
467 | |
468 | pub fn get_property_names(&self) -> Result<JsObject> { |
469 | let mut raw_value = ptr::null_mut(); |
470 | check_status!(unsafe { |
471 | sys::napi_get_property_names(self.0.env, self.0.value, &mut raw_value) |
472 | })?; |
473 | Ok(unsafe { JsObject::from_raw_unchecked(self.0.env, raw_value) }) |
474 | } |
475 | |
476 | /// <https://nodejs.org/api/n-api.html#n_api_napi_get_all_property_names> |
477 | /// return `Array` of property names |
478 | #[cfg(feature = "napi6" )] |
479 | pub fn get_all_property_names( |
480 | &self, |
481 | mode: KeyCollectionMode, |
482 | filter: KeyFilter, |
483 | conversion: KeyConversion, |
484 | ) -> Result<JsObject> { |
485 | let mut properties_value = ptr::null_mut(); |
486 | check_status!(unsafe { |
487 | sys::napi_get_all_property_names( |
488 | self.0.env, |
489 | self.0.value, |
490 | mode.into(), |
491 | filter.into(), |
492 | conversion.into(), |
493 | &mut properties_value, |
494 | ) |
495 | })?; |
496 | Ok(unsafe { JsObject::from_raw_unchecked(self.0.env, properties_value) }) |
497 | } |
498 | |
499 | /// This returns the equivalent of `Object.getPrototypeOf` (which is not the same as the function's prototype property). |
500 | pub fn get_prototype<T>(&self) -> Result<T> |
501 | where |
502 | T: NapiValue, |
503 | { |
504 | let mut result = ptr::null_mut(); |
505 | check_status!(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?; |
506 | unsafe { T::from_raw(self.0.env, result) } |
507 | } |
508 | |
509 | pub fn get_prototype_unchecked<T>(&self) -> Result<T> |
510 | where |
511 | T: NapiValue, |
512 | { |
513 | let mut result = ptr::null_mut(); |
514 | check_status!(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?; |
515 | Ok(unsafe { T::from_raw_unchecked(self.0.env, result) }) |
516 | } |
517 | |
518 | pub fn set_element<T>(&mut self, index: u32, value: T) -> Result<()> |
519 | where |
520 | T: NapiRaw, |
521 | { |
522 | check_status!(unsafe { |
523 | sys::napi_set_element(self.0.env, self.0.value, index, value.raw()) |
524 | }) |
525 | } |
526 | |
527 | pub fn has_element(&self, index: u32) -> Result<bool> { |
528 | let mut result = false; |
529 | check_status!(unsafe { |
530 | sys::napi_has_element(self.0.env, self.0.value, index, &mut result) |
531 | })?; |
532 | Ok(result) |
533 | } |
534 | |
535 | pub fn delete_element(&mut self, index: u32) -> Result<bool> { |
536 | let mut result = false; |
537 | check_status!(unsafe { |
538 | sys::napi_delete_element(self.0.env, self.0.value, index, &mut result) |
539 | })?; |
540 | Ok(result) |
541 | } |
542 | |
543 | pub fn get_element<T>(&self, index: u32) -> Result<T> |
544 | where |
545 | T: NapiValue, |
546 | { |
547 | let mut raw_value = ptr::null_mut(); |
548 | check_status!(unsafe { |
549 | sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) |
550 | })?; |
551 | unsafe { T::from_raw(self.0.env, raw_value) } |
552 | } |
553 | |
554 | pub fn get_element_unchecked<T>(&self, index: u32) -> Result<T> |
555 | where |
556 | T: NapiValue, |
557 | { |
558 | let mut raw_value = ptr::null_mut(); |
559 | check_status!(unsafe { |
560 | sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) |
561 | })?; |
562 | Ok(unsafe { T::from_raw_unchecked(self.0.env, raw_value) }) |
563 | } |
564 | |
565 | /// This method allows the efficient definition of multiple properties on a given object. |
566 | pub fn define_properties(&mut self, properties: &[Property]) -> Result<()> { |
567 | let properties_iter = properties.iter().map(|property| property.raw()); |
568 | #[cfg(feature = "napi5" )] |
569 | { |
570 | let mut closures = properties_iter |
571 | .clone() |
572 | .map(|p| p.data) |
573 | .filter(|data| !data.is_null()) |
574 | .collect::<Vec<*mut std::ffi::c_void>>(); |
575 | let len = Box::into_raw(Box::new(closures.len())); |
576 | check_status!(unsafe { |
577 | sys::napi_add_finalizer( |
578 | self.0.env, |
579 | self.0.value, |
580 | closures.as_mut_ptr().cast(), |
581 | Some(finalize_closures), |
582 | len.cast(), |
583 | ptr::null_mut(), |
584 | ) |
585 | })?; |
586 | std::mem::forget(closures); |
587 | } |
588 | check_status!(unsafe { |
589 | sys::napi_define_properties( |
590 | self.0.env, |
591 | self.0.value, |
592 | properties.len(), |
593 | properties_iter |
594 | .collect::<Vec<sys::napi_property_descriptor>>() |
595 | .as_ptr(), |
596 | ) |
597 | }) |
598 | } |
599 | |
600 | /// Perform `is_array` check before get the length |
601 | /// if `Object` is not array, `ArrayExpected` error returned |
602 | pub fn get_array_length(&self) -> Result<u32> { |
603 | if self.is_array()? != true { |
604 | return Err(Error::new( |
605 | Status::ArrayExpected, |
606 | "Object is not array" .to_owned(), |
607 | )); |
608 | } |
609 | self.get_array_length_unchecked() |
610 | } |
611 | |
612 | /// use this API if you can ensure this `Object` is `Array` |
613 | pub fn get_array_length_unchecked(&self) -> Result<u32> { |
614 | let mut length: u32 = 0; |
615 | check_status!(unsafe { |
616 | sys::napi_get_array_length(self.0.env, self.0.value, &mut length) |
617 | })?; |
618 | Ok(length) |
619 | } |
620 | |
621 | #[cfg(feature = "napi8" )] |
622 | pub fn freeze(&mut self) -> Result<()> { |
623 | check_status!(unsafe { sys::napi_object_freeze(self.0.env, self.0.value) }) |
624 | } |
625 | |
626 | #[cfg(feature = "napi8" )] |
627 | pub fn seal(&mut self) -> Result<()> { |
628 | check_status!(unsafe { sys::napi_object_seal(self.0.env, self.0.value) }) |
629 | } |
630 | } |
631 | }; |
632 | } |
633 | |
634 | pub trait NapiRaw { |
635 | #[allow (clippy::missing_safety_doc)] |
636 | unsafe fn raw(&self) -> sys::napi_value; |
637 | } |
638 | |
639 | pub trait NapiValue: Sized + NapiRaw { |
640 | #[allow (clippy::missing_safety_doc)] |
641 | unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self>; |
642 | |
643 | #[allow (clippy::missing_safety_doc)] |
644 | unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Self; |
645 | } |
646 | |
647 | impl_js_value_methods!(JsUnknown); |
648 | impl_js_value_methods!(JsUndefined); |
649 | impl_js_value_methods!(JsNull); |
650 | impl_js_value_methods!(JsBoolean); |
651 | impl_js_value_methods!(JsBuffer); |
652 | impl_js_value_methods!(JsArrayBuffer); |
653 | impl_js_value_methods!(JsTypedArray); |
654 | impl_js_value_methods!(JsDataView); |
655 | impl_js_value_methods!(JsNumber); |
656 | impl_js_value_methods!(JsString); |
657 | impl_js_value_methods!(JsObject); |
658 | impl_js_value_methods!(JsGlobal); |
659 | #[cfg (feature = "napi5" )] |
660 | impl_js_value_methods!(JsDate); |
661 | impl_js_value_methods!(JsFunction); |
662 | impl_js_value_methods!(JsExternal); |
663 | impl_js_value_methods!(JsSymbol); |
664 | impl_js_value_methods!(JsTimeout); |
665 | impl_js_value_methods!(JSON); |
666 | |
667 | impl_object_methods!(JsObject); |
668 | impl_object_methods!(JsBuffer); |
669 | impl_object_methods!(JsArrayBuffer); |
670 | impl_object_methods!(JsTypedArray); |
671 | impl_object_methods!(JsDataView); |
672 | impl_object_methods!(JsGlobal); |
673 | impl_object_methods!(JSON); |
674 | |
675 | use ValueType::*; |
676 | |
677 | impl_napi_value_trait!(JsUndefined, Undefined); |
678 | impl_napi_value_trait!(JsNull, Null); |
679 | impl_napi_value_trait!(JsBoolean, Boolean); |
680 | impl_napi_value_trait!(JsBuffer, Object); |
681 | impl_napi_value_trait!(JsArrayBuffer, Object); |
682 | impl_napi_value_trait!(JsTypedArray, Object); |
683 | impl_napi_value_trait!(JsDataView, Object); |
684 | impl_napi_value_trait!(JsNumber, Number); |
685 | impl_napi_value_trait!(JsString, String); |
686 | impl_napi_value_trait!(JsObject, Object); |
687 | impl_napi_value_trait!(JsGlobal, Object); |
688 | #[cfg (feature = "napi5" )] |
689 | impl_napi_value_trait!(JsDate, Object); |
690 | impl_napi_value_trait!(JsTimeout, Object); |
691 | impl_napi_value_trait!(JsFunction, Function); |
692 | impl_napi_value_trait!(JsExternal, External); |
693 | impl_napi_value_trait!(JsSymbol, Symbol); |
694 | |
695 | impl NapiValue for JsUnknown { |
696 | unsafe fn from_raw(env: sys::napi_env, value: sys::napi_value) -> Result<Self> { |
697 | Ok(JsUnknown(Value { |
698 | env, |
699 | value, |
700 | value_type: Unknown, |
701 | })) |
702 | } |
703 | |
704 | unsafe fn from_raw_unchecked(env: sys::napi_env, value: sys::napi_value) -> Self { |
705 | JsUnknown(Value { |
706 | env, |
707 | value, |
708 | value_type: Unknown, |
709 | }) |
710 | } |
711 | } |
712 | |
713 | impl NapiRaw for JsUnknown { |
714 | /// get raw js value ptr |
715 | unsafe fn raw(&self) -> sys::napi_value { |
716 | self.0.value |
717 | } |
718 | } |
719 | |
720 | impl<'env> NapiRaw for &'env JsUnknown { |
721 | /// get raw js value ptr |
722 | unsafe fn raw(&self) -> sys::napi_value { |
723 | self.0.value |
724 | } |
725 | } |
726 | |
727 | impl JsUnknown { |
728 | pub fn get_type(&self) -> Result<ValueType> { |
729 | type_of!(self.0.env, self.0.value) |
730 | } |
731 | |
732 | /// # Safety |
733 | /// |
734 | /// This function should be called after `JsUnknown::get_type` |
735 | /// |
736 | /// And the `V` must be match with the return value of `get_type` |
737 | pub unsafe fn cast<V>(&self) -> V |
738 | where |
739 | V: NapiValue, |
740 | { |
741 | unsafe { V::from_raw_unchecked(self.0.env, self.0.value) } |
742 | } |
743 | } |
744 | |
745 | #[cfg (feature = "napi5" )] |
746 | unsafe extern "C" fn finalize_closures(_env: sys::napi_env, data: *mut c_void, len: *mut c_void) { |
747 | let length: usize = *unsafe { Box::from_raw(len.cast()) }; |
748 | let closures: Vec<*mut PropertyClosures> = |
749 | unsafe { Vec::from_raw_parts(ptr:data.cast(), length, capacity:length) }; |
750 | for closure: *mut PropertyClosures in closures.into_iter() { |
751 | drop(unsafe { Box::from_raw(closure) }); |
752 | } |
753 | } |
754 | |