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