napi_calm_down/js_values/
mod.rs

1use std::convert::TryFrom;
2#[cfg(feature = "napi5")]
3use std::ffi::c_void;
4use std::ffi::CString;
5use std::ptr;
6
7use 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")]
13mod de;
14#[cfg(feature = "serde-json")]
15mod ser;
16
17mod arraybuffer;
18#[cfg(feature = "napi6")]
19mod bigint;
20mod boolean;
21mod buffer;
22#[cfg(feature = "napi5")]
23mod date;
24#[cfg(feature = "napi4")]
25mod deferred;
26mod either;
27mod escapable_handle_scope;
28mod function;
29mod global;
30mod number;
31mod object;
32mod object_property;
33mod string;
34mod tagged_object;
35mod undefined;
36mod value;
37mod value_ref;
38
39pub use arraybuffer::*;
40#[cfg(feature = "napi6")]
41pub use bigint::JsBigInt;
42pub use boolean::JsBoolean;
43pub use buffer::*;
44#[cfg(feature = "napi5")]
45pub use date::*;
46#[cfg(feature = "serde-json")]
47pub use de::De;
48#[cfg(feature = "napi4")]
49pub use deferred::*;
50pub use either::Either;
51pub use escapable_handle_scope::EscapableHandleScope;
52pub use function::JsFunction;
53pub use global::*;
54pub use number::JsNumber;
55pub use object::*;
56pub use object_property::*;
57#[cfg(feature = "serde-json")]
58pub use ser::Ser;
59pub use string::*;
60pub(crate) use tagged_object::TaggedObject;
61pub use undefined::JsUndefined;
62pub(crate) use value::Value;
63pub use value_ref::*;
64
65// Value types
66
67pub struct JsUnknown(pub(crate) Value);
68
69#[derive(Clone, Copy)]
70pub struct JsNull(pub(crate) Value);
71
72impl TypeName for JsNull {
73  fn type_name() -> &'static str {
74    "null"
75  }
76
77  fn value_type() -> ValueType {
78    ValueType::Null
79  }
80}
81
82impl ValidateNapiValue for JsNull {}
83
84#[derive(Clone, Copy)]
85pub struct JsSymbol(pub(crate) Value);
86
87impl TypeName for JsSymbol {
88  fn type_name() -> &'static str {
89    "symbol"
90  }
91
92  fn value_type() -> ValueType {
93    ValueType::Symbol
94  }
95}
96
97impl ValidateNapiValue for JsSymbol {}
98
99#[deprecated(since = "3.0.0", note = "Please use `External` instead")]
100pub struct JsExternal(pub(crate) Value);
101
102impl TypeName for JsExternal {
103  fn type_name() -> &'static str {
104    "external"
105  }
106
107  fn value_type() -> ValueType {
108    ValueType::External
109  }
110}
111
112impl ValidateNapiValue for JsExternal {}
113
114macro_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
163macro_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
275macro_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
632pub trait NapiRaw {
633  #[allow(clippy::missing_safety_doc)]
634  unsafe fn raw(&self) -> sys::napi_value;
635}
636
637pub 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
645impl_js_value_methods!(JsUnknown);
646impl_js_value_methods!(JsUndefined);
647impl_js_value_methods!(JsNull);
648impl_js_value_methods!(JsBoolean);
649impl_js_value_methods!(JsBuffer);
650impl_js_value_methods!(JsArrayBuffer);
651impl_js_value_methods!(JsTypedArray);
652impl_js_value_methods!(JsDataView);
653impl_js_value_methods!(JsNumber);
654impl_js_value_methods!(JsString);
655impl_js_value_methods!(JsObject);
656impl_js_value_methods!(JsGlobal);
657#[cfg(feature = "napi5")]
658impl_js_value_methods!(JsDate);
659impl_js_value_methods!(JsFunction);
660impl_js_value_methods!(JsExternal);
661impl_js_value_methods!(JsSymbol);
662impl_js_value_methods!(JsTimeout);
663impl_js_value_methods!(JSON);
664
665impl_object_methods!(JsObject);
666impl_object_methods!(JsBuffer);
667impl_object_methods!(JsArrayBuffer);
668impl_object_methods!(JsTypedArray);
669impl_object_methods!(JsDataView);
670impl_object_methods!(JsGlobal);
671impl_object_methods!(JSON);
672
673use ValueType::*;
674
675impl_napi_value_trait!(JsUndefined, Undefined);
676impl_napi_value_trait!(JsNull, Null);
677impl_napi_value_trait!(JsBoolean, Boolean);
678impl_napi_value_trait!(JsBuffer, Object);
679impl_napi_value_trait!(JsArrayBuffer, Object);
680impl_napi_value_trait!(JsTypedArray, Object);
681impl_napi_value_trait!(JsDataView, Object);
682impl_napi_value_trait!(JsNumber, Number);
683impl_napi_value_trait!(JsString, String);
684impl_napi_value_trait!(JsObject, Object);
685impl_napi_value_trait!(JsGlobal, Object);
686#[cfg(feature = "napi5")]
687impl_napi_value_trait!(JsDate, Object);
688impl_napi_value_trait!(JsTimeout, Object);
689impl_napi_value_trait!(JsFunction, Function);
690impl_napi_value_trait!(JsExternal, External);
691impl_napi_value_trait!(JsSymbol, Symbol);
692
693impl 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
711impl NapiRaw for JsUnknown {
712  /// get raw js value ptr
713  unsafe fn raw(&self) -> sys::napi_value {
714    self.0.value
715  }
716}
717
718impl<'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
725impl 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")]
744unsafe 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(data.cast(), length, length) };
748  for closure in closures.into_iter() {
749    drop(unsafe { Box::from_raw(closure) });
750  }
751}