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