script/dom/bindings/
root.rs1use std::cell::OnceCell;
28use std::default::Default;
29use std::hash::{Hash, Hasher};
30use std::mem;
31
32use js::jsapi::{Heap, JSObject, JSTracer, Value};
33use js::rust::HandleValue;
34use layout_api::TrustedNodeAddress;
35use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
36use script_bindings::assert::{assert_in_layout, assert_in_script};
37pub(crate) use script_bindings::dom::*;
38use script_bindings::reflector::DomObject;
39pub(crate) use script_bindings::root::*;
40
41use crate::dom::bindings::conversions::DerivedFrom;
42use crate::dom::bindings::inheritance::Castable;
43use crate::dom::bindings::trace::JSTraceable;
44use crate::dom::node::Node;
45
46#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]
49#[repr(transparent)]
50pub struct LayoutDom<'dom, T> {
51 value: &'dom T,
52}
53
54impl LayoutDom<'_, Node> {
55 pub(crate) unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> Self {
58 assert_in_layout();
59 let TrustedNodeAddress(addr) = inner;
60 LayoutDom {
61 value: unsafe { &*(addr as *const Node) },
62 }
63 }
64}
65
66unsafe impl<'dom, T: DomObject> LayoutFromRaw<'dom, T> for LayoutDom<'dom, T> {
67 fn from_raw(d: &'dom T) -> Self {
68 LayoutDom { value: d }
69 }
70}
71
72impl<'dom, T> LayoutDom<'dom, T>
73where
74 T: 'dom + DomObject,
75{
76 pub fn unsafe_get(self) -> &'dom T {
79 assert_in_layout();
80 self.value
81 }
82
83 pub(crate) unsafe fn to_layout_slice(slice: &'dom [Dom<T>]) -> &'dom [LayoutDom<'dom, T>] {
86 let _ = mem::transmute::<Dom<T>, LayoutDom<T>>;
89 unsafe { &*(slice as *const [Dom<T>] as *const [LayoutDom<T>]) }
90 }
91}
92
93impl<'dom, T> LayoutDom<'dom, T>
94where
95 T: Castable,
96{
97 pub(crate) fn upcast<U>(&self) -> LayoutDom<'dom, U>
99 where
100 U: Castable,
101 T: DerivedFrom<U>,
102 {
103 assert_in_layout();
104 LayoutDom {
105 value: self.value.upcast::<U>(),
106 }
107 }
108
109 pub(crate) fn downcast<U>(&self) -> Option<LayoutDom<'dom, U>>
111 where
112 U: DerivedFrom<T>,
113 {
114 assert_in_layout();
115 self.value.downcast::<U>().map(|value| LayoutDom { value })
116 }
117
118 pub(crate) fn is<U>(&self) -> bool
120 where
121 U: DerivedFrom<T>,
122 {
123 assert_in_layout();
124 self.value.is::<U>()
125 }
126
127 pub(crate) unsafe fn as_ref(self) -> &'dom T {
133 self.value
134 }
135}
136
137impl<T> LayoutDom<'_, T>
138where
139 T: DomObject,
140{
141 pub(crate) unsafe fn get_jsobject(&self) -> *mut JSObject {
143 assert_in_layout();
144 self.value.reflector().get_jsobject().get()
145 }
146}
147
148impl<T> Copy for LayoutDom<'_, T> {}
149
150impl<T> PartialEq for LayoutDom<'_, T> {
151 fn eq(&self, other: &Self) -> bool {
152 std::ptr::eq(self.value, other.value)
153 }
154}
155
156impl<T> Eq for LayoutDom<'_, T> {}
157
158impl<T> Hash for LayoutDom<'_, T> {
159 fn hash<H: Hasher>(&self, state: &mut H) {
160 (self.value as *const T).hash(state)
161 }
162}
163
164#[expect(clippy::non_canonical_clone_impl)]
165impl<T> Clone for LayoutDom<'_, T> {
166 #[inline]
167 fn clone(&self) -> Self {
168 assert_in_layout();
169 *self
170 }
171}
172
173#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
180pub(crate) struct DomOnceCell<T: DomObject> {
181 ptr: OnceCell<Dom<T>>,
182}
183
184impl<T> DomOnceCell<T>
185where
186 T: DomObject,
187{
188 pub(crate) fn init_once<F>(&self, cb: F) -> &T
191 where
192 F: FnOnce() -> DomRoot<T>,
193 {
194 assert_in_script();
195 self.ptr.get_or_init(|| Dom::from_ref(&cb()))
196 }
197}
198
199impl<T: DomObject> Default for DomOnceCell<T> {
200 fn default() -> DomOnceCell<T> {
201 assert_in_script();
202 DomOnceCell {
203 ptr: OnceCell::new(),
204 }
205 }
206}
207
208impl<T: DomObject> MallocSizeOf for DomOnceCell<T> {
209 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
210 0
212 }
213}
214
215unsafe impl<T: DomObject> JSTraceable for DomOnceCell<T> {
216 unsafe fn trace(&self, trc: *mut JSTracer) {
217 if let Some(ptr) = self.ptr.get() {
218 unsafe { ptr.trace(trc) };
219 }
220 }
221}
222
223pub trait AsHandleValue<'a> {
229 fn as_handle_value(&'a self) -> HandleValue<'a>;
230}
231
232impl<'a> AsHandleValue<'a> for Heap<Value> {
233 #[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
234 fn as_handle_value(&'a self) -> HandleValue<'a> {
235 unsafe { HandleValue::from_marked_location(self.ptr.get() as *const _) }
238 }
239}