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