diff options
Diffstat (limited to 'components/script/dom/bindings/root.rs')
-rw-r--r-- | components/script/dom/bindings/root.rs | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs index 19df89df53f..0ba69687dba 100644 --- a/components/script/dom/bindings/root.rs +++ b/components/script/dom/bindings/root.rs @@ -26,7 +26,7 @@ use crate::dom::bindings::conversions::DerivedFrom; use crate::dom::bindings::inheritance::Castable; -use crate::dom::bindings::reflector::{DomObject, Reflector}; +use crate::dom::bindings::reflector::{DomObject, MutDomObject, Reflector}; use crate::dom::bindings::trace::trace_reflector; use crate::dom::bindings::trace::JSTraceable; use crate::dom::node::Node; @@ -62,7 +62,7 @@ where /// It cannot outlive its associated `RootCollection`, and it gives /// out references which cannot outlive this new `Root`. #[allow(unrooted_must_root)] - unsafe fn new(value: T) -> Self { + pub unsafe fn new(value: T) -> Self { debug_assert!(thread_state::get().is_script()); STACK_ROOTS.with(|ref root_list| { let root_list = &*root_list.get().unwrap(); @@ -99,6 +99,32 @@ where } } +unsafe impl<T> StableTraceObject for MaybeUnreflectedDom<T> +where + T: DomObject, +{ + fn stable_trace_object<'a>(&'a self) -> *const dyn JSTraceable { + // The JSTraceable impl for Reflector doesn't actually do anything, + // so we need this shenanigan to actually trace the reflector of the + // T pointer in Dom<T>. + #[allow(unrooted_must_root)] + struct MaybeUnreflectedStackRoot<T>(T); + unsafe impl<T> JSTraceable for MaybeUnreflectedStackRoot<T> + where + T: DomObject, + { + unsafe fn trace(&self, tracer: *mut JSTracer) { + if self.0.reflector().get_jsobject().is_null() { + self.0.trace(tracer); + } else { + trace_reflector(tracer, "on stack", &self.0.reflector()); + } + } + } + unsafe { &*(self.ptr.as_ptr() as *const T as *const MaybeUnreflectedStackRoot<T>) } + } +} + impl<T> Deref for Root<T> where T: Deref + StableTraceObject, @@ -236,7 +262,10 @@ impl RootCollection { unsafe fn unroot(&self, object: *const dyn JSTraceable) { debug_assert!(thread_state::get().is_script()); let roots = &mut *self.roots.get(); - match roots.iter().rposition(|r| *r == object) { + match roots + .iter() + .rposition(|r| *r as *const () == object as *const ()) + { Some(idx) => { roots.remove(idx); }, @@ -341,6 +370,46 @@ unsafe impl<T: DomObject> JSTraceable for Dom<T> { } } +/// A traced reference to a DOM object that may not be reflected yet. +#[unrooted_must_root_lint::must_root] +pub struct MaybeUnreflectedDom<T> { + ptr: ptr::NonNull<T>, +} + +impl<T> MaybeUnreflectedDom<T> +where + T: DomObject, +{ + #[allow(unrooted_must_root)] + pub unsafe fn from_box(value: Box<T>) -> Self { + Self { + ptr: Box::into_raw_non_null(value), + } + } +} + +impl<T> Root<MaybeUnreflectedDom<T>> +where + T: DomObject, +{ + pub fn as_ptr(&self) -> *const T { + self.value.ptr.as_ptr() + } +} + +impl<T> Root<MaybeUnreflectedDom<T>> +where + T: MutDomObject, +{ + pub unsafe fn reflect_with(self, obj: *mut JSObject) -> DomRoot<T> { + let ptr = self.as_ptr(); + drop(self); + let root = DomRoot::from_ref(&*ptr); + root.init_reflector(obj); + root + } +} + /// An unrooted reference to a DOM object for use in layout. `Layout*Helpers` /// traits must be implemented on this. #[unrooted_must_root_lint::allow_unrooted_interior] |