1use crate::jsapi::{Heap, JSObject, JSTracer};
2use crate::rust::{Runtime, Stencil};
3use mozjs_sys::trace::Traceable;
4use std::cell::RefCell;
5use std::ffi::c_void;
6
7use crate::typedarray::{TypedArray, TypedArrayElement};
8
9unsafe impl<T: TypedArrayElement> Traceable for TypedArray<T, Box<Heap<*mut JSObject>>> {
10 unsafe fn trace(&self, trc: *mut JSTracer) {
11 self.underlying_object().trace(trc);
12 }
13}
14
15unsafe impl Traceable for Runtime {
16 #[inline]
17 unsafe fn trace(&self, _: *mut JSTracer) {}
18}
19
20unsafe impl Traceable for Stencil {
21 #[inline]
22 unsafe fn trace(&self, _: *mut JSTracer) {}
23}
24
25pub struct RootedTraceableSet {
27 set: Vec<*const dyn Traceable>,
28}
29
30thread_local!(
31 static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> = RefCell::new(RootedTraceableSet::new())
32);
33
34impl RootedTraceableSet {
35 fn new() -> RootedTraceableSet {
36 RootedTraceableSet { set: Vec::new() }
37 }
38
39 pub unsafe fn add(traceable: *const dyn Traceable) {
40 ROOTED_TRACEABLES.with(|traceables| {
41 traceables.borrow_mut().set.push(traceable);
42 });
43 }
44
45 pub unsafe fn remove(traceable: *const dyn Traceable) {
46 ROOTED_TRACEABLES.with(|traceables| {
47 let mut traceables = traceables.borrow_mut();
48 let idx = match traceables
49 .set
50 .iter()
51 .rposition(|x| *x as *const () == traceable as *const ())
52 {
53 Some(idx) => idx,
54 None => return,
55 };
56 traceables.set.remove(idx);
57 });
58 }
59
60 pub(crate) unsafe fn trace(&self, trc: *mut JSTracer) {
61 for traceable in &self.set {
62 (**traceable).trace(trc);
63 }
64 }
65}
66
67pub unsafe extern "C" fn trace_traceables(trc: *mut JSTracer, _: *mut c_void) {
68 ROOTED_TRACEABLES.with(|traceables| {
69 traceables.borrow().trace(trc);
70 });
71}