1use crate::glue::{
6 CallBigIntTracer, CallFunctionTracer, CallIdTracer, CallObjectTracer,
7 CallPropertyDescriptorTracer, CallScriptTracer, CallStringTracer, CallSymbolTracer,
8 CallValueRootTracer, CallValueTracer,
9};
10use crate::jsapi::js::TraceValueArray;
11use crate::jsapi::JS::{PropertyDescriptor, Value};
12use crate::jsapi::{jsid, JSFunction, JSObject, JSScript, JSString, JSTracer};
13
14use crate::jsapi::JS::{BigInt, JobQueue, Symbol};
15use crate::jsgc::{Heap, ValueArray};
16use std::any::TypeId;
17use std::borrow::Cow;
18use std::cell::{Cell, RefCell, UnsafeCell};
19use std::collections::btree_map::BTreeMap;
20use std::collections::btree_set::BTreeSet;
21use std::collections::vec_deque::VecDeque;
22use std::collections::{HashMap, HashSet};
23use std::hash::{BuildHasher, Hash};
24use std::num::{
25 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
26 NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
27};
28use std::ops::Range;
29use std::path::PathBuf;
30use std::rc::Rc;
31use std::sync::atomic::{
32 AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
33 AtomicU64, AtomicU8, AtomicUsize,
34};
35use std::thread::JoinHandle;
36use std::time::{Duration, Instant, SystemTime};
37
38pub unsafe trait Traceable {
43 unsafe fn trace(&self, trc: *mut JSTracer);
45}
46
47unsafe impl Traceable for Heap<*mut JSFunction> {
48 #[inline]
49 unsafe fn trace(&self, trc: *mut JSTracer) {
50 if self.get().is_null() {
51 return;
52 }
53 CallFunctionTracer(trc, self as *const _ as *mut Self, c"function".as_ptr());
54 }
55}
56
57unsafe impl Traceable for Heap<*mut JSObject> {
58 #[inline]
59 unsafe fn trace(&self, trc: *mut JSTracer) {
60 if self.get().is_null() {
61 return;
62 }
63 CallObjectTracer(trc, self as *const _ as *mut Self, c"object".as_ptr());
64 }
65}
66
67unsafe impl Traceable for Heap<*mut Symbol> {
68 unsafe fn trace(&self, trc: *mut JSTracer) {
69 if self.get().is_null() {
70 return;
71 }
72 CallSymbolTracer(trc, self as *const _ as *mut Self, c"symbol".as_ptr());
73 }
74}
75
76unsafe impl Traceable for Heap<*mut BigInt> {
77 unsafe fn trace(&self, trc: *mut JSTracer) {
78 if self.get().is_null() {
79 return;
80 }
81 CallBigIntTracer(trc, self as *const _ as *mut Self, c"bigint".as_ptr());
82 }
83}
84
85unsafe impl Traceable for Heap<*mut JSScript> {
86 #[inline]
87 unsafe fn trace(&self, trc: *mut JSTracer) {
88 if self.get().is_null() {
89 return;
90 }
91 CallScriptTracer(trc, self as *const _ as *mut Self, c"script".as_ptr());
92 }
93}
94
95unsafe impl Traceable for Heap<*mut JSString> {
96 #[inline]
97 unsafe fn trace(&self, trc: *mut JSTracer) {
98 if self.get().is_null() {
99 return;
100 }
101 CallStringTracer(trc, self as *const _ as *mut Self, c"string".as_ptr());
102 }
103}
104
105unsafe impl Traceable for Heap<Value> {
106 #[inline]
107 unsafe fn trace(&self, trc: *mut JSTracer) {
108 CallValueTracer(trc, self as *const _ as *mut Self, c"value".as_ptr());
109 }
110}
111
112unsafe impl Traceable for Value {
113 #[inline]
114 unsafe fn trace(&self, trc: *mut JSTracer) {
115 CallValueRootTracer(trc, self as *const _ as *mut Self, c"value".as_ptr());
116 }
117}
118
119unsafe impl Traceable for Heap<jsid> {
120 #[inline]
121 unsafe fn trace(&self, trc: *mut JSTracer) {
122 CallIdTracer(trc, self as *const _ as *mut Self, c"id".as_ptr());
123 }
124}
125
126unsafe impl Traceable for PropertyDescriptor {
127 #[inline]
128 unsafe fn trace(&self, trc: *mut JSTracer) {
129 CallPropertyDescriptorTracer(trc, self as *const _ as *mut _);
130 }
131}
132
133unsafe impl<T: Traceable> Traceable for Rc<T> {
134 #[inline]
135 unsafe fn trace(&self, trc: *mut JSTracer) {
136 (**self).trace(trc);
137 }
138}
139
140unsafe impl<T: Traceable + ?Sized> Traceable for Box<T> {
141 #[inline]
142 unsafe fn trace(&self, trc: *mut JSTracer) {
143 (**self).trace(trc);
144 }
145}
146
147unsafe impl<T: Traceable + Copy> Traceable for Cell<T> {
148 #[inline]
149 unsafe fn trace(&self, trc: *mut JSTracer) {
150 self.get().trace(trc);
151 }
152}
153
154unsafe impl<T: Traceable> Traceable for UnsafeCell<T> {
155 #[inline]
156 unsafe fn trace(&self, trc: *mut JSTracer) {
157 (*self.get()).trace(trc);
158 }
159}
160
161unsafe impl<T: Traceable> Traceable for RefCell<T> {
162 #[inline]
163 unsafe fn trace(&self, trc: *mut JSTracer) {
164 (*self).borrow().trace(trc);
165 }
166}
167
168unsafe impl<T: Traceable> Traceable for Option<T> {
169 #[inline]
170 unsafe fn trace(&self, trc: *mut JSTracer) {
171 self.as_ref().map(|t| t.trace(trc));
172 }
173}
174
175unsafe impl<T: Traceable, E: Traceable> Traceable for Result<T, E> {
176 #[inline]
177 unsafe fn trace(&self, trc: *mut JSTracer) {
178 match self {
179 Ok(t) => t.trace(trc),
180 Err(e) => e.trace(trc),
181 }
182 }
183}
184
185unsafe impl<T: Traceable> Traceable for [T] {
186 #[inline]
187 unsafe fn trace(&self, trc: *mut JSTracer) {
188 for t in self.iter() {
189 t.trace(trc);
190 }
191 }
192}
193
194unsafe impl<T: Traceable, const COUNT: usize> Traceable for [T; COUNT] {
196 #[inline]
197 unsafe fn trace(&self, tracer: *mut JSTracer) {
198 for v in self.iter() {
199 v.trace(tracer);
200 }
201 }
202}
203
204unsafe impl<const N: usize> Traceable for ValueArray<N> {
205 #[inline]
206 unsafe fn trace(&self, tracer: *mut JSTracer) {
207 TraceValueArray(tracer, N, self.get_mut_ptr());
208 }
209}
210
211unsafe impl<T: Traceable> Traceable for Vec<T> {
214 #[inline]
215 unsafe fn trace(&self, trc: *mut JSTracer) {
216 for t in &*self {
217 t.trace(trc);
218 }
219 }
220}
221
222unsafe impl<T: Traceable> Traceable for VecDeque<T> {
223 #[inline]
224 unsafe fn trace(&self, trc: *mut JSTracer) {
225 for t in &*self {
226 t.trace(trc);
227 }
228 }
229}
230
231unsafe impl<K: Traceable + Eq + Hash, V: Traceable, S: BuildHasher> Traceable for HashMap<K, V, S> {
232 #[inline]
233 unsafe fn trace(&self, trc: *mut JSTracer) {
234 for (k, v) in &*self {
235 k.trace(trc);
236 v.trace(trc);
237 }
238 }
239}
240
241unsafe impl<T: Traceable + Eq + Hash, S: BuildHasher> Traceable for HashSet<T, S> {
242 #[inline]
243 unsafe fn trace(&self, trc: *mut JSTracer) {
244 for t in &*self {
245 t.trace(trc);
246 }
247 }
248}
249
250unsafe impl<K: Traceable + Eq + Hash, V: Traceable> Traceable for BTreeMap<K, V> {
251 #[inline]
252 unsafe fn trace(&self, trc: *mut JSTracer) {
253 for (k, v) in &*self {
254 k.trace(trc);
255 v.trace(trc);
256 }
257 }
258}
259
260unsafe impl<T: Traceable> Traceable for BTreeSet<T> {
261 #[inline]
262 unsafe fn trace(&self, trc: *mut JSTracer) {
263 for t in &*self {
264 t.trace(trc);
265 }
266 }
267}
268
269macro_rules! impl_traceable_tuple {
270 () => {
271 unsafe impl Traceable for () {
272 #[inline]
273 unsafe fn trace(&self, _: *mut JSTracer) {}
274 }
275 };
276 ($($name:ident)+) => {
277 unsafe impl<$($name: Traceable,)+> Traceable for ($($name,)+) {
278 #[allow(non_snake_case)]
279 #[inline]
280 unsafe fn trace(&self, trc: *mut JSTracer) {
281 let ($(ref $name,)+) = *self;
282 $($name.trace(trc);)+
283 }
284 }
285 };
286}
287
288impl_traceable_tuple! {}
289impl_traceable_tuple! { A }
290impl_traceable_tuple! { A B }
291impl_traceable_tuple! { A B C }
292impl_traceable_tuple! { A B C D }
293impl_traceable_tuple! { A B C D E }
294impl_traceable_tuple! { A B C D E F }
295impl_traceable_tuple! { A B C D E F G }
296impl_traceable_tuple! { A B C D E F G H }
297impl_traceable_tuple! { A B C D E F G H I }
298impl_traceable_tuple! { A B C D E F G H I J }
299impl_traceable_tuple! { A B C D E F G H I J K }
300impl_traceable_tuple! { A B C D E F G H I J K L }
301
302macro_rules! impl_traceable_fnptr {
303 () => {
304 unsafe impl<Ret> Traceable for fn() -> Ret {
305 #[inline]
306 unsafe fn trace(&self, _: *mut JSTracer) {}
307 }
308 unsafe impl<Ret> Traceable for unsafe fn() -> Ret {
309 #[inline]
310 unsafe fn trace(&self, _: *mut JSTracer) {}
311 }
312 unsafe impl<Ret> Traceable for extern "C" fn() -> Ret {
313 #[inline]
314 unsafe fn trace(&self, _: *mut JSTracer) {}
315 }
316 unsafe impl<Ret> Traceable for unsafe extern "C" fn() -> Ret {
317 #[inline]
318 unsafe fn trace(&self, _: *mut JSTracer) {}
319 }
320 };
321 ($($arg:ident)+) => {
322 unsafe impl<Ret, $($arg,)+> Traceable for fn($($arg,)+) -> Ret {
323 #[inline]
324 unsafe fn trace(&self, _: *mut JSTracer) {}
325 }
326 unsafe impl<Ret, $($arg,)+> Traceable for unsafe fn($($arg,)+) -> Ret {
327 #[inline]
328 unsafe fn trace(&self, _: *mut JSTracer) {}
329 }
330 unsafe impl<Ret, $($arg,)+> Traceable for extern "C" fn($($arg,)+) -> Ret {
331 #[inline]
332 unsafe fn trace(&self, _: *mut JSTracer) {}
333 }
334 unsafe impl<Ret, $($arg,)+> Traceable for unsafe extern "C" fn($($arg,)+) -> Ret {
335 #[inline]
336 unsafe fn trace(&self, _: *mut JSTracer) {}
337 }
338 unsafe impl<Ret, $($arg,)+> Traceable for extern "C" fn($($arg),+, ...) -> Ret {
339 #[inline]
340 unsafe fn trace(&self, _: *mut JSTracer) {}
341 }
342 unsafe impl<Ret, $($arg,)+> Traceable for unsafe extern "C" fn($($arg),+, ...) -> Ret {
343 #[inline]
344 unsafe fn trace(&self, _: *mut JSTracer) {}
345 }
346 }
347}
348
349impl_traceable_fnptr! {}
350impl_traceable_fnptr! { A }
351impl_traceable_fnptr! { A B }
352impl_traceable_fnptr! { A B C }
353impl_traceable_fnptr! { A B C D }
354impl_traceable_fnptr! { A B C D E }
355impl_traceable_fnptr! { A B C D E F }
356impl_traceable_fnptr! { A B C D E F G }
357impl_traceable_fnptr! { A B C D E F G H }
358impl_traceable_fnptr! { A B C D E F G H I }
359impl_traceable_fnptr! { A B C D E F G H I J }
360impl_traceable_fnptr! { A B C D E F G H I J K }
361impl_traceable_fnptr! { A B C D E F G H I J K L }
362
363macro_rules! impl_traceable_simple {
365 ($($ty:ty $(,)?)+) => {
366 $(
367 unsafe impl Traceable for $ty {
368 #[inline]
369 unsafe fn trace(&self, _: *mut JSTracer) {}
370 }
371 )+
372 }
373}
374
375impl_traceable_simple!(bool);
376impl_traceable_simple!(i8, i16, i32, i64, isize);
377impl_traceable_simple!(u8, u16, u32, u64, usize);
378impl_traceable_simple!(f32, f64);
379impl_traceable_simple!(char, String);
380impl_traceable_simple!(
381 NonZeroI128,
382 NonZeroI16,
383 NonZeroI32,
384 NonZeroI64,
385 NonZeroI8,
386 NonZeroIsize
387);
388impl_traceable_simple!(
389 NonZeroU128,
390 NonZeroU16,
391 NonZeroU32,
392 NonZeroU64,
393 NonZeroU8,
394 NonZeroUsize
395);
396impl_traceable_simple!(AtomicBool);
397impl_traceable_simple!(AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize);
398impl_traceable_simple!(AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize);
399impl_traceable_simple!(Cow<'static, str>);
400impl_traceable_simple!(TypeId);
401impl_traceable_simple!(Duration, Instant, SystemTime);
402impl_traceable_simple!(PathBuf);
403impl_traceable_simple!(Range<u64>);
404impl_traceable_simple!(JoinHandle<()>);
405impl_traceable_simple!(*mut JobQueue);
406
407unsafe impl<'a> Traceable for &'a str {
408 #[inline]
409 unsafe fn trace(&self, _: *mut JSTracer) {}
410}