script_bindings/
weakref.rs1use std::hash::{Hash, Hasher};
15use std::rc::{Rc, Weak};
16use std::{mem, ptr};
17
18use js::jsapi::JSTracer;
19use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
20
21use crate::JSTraceable;
22use crate::reflector::DomObject;
23use crate::root::DomRoot;
24
25#[derive(Clone)]
27#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
28pub struct WeakRef<T: WeakReferenceable>(Weak<T>);
29
30pub trait WeakReferenceable: DomObject + Sized {
32 fn downgrade(&self) -> WeakRef<Self> {
34 let rc = unsafe { Rc::from_raw(self as *const Self) };
35 let weak = WeakRef(Rc::downgrade(&rc));
36 mem::forget(rc);
37 weak
38 }
39}
40
41impl<T: WeakReferenceable> Eq for WeakRef<T> {}
42
43impl<T: WeakReferenceable> Hash for WeakRef<T> {
44 fn hash<H: Hasher>(&self, state: &mut H) {
45 self.0.as_ptr().hash(state);
46 }
47}
48
49impl<T: WeakReferenceable> WeakRef<T> {
50 pub fn new(value: &T) -> Self {
54 value.downgrade()
55 }
56
57 pub fn root(&self) -> Option<DomRoot<T>> {
59 self.0.upgrade().map(|x| DomRoot::from_ref(&*x))
60 }
61
62 pub fn is_alive(&self) -> bool {
64 self.0.strong_count() > 0
65 }
66}
67
68impl<T: WeakReferenceable> MallocSizeOf for WeakRef<T> {
69 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
70 0
71 }
72}
73
74impl<T: WeakReferenceable> PartialEq for WeakRef<T> {
75 fn eq(&self, other: &Self) -> bool {
76 self.0.ptr_eq(&other.0)
77 }
78}
79
80impl<T: WeakReferenceable> PartialEq<T> for WeakRef<T> {
81 fn eq(&self, other: &T) -> bool {
82 match self.0.upgrade() {
83 Some(ptr) => ptr::eq(Rc::as_ptr(&ptr), other),
84 None => false,
85 }
86 }
87}
88
89unsafe impl<T: WeakReferenceable> JSTraceable for WeakRef<T> {
90 unsafe fn trace(&self, _: *mut JSTracer) {
91 }
93}