napi/js_values/
mod.rs

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