diff --git a/components/script/dom/bindings/DESIGN.md b/components/script/dom/bindings/DESIGN.md index e47d7467609..b97bac77e68 100644 --- a/components/script/dom/bindings/DESIGN.md +++ b/components/script/dom/bindings/DESIGN.md @@ -33,8 +33,9 @@ In the `_finalize()` function the pointer of the Rusty DOM object that is contai For supporting SpiderMonkey’s exact GC rooting, we introduce [some types](https://github.com/mozilla/servo/wiki/Using-DOM-types): - `JS` is used for the DOM typed field in a DOM type structure. The GC can trace them recursively while the enclosing DOM object (maybe root) is alive. + - `LayoutJS` is specialized `JS` to use in layout. `Layout*Helper` must be implemented on this type to prevent calling methods from non layout code. - `Temporary` is used as a return value for functions returning a DOM type. They are rooted for the duration of their lifetime. But a retun value gets moved around which can break the LIFO ordering constraint. Thus we need to introduce `Root`. - `Root` contains the pointer to `JSObject` which the represented DOM type has. SpiderMonkey's conservative stack scanner scans it's pointers and marks a pointed `JSObject` as GC root. - `JSRef` is just a reference to the value rooted by `Root`. - `RootCollection` is used to dynamically check if rooting satisfies LIFO ordering, because SpiderMonkey's GC requires LIFO order (See also: [Exact Stack Rooting - Storing a GCPointer on the CStack](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting)). - - `MutHeap` is a version of `Cell` that is safe to use for internal mutability of Spidermonkey heap objects like `JSVal` and `JS` \ No newline at end of file + - `MutHeap` is a version of `Cell` that is safe to use for internal mutability of Spidermonkey heap objects like `JSVal` and `JS` diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 3c9eba38911..2e229a28df3 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -129,8 +129,25 @@ pub struct JS { ptr: NonZero<*const T> } +impl JS { + /// Returns `LayoutJS` containing the same pointer. + fn to_layout(self) -> LayoutJS { + LayoutJS { + ptr: self.ptr.clone() + } + } +} + +/// This is specialized `JS` to use in under `layout` crate. +/// `Layout*Helpers` traits must be implemented on this. +pub struct LayoutJS { + ptr: NonZero<*const T> +} + impl Copy for JS {} +impl Copy for LayoutJS {} + impl PartialEq for JS { #[allow(unrooted_must_root)] fn eq(&self, other: &JS) -> bool { @@ -138,6 +155,13 @@ impl PartialEq for JS { } } +impl PartialEq for LayoutJS { + #[allow(unrooted_must_root)] + fn eq(&self, other: &LayoutJS) -> bool { + self.ptr == other.ptr + } +} + impl Clone for JS { #[inline] fn clone(&self) -> JS { @@ -147,6 +171,15 @@ impl Clone for JS { } } +impl Clone for LayoutJS { + #[inline] + fn clone(&self) -> LayoutJS { + LayoutJS { + ptr: self.ptr.clone() + } + } +} + impl JS { /// Create a new JS-owned value wrapped from an address known to be a `Node` pointer. pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS { @@ -198,6 +231,15 @@ impl Reflectable for JS { } } +// XXXjdm same above +impl Reflectable for LayoutJS { + fn reflector<'a>(&'a self) -> &'a Reflector { + unsafe { + (*self.unsafe_get()).reflector() + } + } +} + /// A trait to be implemented for JS-managed types that can be stored in /// mutable member fields. /// @@ -296,6 +338,12 @@ impl MutNullableJS { self.ptr.get() } + /// Retrieve a copy of the inner optional `JS` as `LayoutJS`. + /// For use by layout, which can't use safe types like Temporary. + pub unsafe fn get_inner_as_layout(&self) -> Option> { + self.get_inner().map(|js| js.to_layout()) + } + /// Retrieve a copy of the current inner value. If it is `None`, it is /// initialized with the result of `cb` first. pub fn or_init(&self, cb: F) -> Temporary @@ -313,9 +361,8 @@ impl MutNullableJS { } impl JS { - /// Returns an unsafe pointer to the interior of this object. This is the - /// only method that be safely accessed from layout. (The fact that this is - /// unsafe is what necessitates the layout wrappers.) + /// Returns an unsafe pointer to the interior of this object. + /// This should only be used by the DOM bindings. pub unsafe fn unsafe_get(&self) -> *const T { *self.ptr } @@ -328,6 +375,15 @@ impl JS { } } +impl LayoutJS { + /// Returns an unsafe pointer to the interior of this JS object without touching the borrow + /// flags. This is the only method that be safely accessed from layout. (The fact that this + /// is unsafe is what necessitates the layout wrappers.) + pub unsafe fn unsafe_get(&self) -> *const T { + *self.ptr + } +} + impl JS { /// Return `self` as a `JS` of another type. //XXXjdm It would be lovely if this could be private. @@ -341,6 +397,12 @@ impl JS { } } +impl LayoutJS { + /// Return `self` as a `LayoutJS` of another type. + pub unsafe fn transmute_copy(&self) -> LayoutJS { + mem::transmute_copy(self) + } +} /// Get an `Option>` out of an `Option>` pub trait RootedReference {