Skip to main content

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::*;
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      /// <https://nodejs.org/api/n-api.html#n_api_napi_get_all_property_names>
524      /// return `Array` of property names
525      #[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      /// This returns the equivalent of `Object.getPrototypeOf` (which is not the same as the function's prototype property).
547      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      /// This method allows the efficient definition of multiple properties on a given object.
618      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      /// Perform `is_array` check before get the length
658      /// if `Object` is not array, `ArrayExpected` error returned
659      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      /// use this API if you can ensure this `Object` is `Array`
670      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);