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#[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 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#[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<'a, T: Traceable + 'static> RootedVec<'a, T> {
53 pub fn new(root: &'a mut RootableVec<T>) -> RootedVec<'a, T> {
54 unsafe {
55 RootedTraceableSet::add(root);
56 }
57 RootedVec { root }
58 }
59
60 pub fn from_iter<I>(root: &'a mut RootableVec<T>, iter: I) -> Self
61 where
62 I: Iterator<Item = T>,
63 {
64 unsafe {
65 RootedTraceableSet::add(root);
66 }
67 root.v.extend(iter);
68 RootedVec { root }
69 }
70}
71
72impl<'a, T: Traceable + 'static> Drop for RootedVec<'a, T> {
73 fn drop(&mut self) {
74 self.clear();
75 unsafe {
76 RootedTraceableSet::remove(self.root);
77 }
78 }
79}
80
81impl<'a, T: Traceable> Deref for RootedVec<'a, T> {
82 type Target = Vec<T>;
83 fn deref(&self) -> &Vec<T> {
84 &self.root.v
85 }
86}
87
88impl<'a, T: Traceable> DerefMut for RootedVec<'a, T> {
89 fn deref_mut(&mut self) -> &mut Vec<T> {
90 &mut self.root.v
91 }
92}
93
94pub struct RootedTraceableBox<T: Traceable + 'static> {
99 ptr: *mut T,
100}
101
102impl<T: Traceable + 'static> RootedTraceableBox<T> {
103 pub fn new(traceable: T) -> RootedTraceableBox<T> {
105 Self::from_box(Box::new(traceable))
106 }
107
108 pub fn from_box(boxed_traceable: Box<T>) -> RootedTraceableBox<T> {
110 let traceable = Box::into_raw(boxed_traceable);
111 unsafe {
112 RootedTraceableSet::add(traceable);
113 }
114 RootedTraceableBox { ptr: traceable }
115 }
116
117 pub unsafe fn ptr(&self) -> *mut T {
119 self.ptr
120 }
121}
122
123impl<T> RootedTraceableBox<Heap<T>>
124where
125 Heap<T>: Traceable + 'static,
126 T: GCMethods + Copy,
127{
128 pub fn handle(&self) -> Handle<T> {
129 unsafe { Handle::from_raw((*self.ptr).handle()) }
130 }
131}
132
133unsafe impl<T: Traceable + 'static> Traceable for RootedTraceableBox<T> {
134 unsafe fn trace(&self, trc: *mut JSTracer) {
135 (*self.ptr).trace(trc)
136 }
137}
138
139impl<T: Traceable> Deref for RootedTraceableBox<T> {
140 type Target = T;
141 fn deref(&self) -> &T {
142 unsafe { &*self.ptr }
143 }
144}
145
146impl<T: Traceable> DerefMut for RootedTraceableBox<T> {
147 fn deref_mut(&mut self) -> &mut T {
148 unsafe { &mut *self.ptr }
149 }
150}
151
152impl<T: Traceable + 'static> Drop for RootedTraceableBox<T> {
153 fn drop(&mut self) {
154 unsafe {
155 RootedTraceableSet::remove(self.ptr);
156 let _ = Box::from_raw(self.ptr);
157 }
158 }
159}