mozjs/gc/
collections.rs

1use crate::gc::RootedTraceableSet;
2use crate::jsapi::{Heap, JSTracer};
3use crate::rust::Handle;
4use mozjs_sys::jsapi::JS;
5use mozjs_sys::jsgc::GCMethods;
6use mozjs_sys::jsval::JSVal;
7use mozjs_sys::trace::Traceable;
8use std::ops::{Deref, DerefMut};
9
10/// A vector of items to be rooted with `RootedVec`.
11/// Guaranteed to be empty when not rooted.
12#[cfg_attr(feature = "crown", allow(crown::unrooted_must_root))]
13#[cfg_attr(
14    feature = "crown",
15    crown::unrooted_must_root_lint::allow_unrooted_interior
16)]
17pub struct RootableVec<T: Traceable> {
18    v: Vec<T>,
19}
20
21impl<T: Traceable> RootableVec<T> {
22    /// Create a vector of items of type T that can be rooted later.
23    pub fn new_unrooted() -> RootableVec<T> {
24        RootableVec { v: Vec::new() }
25    }
26}
27
28unsafe impl<T: Traceable> Traceable for RootableVec<T> {
29    unsafe fn trace(&self, trc: *mut JSTracer) {
30        self.v.trace(trc);
31    }
32}
33
34/// A vector of items rooted for the lifetime 'a.
35#[cfg_attr(
36    feature = "crown",
37    crown::unrooted_must_root_lint::allow_unrooted_interior
38)]
39pub struct RootedVec<'a, T: Traceable + 'static> {
40    root: &'a mut RootableVec<T>,
41}
42
43impl From<&RootedVec<'_, JSVal>> for JS::HandleValueArray {
44    fn from(vec: &RootedVec<'_, JSVal>) -> JS::HandleValueArray {
45        JS::HandleValueArray {
46            length_: vec.root.v.len(),
47            elements_: vec.root.v.as_ptr(),
48        }
49    }
50}
51
52impl From<&super::RootedGuard<'_, Vec<JSVal>>> for JS::HandleValueArray {
53    fn from(vec: &super::RootedGuard<'_, Vec<JSVal>>) -> JS::HandleValueArray {
54        JS::HandleValueArray {
55            length_: vec.len(),
56            elements_: vec.deref().as_ptr(),
57        }
58    }
59}
60
61impl<'a, T: Traceable + 'static> RootedVec<'a, T> {
62    pub fn new(root: &'a mut RootableVec<T>) -> RootedVec<'a, T> {
63        unsafe {
64            RootedTraceableSet::add(root);
65        }
66        RootedVec { root }
67    }
68
69    pub fn from_iter<I>(root: &'a mut RootableVec<T>, iter: I) -> Self
70    where
71        I: Iterator<Item = T>,
72    {
73        unsafe {
74            RootedTraceableSet::add(root);
75        }
76        root.v.extend(iter);
77        RootedVec { root }
78    }
79}
80
81impl<'a, T: Traceable + 'static> Drop for RootedVec<'a, T> {
82    fn drop(&mut self) {
83        self.clear();
84        unsafe {
85            RootedTraceableSet::remove(self.root);
86        }
87    }
88}
89
90impl<'a, T: Traceable> Deref for RootedVec<'a, T> {
91    type Target = Vec<T>;
92    fn deref(&self) -> &Vec<T> {
93        &self.root.v
94    }
95}
96
97impl<'a, T: Traceable> DerefMut for RootedVec<'a, T> {
98    fn deref_mut(&mut self) -> &mut Vec<T> {
99        &mut self.root.v
100    }
101}
102
103/// Roots any JSTraceable thing
104///
105/// If you have GC things like *mut JSObject or JSVal, use rooted!.
106/// If you know what you're doing, use this.
107pub struct RootedTraceableBox<T: Traceable + 'static> {
108    ptr: *mut T,
109}
110
111impl<T: Traceable + 'static> RootedTraceableBox<T> {
112    /// Root a JSTraceable thing for the life of this RootedTraceableBox
113    pub fn new(traceable: T) -> RootedTraceableBox<T> {
114        Self::from_box(Box::new(traceable))
115    }
116
117    /// Consumes a boxed JSTraceable and roots it for the life of this RootedTraceableBox.
118    pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
119        let traceable = Box::into_raw(boxed_traceable);
120        unsafe {
121            RootedTraceableSet::add(traceable);
122        }
123        RootedTraceableBox { ptr: traceable }
124    }
125
126    /// Returns underlying pointer
127    pub unsafe fn ptr(&self) -> *mut T {
128        self.ptr
129    }
130}
131
132impl<T> RootedTraceableBox<Heap<T>>
133where
134    Heap<T>: Traceable + 'static,
135    T: GCMethods + Copy,
136{
137    pub fn handle(&self) -> Handle<T> {
138        unsafe { Handle::from_raw((*self.ptr).handle()) }
139    }
140}
141
142unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
143    unsafe fn trace(&self, trc: *mut JSTracer) {
144        (*self.ptr).trace(trc)
145    }
146}
147
148impl<T: Traceable> Deref for RootedTraceableBox<T> {
149    type Target = T;
150    fn deref(&self) -> &T {
151        unsafe { &*self.ptr }
152    }
153}
154
155impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
156    fn deref_mut(&mut self) -> &mut T {
157        unsafe { &mut *self.ptr }
158    }
159}
160
161impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
162    fn drop(&mut self) {
163        unsafe {
164            RootedTraceableSet::remove(self.ptr);
165            let _ = Box::from_raw(self.ptr);
166        }
167    }
168}