diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 9523585785f..b9bdc48a3ea 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -32,7 +32,7 @@ use gfx::paint_task::{PaintChan, PaintLayer}; use gfx::paint_task::Msg as PaintMsg; use layout_traits::{LayoutControlMsg, LayoutTaskFactory}; use log; -use script::dom::bindings::js::JS; +use script::dom::bindings::js::{JS, LayoutJS}; use script::dom::node::{LayoutDataRef, Node, NodeTypeId}; use script::dom::element::ElementTypeId; use script::dom::htmlelement::HTMLElementTypeId; @@ -719,8 +719,8 @@ impl LayoutTask { // FIXME: Isolate this transmutation into a "bridge" module. // FIXME(rust#16366): The following line had to be moved because of a // rustc bug. It should be in the next unsafe block. - let mut node: JS = unsafe { - JS::from_trusted_node_address(data.document_root) + let mut node: LayoutJS = unsafe { + JS::from_trusted_node_address(data.document_root).to_layout() }; let node: &mut LayoutNode = unsafe { mem::transmute(&mut node) diff --git a/components/layout/util.rs b/components/layout/util.rs index e04bbfbbd7e..984c2c44657 100644 --- a/components/layout/util.rs +++ b/components/layout/util.rs @@ -10,7 +10,7 @@ use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode}; use gfx::display_list::OpaqueNode; use gfx; use libc::uintptr_t; -use script::dom::bindings::js::JS; +use script::dom::bindings::js::{JS, LayoutJS}; use script::dom::bindings::utils::Reflectable; use script::dom::node::{Node, SharedLayoutData}; use script::layout_interface::{LayoutChan, TrustedNodeAddress}; @@ -126,7 +126,7 @@ pub trait OpaqueNodeMethods { fn from_script_node(node: TrustedNodeAddress) -> Self; /// Converts a DOM node to an `OpaqueNode'. - fn from_jsmanaged(node: &JS) -> Self; + fn from_jsmanaged(node: &LayoutJS) -> Self; /// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type /// of node that script expects to receive in a hit test. @@ -150,11 +150,11 @@ impl OpaqueNodeMethods for OpaqueNode { fn from_script_node(node: TrustedNodeAddress) -> OpaqueNode { unsafe { - OpaqueNodeMethods::from_jsmanaged(&JS::from_trusted_node_address(node)) + OpaqueNodeMethods::from_jsmanaged(&JS::from_trusted_node_address(node).to_layout()) } } - fn from_jsmanaged(node: &JS) -> OpaqueNode { + fn from_jsmanaged(node: &LayoutJS) -> OpaqueNode { unsafe { let ptr: uintptr_t = mem::transmute(node.reflector().get_jsobject()); OpaqueNode(ptr) diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 039073e8795..e05f005c380 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -12,7 +12,7 @@ //! //! 1. Layout is not allowed to mutate the DOM. //! -//! 2. Layout is not allowed to see anything with `JS` in the name, because it could hang +//! 2. Layout is not allowed to see anything with `LayoutJS` in the name, because it could hang //! onto these objects and cause use-after-free. //! //! When implementing wrapper functions, be careful that you do not touch the borrow flags, or you @@ -43,7 +43,7 @@ use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElemen use script::dom::bindings::codegen::InheritTypes::{HTMLCanvasElementCast, HTMLImageElementCast}; use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLTextAreaElementCast}; use script::dom::bindings::codegen::InheritTypes::{NodeCast, TextCast}; -use script::dom::bindings::js::JS; +use script::dom::bindings::js::{JS, LayoutJS}; use script::dom::element::{Element, ElementTypeId}; use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers}; use script::dom::htmlelement::HTMLElementTypeId; @@ -75,15 +75,15 @@ use url::Url; /// Allows some convenience methods on generic layout nodes. pub trait TLayoutNode { /// Creates a new layout node with the same lifetime as this layout node. - unsafe fn new_with_this_lifetime(&self, node: &JS) -> Self; + unsafe fn new_with_this_lifetime(&self, node: &LayoutJS) -> Self; /// Returns the type ID of this node. Fails if this node is borrowed mutably. Returns `None` /// if this is a pseudo-element; otherwise, returns `Some`. fn type_id(&self) -> Option; - /// Returns the interior of this node as a `JS`. This is highly unsafe for layout to + /// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to /// call and as such is marked `unsafe`. - unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS; + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS; /// Returns the interior of this node as a `Node`. This is highly unsafe for layout to call /// and as such is marked `unsafe`. @@ -110,8 +110,8 @@ pub trait TLayoutNode { /// FIXME(pcwalton): Don't copy URLs. fn image_url(&self) -> Option { unsafe { - match HTMLImageElementCast::to_js(self.get_jsmanaged()) { - Some(elem) => elem.image().as_ref().map(|url| (*url).clone()), + match HTMLImageElementCast::to_js(&self.get_jsmanaged().to_script()) { + Some(elem) => elem.to_layout().image().as_ref().map(|url| (*url).clone()), None => panic!("not an image!") } } @@ -119,22 +119,22 @@ pub trait TLayoutNode { fn get_renderer(&self) -> Option> { unsafe { - let canvas_element: Option> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); - canvas_element.and_then(|elem| elem.get_renderer()) + let canvas_element: Option> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script()); + canvas_element.and_then(|elem| elem.to_layout().get_renderer()) } } fn get_canvas_width(&self) -> u32 { unsafe { - let canvas_element: Option> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); - canvas_element.unwrap().get_canvas_width() + let canvas_element: Option> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script()); + canvas_element.unwrap().to_layout().get_canvas_width() } } fn get_canvas_height(&self) -> u32 { unsafe { - let canvas_element: Option> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); - canvas_element.unwrap().get_canvas_height() + let canvas_element: Option> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script()); + canvas_element.unwrap().to_layout().get_canvas_height() } } @@ -143,7 +143,7 @@ pub trait TLayoutNode { fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) { unsafe { let iframe_element: JS = - match HTMLIFrameElementCast::to_js(self.get_jsmanaged()) { + match HTMLIFrameElementCast::to_js(&self.get_jsmanaged().to_script()) { Some(elem) => elem, None => panic!("not an iframe element!") }; @@ -162,11 +162,11 @@ pub trait TLayoutNode { } /// A wrapper so that layout can access only the methods that it should have access to. Layout must -/// only ever see these and must never see instances of `JS`. +/// only ever see these and must never see instances of `LayoutJS`. #[derive(Copy)] pub struct LayoutNode<'a> { /// The wrapped node. - node: JS, + node: LayoutJS, /// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping. pub chain: ContravariantLifetime<'a>, @@ -189,7 +189,7 @@ impl<'a> PartialEq for LayoutNode<'a> { } impl<'ln> TLayoutNode for LayoutNode<'ln> { - unsafe fn new_with_this_lifetime(&self, node: &JS) -> LayoutNode<'ln> { + unsafe fn new_with_this_lifetime(&self, node: &LayoutJS) -> LayoutNode<'ln> { LayoutNode { node: node.transmute_copy(), chain: self.chain, @@ -202,7 +202,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { } } - unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS { + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS { &self.node } @@ -214,15 +214,15 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> { fn text(&self) -> String { unsafe { - let text: Option> = TextCast::to_js(self.get_jsmanaged()); + let text: Option> = TextCast::to_js(&self.get_jsmanaged().to_script()); if let Some(text) = text { return (*text.unsafe_get()).characterdata().data_for_layout().to_owned(); } - let input: Option> = HTMLInputElementCast::to_js(self.get_jsmanaged()); + let input: Option> = HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script()); if let Some(input) = input { return input.get_value_for_layout(); } - let area: Option> = HTMLTextAreaElementCast::to_js(self.get_jsmanaged()); + let area: Option> = HTMLTextAreaElementCast::to_js(&self.get_jsmanaged().to_script()); if let Some(area) = area { return area.get_value_for_layout(); } @@ -294,7 +294,7 @@ impl<'ln> LayoutNode<'ln> { } - pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS { + pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS { &self.node } @@ -371,8 +371,8 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> { #[inline] fn as_element(self) -> LayoutElement<'ln> { unsafe { - let elem: JS = match ElementCast::to_js(&self.node) { - Some(elem) => elem, + let elem: LayoutJS = match ElementCast::to_js(&self.node.to_script()) { + Some(elem) => elem.to_layout(), None => panic!("not an element") }; @@ -411,8 +411,8 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> { fn is_html_element_in_html_document(self) -> bool { unsafe { - match ElementCast::to_js(&self.node) { - Some(elem) => elem.html_element_in_html_document_for_layout(), + match ElementCast::to_js(&self.node.to_script()) { + Some(elem) => elem.to_layout().html_element_in_html_document_for_layout(), None => false } } @@ -707,7 +707,7 @@ pub struct ThreadSafeLayoutNode<'ln> { impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { /// Creates a new layout node with the same lifetime as this layout node. - unsafe fn new_with_this_lifetime(&self, node: &JS) -> ThreadSafeLayoutNode<'ln> { + unsafe fn new_with_this_lifetime(&self, node: &LayoutJS) -> ThreadSafeLayoutNode<'ln> { ThreadSafeLayoutNode { node: LayoutNode { node: node.transmute_copy(), @@ -726,7 +726,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { self.node.type_id() } - unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS { + unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS { self.node.get_jsmanaged() } @@ -824,7 +824,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { #[inline] pub fn as_element(&self) -> ThreadSafeLayoutElement<'ln> { unsafe { - let element = match ElementCast::to_js(self.get_jsmanaged()) { + let element = match ElementCast::to_js(&self.get_jsmanaged().to_script()) { Some(e) => e.unsafe_get(), None => panic!("not an element") }; @@ -936,7 +936,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { pub fn is_ignorable_whitespace(&self) -> bool { unsafe { - let text: JS = match TextCast::to_js(self.get_jsmanaged()) { + let text: JS = match TextCast::to_js(&self.get_jsmanaged().to_script()) { Some(text) => text, None => return false }; @@ -960,9 +960,9 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { pub fn get_input_value(&self) -> String { unsafe { - let input: Option> = HTMLInputElementCast::to_js(self.get_jsmanaged()); + let input: Option> = HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script()); match input { - Some(input) => input.get_value_for_layout(), + Some(input) => input.to_layout().get_value_for_layout(), None => panic!("not an input element!") } } @@ -970,8 +970,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { pub fn get_input_size(&self) -> u32 { unsafe { - match HTMLInputElementCast::to_js(self.get_jsmanaged()) { - Some(input) => input.get_size_for_layout(), + match HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script()) { + Some(input) => input.to_layout().get_size_for_layout(), None => panic!("not an input element!") } } @@ -980,7 +980,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> { pub fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute) -> Option { unsafe { - let elem: Option> = ElementCast::to_js(self.get_jsmanaged()); + let elem: Option> = ElementCast::to_js(&self.get_jsmanaged().to_script()); match elem { Some(element) => { (*element.unsafe_get()).get_unsigned_integer_attribute_for_layout(attribute) diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 2e229a28df3..f2d00c6d76f 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -144,6 +144,14 @@ pub struct LayoutJS { ptr: NonZero<*const T> } +impl LayoutJS { + pub fn to_script(self) -> JS { + JS { + ptr: self.ptr + } + } +} + impl Copy for JS {} impl Copy for LayoutJS {}