1use std::marker::PhantomData;
2use std::mem::MaybeUninit;
3use std::ops::{Deref, IndexMut};
4use std::ptr;
5use std::ptr::NonNull;
6
7use crate::context::NoGC;
8use crate::jsapi::{jsid, JSContext, JSFunction, JSObject, JSScript, JSString, Symbol, Value, JS};
9use mozjs_sys::jsgc::{RootKind, Rooted};
10
11use crate::jsapi::Handle as RawHandle;
12use crate::jsapi::HandleObject as RawHandleObject;
13use crate::jsapi::HandleValue as RawHandleValue;
14use crate::jsapi::MutableHandle as RawMutableHandle;
15use mozjs_sys::jsgc::IntoHandle as IntoRawHandle;
16use mozjs_sys::jsgc::IntoMutableHandle as IntoRawMutableHandle;
17use mozjs_sys::jsgc::ValueArray;
18
19#[cfg_attr(
23 feature = "crown",
24 crown::unrooted_must_root_lint::allow_unrooted_interior
25)]
26pub struct RootedGuard<'a, T: 'a + RootKind> {
27 root: *mut Rooted<T>,
28 anchor: PhantomData<&'a mut Rooted<T>>,
29}
30
31impl<'a, T: 'a + RootKind> RootedGuard<'a, T> {
32 pub fn new(cx: *mut JSContext, root: &'a mut MaybeUninit<Rooted<T>>, initial: T) -> Self {
33 let root: *mut Rooted<T> = root.write(Rooted::new_unrooted(initial));
34
35 unsafe {
36 Rooted::add_to_root_stack(root, cx);
37 RootedGuard {
38 root,
39 anchor: PhantomData,
40 }
41 }
42 }
43
44 pub fn handle(&'a self) -> Handle<'a, T> {
45 unsafe { Handle::from_marked_location(self.as_ptr()) }
47 }
48
49 pub fn handle_mut(&mut self) -> MutableHandle<T> {
50 unsafe { MutableHandle::from_marked_location(self.as_ptr()) }
51 }
52
53 pub fn as_ptr(&self) -> *mut T {
54 unsafe { (&raw mut (*self.root).data) }
56 }
57
58 pub fn as_ref<'s: 'r, 'cx: 'r, 'r>(&'s self, _no_gc: &'cx NoGC) -> &'r T
76 where
77 'a: 's,
78 {
79 unsafe { &*(self.as_ptr()) }
80 }
81
82 pub fn as_mut_ref<'s: 'r, 'cx: 'r, 'r>(&'s mut self, _no_gc: &'cx NoGC) -> &'r mut T
100 where
101 'a: 's,
102 {
103 unsafe { &mut *(self.as_ptr()) }
104 }
105
106 pub unsafe fn as_mut<'b>(&'b mut self) -> &'b mut T
109 where
110 'a: 'b,
111 {
112 &mut *(self.as_ptr())
113 }
114
115 pub fn get(&self) -> T
116 where
117 T: Copy,
118 {
119 *self.deref()
120 }
121
122 pub fn set(&mut self, v: T) {
123 unsafe { *self.as_mut() = v };
125 }
126}
127
128impl<'a, T> RootedGuard<'a, Option<T>>
129where
130 Option<T>: RootKind,
131{
132 pub fn take(&mut self) -> Option<T> {
133 unsafe { self.as_mut().take() }
135 }
136}
137
138impl<'a, T> RootedGuard<'a, Vec<T>>
139where
140 Vec<T>: RootKind,
141{
142 pub fn push(&mut self, value: T) {
143 unsafe { self.as_mut().push(value) }
145 }
146
147 pub fn extend(&mut self, iterator: impl Iterator<Item = T>) {
148 unsafe { self.as_mut().extend(iterator) }
150 }
151
152 pub fn set_index(&mut self, index: usize, value: T) {
153 unsafe {
155 *self.as_mut().index_mut(index) = value;
156 }
157 }
158
159 pub fn handle_at(&'_ self, index: usize) -> Handle<'_, T> {
160 assert!(index < self.len());
161 unsafe { Handle::from_marked_location(self.deref().as_ptr().add(index)) }
163 }
164
165 pub fn handle_mut_at(&'_ mut self, index: usize) -> MutableHandle<'_, T> {
166 assert!(index < self.len());
167 unsafe { MutableHandle::from_marked_location(self.as_mut().as_mut_ptr().add(index)) }
169 }
170}
171
172impl<'a, T: 'a + RootKind> Deref for RootedGuard<'a, T> {
173 type Target = T;
174
175 fn deref(&self) -> &T {
178 unsafe { &(*self.root).data }
179 }
180}
181
182impl<'a, T: 'a + RootKind> Drop for RootedGuard<'a, T> {
183 fn drop(&mut self) {
184 unsafe {
187 let ptr = self.as_ptr();
188 ptr::drop_in_place(ptr);
189 ptr.write_bytes(0, 1);
190 }
191
192 unsafe {
193 (*self.root).remove_from_root_stack();
194 }
195 }
196}
197
198impl<'a, const N: usize> From<&RootedGuard<'a, ValueArray<N>>> for JS::HandleValueArray {
199 fn from(array: &RootedGuard<'a, ValueArray<N>>) -> JS::HandleValueArray {
200 JS::HandleValueArray::from(unsafe { &*array.root })
201 }
202}
203
204pub struct Handle<'a, T: 'a> {
205 pub(crate) ptr: NonNull<T>,
206 pub(crate) _phantom: PhantomData<&'a T>,
207}
208
209impl<T> Clone for Handle<'_, T> {
210 fn clone(&self) -> Self {
211 *self
212 }
213}
214
215impl<T> Copy for Handle<'_, T> {}
216
217#[cfg_attr(
218 feature = "crown",
219 crown::unrooted_must_root_lint::allow_unrooted_interior
220)]
221pub struct MutableHandle<'a, T: 'a> {
222 pub(crate) ptr: NonNull<T>,
223 anchor: PhantomData<&'a mut T>,
224}
225
226pub type HandleFunction<'a> = Handle<'a, *mut JSFunction>;
227pub type HandleId<'a> = Handle<'a, jsid>;
228pub type HandleObject<'a> = Handle<'a, *mut JSObject>;
229pub type HandleScript<'a> = Handle<'a, *mut JSScript>;
230pub type HandleString<'a> = Handle<'a, *mut JSString>;
231pub type HandleSymbol<'a> = Handle<'a, *mut Symbol>;
232pub type HandleValue<'a> = Handle<'a, Value>;
233
234pub type MutableHandleFunction<'a> = MutableHandle<'a, *mut JSFunction>;
235pub type MutableHandleId<'a> = MutableHandle<'a, jsid>;
236pub type MutableHandleObject<'a> = MutableHandle<'a, *mut JSObject>;
237pub type MutableHandleScript<'a> = MutableHandle<'a, *mut JSScript>;
238pub type MutableHandleString<'a> = MutableHandle<'a, *mut JSString>;
239pub type MutableHandleSymbol<'a> = MutableHandle<'a, *mut Symbol>;
240pub type MutableHandleValue<'a> = MutableHandle<'a, Value>;
241
242impl<'a, T> Handle<'a, T> {
243 pub fn get(&self) -> T
244 where
245 T: Copy,
246 {
247 unsafe { *self.ptr.as_ptr() }
248 }
249
250 pub fn as_ref<'s: 'r, 'cx: 'r, 'r>(&'s self, _no_gc: &'cx NoGC) -> &'r T
270 where
271 'a: 's,
272 {
273 unsafe { self.ptr.as_ref() }
274 }
275
276 pub unsafe fn from_marked_location(ptr: *const T) -> Self {
277 Handle {
278 ptr: NonNull::new(ptr as *mut T).unwrap(),
279 _phantom: PhantomData,
280 }
281 }
282
283 pub unsafe fn from_raw(handle: RawHandle<T>) -> Self {
284 Handle::from_marked_location(handle.ptr)
285 }
286}
287
288impl<'a, T> IntoRawHandle for Handle<'a, T> {
289 type Target = T;
290 fn into_handle(self) -> RawHandle<T> {
291 unsafe { RawHandle::from_marked_location(self.ptr.as_ptr()) }
292 }
293}
294
295impl<'a, T> IntoRawHandle for MutableHandle<'a, T> {
296 type Target = T;
297 fn into_handle(self) -> RawHandle<T> {
298 unsafe { RawHandle::from_marked_location(self.ptr.as_ptr()) }
299 }
300}
301
302impl<'a, T> IntoRawMutableHandle for MutableHandle<'a, T> {
303 fn into_handle_mut(self) -> RawMutableHandle<T> {
304 unsafe { RawMutableHandle::from_marked_location(self.ptr.as_ptr()) }
305 }
306}
307
308impl<'a, T> Deref for Handle<'a, T> {
309 type Target = T;
310
311 fn deref(&self) -> &T {
314 unsafe { self.ptr.as_ref() }
315 }
316}
317
318impl<'a, T> MutableHandle<'a, T> {
319 pub unsafe fn from_marked_location(ptr: *mut T) -> Self {
320 Self {
321 ptr: NonNull::new(ptr).unwrap(),
322 anchor: PhantomData,
323 }
324 }
325
326 pub unsafe fn from_raw(handle: RawMutableHandle<T>) -> Self {
327 MutableHandle::from_marked_location(handle.ptr)
328 }
329
330 pub fn handle(&self) -> Handle<'a, T> {
331 unsafe { Handle::from_marked_location(self.ptr.as_ptr()) }
333 }
334
335 pub fn get(&self) -> T
336 where
337 T: Copy,
338 {
339 unsafe { *self.ptr.as_ptr() }
340 }
341
342 pub fn set(&mut self, v: T)
343 where
344 T: Copy,
345 {
346 unsafe { *self.ptr.as_mut() = v }
347 }
348
349 pub fn as_ref<'s: 'r, 'cx: 'r, 'r>(&'s self, _no_gc: &'cx NoGC) -> &'r T
368 where
369 'a: 's,
370 {
371 unsafe { self.ptr.as_ref() }
372 }
373
374 pub fn as_mut_ref<'s: 'r, 'cx: 'r, 'r>(&'s mut self, _no_gc: &'cx NoGC) -> &'r mut T
393 where
394 'a: 's,
395 {
396 unsafe { self.ptr.as_mut() }
397 }
398
399 pub unsafe fn as_mut<'b>(&'b mut self) -> &'b mut T
402 where
403 'a: 'b,
404 {
405 self.ptr.as_mut()
406 }
407
408 pub fn reborrow<'b>(&'b mut self) -> MutableHandle<'b, T>
419 where
420 'a: 'b,
421 {
422 MutableHandle {
423 ptr: self.ptr,
424 anchor: PhantomData,
425 }
426 }
427
428 pub(crate) fn raw(&mut self) -> RawMutableHandle<T> {
429 unsafe { RawMutableHandle::from_marked_location(self.ptr.as_ptr()) }
430 }
431}
432
433impl<'a, T> MutableHandle<'a, Option<T>> {
434 pub fn take(&mut self) -> Option<T> {
435 unsafe { self.as_mut().take() }
437 }
438}
439
440impl<'a, T> Deref for MutableHandle<'a, T> {
441 type Target = T;
442
443 fn deref(&self) -> &T {
446 unsafe { self.ptr.as_ref() }
447 }
448}
449
450impl HandleValue<'static> {
451 pub fn null() -> Self {
452 unsafe { Self::from_raw(RawHandleValue::null()) }
453 }
454
455 pub fn undefined() -> Self {
456 unsafe { Self::from_raw(RawHandleValue::undefined()) }
457 }
458}
459
460impl<'a> HandleObject<'a> {
461 pub fn null() -> Self {
462 unsafe { Self::from_raw(RawHandleObject::null()) }
463 }
464}