1use std::marker::PhantomData;
2use std::mem::MaybeUninit;
3use std::ops::Deref;
4use std::ptr;
5
6use crate::jsapi::{jsid, JSContext, JSFunction, JSObject, JSScript, JSString, Symbol, Value, JS};
7use mozjs_sys::jsgc::{RootKind, Rooted};
8
9use crate::jsapi::Handle as RawHandle;
10use crate::jsapi::HandleValue as RawHandleValue;
11use crate::jsapi::MutableHandle as RawMutableHandle;
12use mozjs_sys::jsgc::IntoHandle as IntoRawHandle;
13use mozjs_sys::jsgc::IntoMutableHandle as IntoRawMutableHandle;
14use mozjs_sys::jsgc::ValueArray;
15
16#[cfg_attr(
20 feature = "crown",
21 crown::unrooted_must_root_lint::allow_unrooted_interior
22)]
23pub struct RootedGuard<'a, T: 'a + RootKind> {
24 root: *mut Rooted<T>,
25 anchor: PhantomData<&'a mut Rooted<T>>,
26}
27
28impl<'a, T: 'a + RootKind> RootedGuard<'a, T> {
29 pub fn new(cx: *mut JSContext, root: &'a mut MaybeUninit<Rooted<T>>, initial: T) -> Self {
30 let root: *mut Rooted<T> = root.write(Rooted::new_unrooted(initial));
31
32 unsafe {
33 Rooted::add_to_root_stack(root, cx);
34 RootedGuard {
35 root,
36 anchor: PhantomData,
37 }
38 }
39 }
40
41 pub fn handle(&'a self) -> Handle<'a, T> {
42 Handle::new(&self)
43 }
44
45 pub fn handle_mut(&mut self) -> MutableHandle<T> {
46 unsafe { MutableHandle::from_marked_location(self.as_ptr()) }
47 }
48
49 pub fn as_ptr(&self) -> *mut T {
50 unsafe { (&raw mut (*self.root).data) }
52 }
53
54 pub unsafe fn as_mut<'b>(&'b mut self) -> &'b mut T
56 where
57 'a: 'b,
58 {
59 &mut *(self.as_ptr())
60 }
61
62 pub fn get(&self) -> T
63 where
64 T: Copy,
65 {
66 *self.deref()
67 }
68
69 pub fn set(&mut self, v: T) {
70 unsafe { *self.as_mut() = v };
72 }
73}
74
75impl<'a, T> RootedGuard<'a, Option<T>>
76where
77 Option<T>: RootKind,
78{
79 pub fn take(&mut self) -> Option<T> {
80 unsafe { self.as_mut().take() }
82 }
83}
84
85impl<'a, T: 'a + RootKind> Deref for RootedGuard<'a, T> {
86 type Target = T;
87 fn deref(&self) -> &T {
88 unsafe { &(*self.root).data }
89 }
90}
91
92impl<'a, T: 'a + RootKind> Drop for RootedGuard<'a, T> {
93 fn drop(&mut self) {
94 unsafe {
97 let ptr = self.as_ptr();
98 ptr::drop_in_place(ptr);
99 ptr.write_bytes(0, 1);
100 }
101
102 unsafe {
103 (*self.root).remove_from_root_stack();
104 }
105 }
106}
107
108impl<'a, const N: usize> From<&RootedGuard<'a, ValueArray<N>>> for JS::HandleValueArray {
109 fn from(array: &RootedGuard<'a, ValueArray<N>>) -> JS::HandleValueArray {
110 JS::HandleValueArray::from(unsafe { &*array.root })
111 }
112}
113
114pub struct Handle<'a, T: 'a> {
115 pub(crate) ptr: &'a T,
116}
117
118impl<T> Clone for Handle<'_, T> {
119 fn clone(&self) -> Self {
120 *self
121 }
122}
123
124impl<T> Copy for Handle<'_, T> {}
125
126#[cfg_attr(
127 feature = "crown",
128 crown::unrooted_must_root_lint::allow_unrooted_interior
129)]
130pub struct MutableHandle<'a, T: 'a> {
131 pub(crate) ptr: *mut T,
132 anchor: PhantomData<&'a mut T>,
133}
134
135pub type HandleFunction<'a> = Handle<'a, *mut JSFunction>;
136pub type HandleId<'a> = Handle<'a, jsid>;
137pub type HandleObject<'a> = Handle<'a, *mut JSObject>;
138pub type HandleScript<'a> = Handle<'a, *mut JSScript>;
139pub type HandleString<'a> = Handle<'a, *mut JSString>;
140pub type HandleSymbol<'a> = Handle<'a, *mut Symbol>;
141pub type HandleValue<'a> = Handle<'a, Value>;
142
143pub type MutableHandleFunction<'a> = MutableHandle<'a, *mut JSFunction>;
144pub type MutableHandleId<'a> = MutableHandle<'a, jsid>;
145pub type MutableHandleObject<'a> = MutableHandle<'a, *mut JSObject>;
146pub type MutableHandleScript<'a> = MutableHandle<'a, *mut JSScript>;
147pub type MutableHandleString<'a> = MutableHandle<'a, *mut JSString>;
148pub type MutableHandleSymbol<'a> = MutableHandle<'a, *mut Symbol>;
149pub type MutableHandleValue<'a> = MutableHandle<'a, Value>;
150
151impl<'a, T> Handle<'a, T> {
152 pub fn get(&self) -> T
153 where
154 T: Copy,
155 {
156 *self.ptr
157 }
158
159 pub(crate) fn new(ptr: &'a T) -> Self {
160 Handle { ptr }
161 }
162
163 pub unsafe fn from_marked_location(ptr: *const T) -> Self {
164 Handle::new(&*ptr)
165 }
166
167 pub unsafe fn from_raw(handle: RawHandle<T>) -> Self {
168 Handle::from_marked_location(handle.ptr)
169 }
170}
171
172impl<'a, T> IntoRawHandle for Handle<'a, T> {
173 type Target = T;
174 fn into_handle(self) -> RawHandle<T> {
175 unsafe { RawHandle::from_marked_location(self.ptr) }
176 }
177}
178
179impl<'a, T> IntoRawHandle for MutableHandle<'a, T> {
180 type Target = T;
181 fn into_handle(self) -> RawHandle<T> {
182 unsafe { RawHandle::from_marked_location(self.ptr) }
183 }
184}
185
186impl<'a, T> IntoRawMutableHandle for MutableHandle<'a, T> {
187 fn into_handle_mut(self) -> RawMutableHandle<T> {
188 unsafe { RawMutableHandle::from_marked_location(self.ptr) }
189 }
190}
191
192impl<'a, T> Deref for Handle<'a, T> {
193 type Target = T;
194
195 fn deref(&self) -> &T {
196 self.ptr
197 }
198}
199
200impl<'a, T> MutableHandle<'a, T> {
201 pub unsafe fn from_marked_location(ptr: *mut T) -> Self {
202 MutableHandle::new(&mut *ptr)
203 }
204
205 pub unsafe fn from_raw(handle: RawMutableHandle<T>) -> Self {
206 MutableHandle::from_marked_location(handle.ptr)
207 }
208
209 pub fn handle(&self) -> Handle<T> {
210 unsafe { Handle::new(&*self.ptr) }
211 }
212
213 pub(crate) fn new(ptr: &'a mut T) -> Self {
214 Self {
215 ptr,
216 anchor: PhantomData,
217 }
218 }
219
220 pub fn get(&self) -> T
221 where
222 T: Copy,
223 {
224 unsafe { *self.ptr }
225 }
226
227 pub fn set(&mut self, v: T)
228 where
229 T: Copy,
230 {
231 unsafe { *self.ptr = v }
232 }
233
234 pub unsafe fn as_mut<'b>(&'b mut self) -> &'b mut T
236 where
237 'a: 'b,
238 {
239 &mut *(self.ptr)
240 }
241
242 pub fn reborrow<'b>(&'b mut self) -> MutableHandle<'b, T>
253 where
254 'a: 'b,
255 {
256 MutableHandle {
257 ptr: self.ptr,
258 anchor: PhantomData,
259 }
260 }
261
262 pub(crate) fn raw(&mut self) -> RawMutableHandle<T> {
263 unsafe { RawMutableHandle::from_marked_location(self.ptr) }
264 }
265}
266
267impl<'a, T> MutableHandle<'a, Option<T>> {
268 pub fn take(&mut self) -> Option<T> {
269 unsafe { self.as_mut().take() }
271 }
272}
273
274impl<'a, T> Deref for MutableHandle<'a, T> {
275 type Target = T;
276
277 fn deref(&self) -> &T {
278 unsafe { &*self.ptr }
279 }
280}
281
282impl HandleValue<'static> {
283 pub fn null() -> Self {
284 unsafe { Self::from_raw(RawHandleValue::null()) }
285 }
286
287 pub fn undefined() -> Self {
288 unsafe { Self::from_raw(RawHandleValue::undefined()) }
289 }
290}
291
292const ConstNullValue: *mut JSObject = ptr::null_mut();
293
294impl<'a> HandleObject<'a> {
295 pub fn null() -> Self {
296 unsafe { HandleObject::from_marked_location(&ConstNullValue) }
297 }
298}