aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/root.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/root.rs')
-rw-r--r--components/script/dom/bindings/root.rs75
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]