Introduce a new type MaybeUnreflectedDom<T> (fixes #25701)

This commit is contained in:
Anthony Ramine 2020-02-17 10:17:47 +01:00
parent 3475790fc2
commit 14846d0567
8 changed files with 120 additions and 80 deletions

View file

@ -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,
@ -341,6 +367,36 @@ 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> Deref for MaybeUnreflectedDom<T>
where
T: DomObject,
{
type Target = T;
fn deref(&self) -> &T {
debug_assert!(thread_state::get().is_script());
unsafe { &*self.ptr.as_ptr() }
}
}
/// 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]