quickjs_runtime/quickjs_utils/
properties.rs

1use crate::jsutils::JsError;
2use crate::quickjs_utils::atoms;
3use crate::quickjs_utils::atoms::JSAtomRef;
4use libquickjs_sys as q;
5#[cfg(feature = "bellard")]
6use std::os::raw::c_int;
7
8#[allow(clippy::upper_case_acronyms)]
9/// this is a wrapper struct for JSPropertyEnum struct in quickjs
10/// it used primarily as a result of objects::get_own_property_names()
11pub struct JSPropertyEnumRef {
12    context: *mut q::JSContext,
13    property_enum: *mut q::JSPropertyEnum,
14    length: u32,
15}
16
17impl JSPropertyEnumRef {
18    pub fn new(
19        context: *mut q::JSContext,
20        property_enum: *mut q::JSPropertyEnum,
21        length: u32,
22    ) -> Self {
23        Self {
24            context,
25            property_enum,
26            length,
27        }
28    }
29    /// get a raw ptr to an Atom
30    /// # Safety
31    /// do not drop the JSPropertyEnumRef while still using the ptr
32    pub unsafe fn get_atom_raw(&self, index: u32) -> *mut q::JSAtom {
33        if index >= self.length {
34            panic!("index out of bounds");
35        }
36        let prop: *mut q::JSPropertyEnum = self.property_enum.offset(index as isize);
37        let atom: *mut q::JSAtom = (*prop).atom as *mut q::JSAtom;
38        atom
39    }
40    pub fn get_atom(&self, index: u32) -> JSAtomRef {
41        let atom: *mut q::JSAtom = unsafe { self.get_atom_raw(index) };
42        let atom_ref = JSAtomRef::new(self.context, atom as q::JSAtom);
43        atom_ref.increment_ref_ct();
44        atom_ref
45    }
46    pub fn get_name(&self, index: u32) -> Result<String, JsError> {
47        let atom: *mut q::JSAtom = unsafe { self.get_atom_raw(index) };
48        let atom = atom as q::JSAtom;
49        unsafe { Ok(atoms::to_str(self.context, &atom)?.to_string()) }
50    }
51    pub fn is_enumerable(&self, index: u32) -> bool {
52        if index >= self.length {
53            panic!("index out of bounds");
54        }
55        unsafe {
56            let prop: *mut q::JSPropertyEnum = self.property_enum.offset(index as isize);
57            #[cfg(feature = "bellard")]
58            {
59                let is_enumerable: c_int = (*prop).is_enumerable;
60                is_enumerable != 0
61            }
62            #[cfg(feature = "quickjs-ng")]
63            (*prop).is_enumerable
64        }
65    }
66    pub fn len(&self) -> u32 {
67        self.length
68    }
69    pub fn is_empty(&self) -> bool {
70        self.length == 0
71    }
72}
73
74impl Drop for JSPropertyEnumRef {
75    fn drop(&mut self) {
76        unsafe {
77            for index in 0..self.length {
78                let prop: *mut q::JSPropertyEnum = self.property_enum.offset(index as isize);
79                q::JS_FreeAtom(self.context, (*prop).atom);
80            }
81
82            q::js_free(self.context, self.property_enum as *mut std::ffi::c_void);
83        }
84    }
85}