Use LayoutJS<T> in layout crate.

This commit is contained in:
Tetsuharu OHZEKI 2015-01-12 02:17:58 +09:00
parent e2bd9eadd8
commit 6b1e2bd11c
4 changed files with 50 additions and 42 deletions

View file

@ -32,7 +32,7 @@ use gfx::paint_task::{PaintChan, PaintLayer};
use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::Msg as PaintMsg;
use layout_traits::{LayoutControlMsg, LayoutTaskFactory}; use layout_traits::{LayoutControlMsg, LayoutTaskFactory};
use log; 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::node::{LayoutDataRef, Node, NodeTypeId};
use script::dom::element::ElementTypeId; use script::dom::element::ElementTypeId;
use script::dom::htmlelement::HTMLElementTypeId; use script::dom::htmlelement::HTMLElementTypeId;
@ -719,8 +719,8 @@ impl LayoutTask {
// FIXME: Isolate this transmutation into a "bridge" module. // FIXME: Isolate this transmutation into a "bridge" module.
// FIXME(rust#16366): The following line had to be moved because of a // FIXME(rust#16366): The following line had to be moved because of a
// rustc bug. It should be in the next unsafe block. // rustc bug. It should be in the next unsafe block.
let mut node: JS<Node> = unsafe { let mut node: LayoutJS<Node> = unsafe {
JS::from_trusted_node_address(data.document_root) JS::from_trusted_node_address(data.document_root).to_layout()
}; };
let node: &mut LayoutNode = unsafe { let node: &mut LayoutNode = unsafe {
mem::transmute(&mut node) mem::transmute(&mut node)

View file

@ -10,7 +10,7 @@ use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use gfx; use gfx;
use libc::uintptr_t; 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::bindings::utils::Reflectable;
use script::dom::node::{Node, SharedLayoutData}; use script::dom::node::{Node, SharedLayoutData};
use script::layout_interface::{LayoutChan, TrustedNodeAddress}; use script::layout_interface::{LayoutChan, TrustedNodeAddress};
@ -126,7 +126,7 @@ pub trait OpaqueNodeMethods {
fn from_script_node(node: TrustedNodeAddress) -> Self; fn from_script_node(node: TrustedNodeAddress) -> Self;
/// Converts a DOM node to an `OpaqueNode'. /// Converts a DOM node to an `OpaqueNode'.
fn from_jsmanaged(node: &JS<Node>) -> Self; fn from_jsmanaged(node: &LayoutJS<Node>) -> Self;
/// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type /// Converts this node to an `UntrustedNodeAddress`. An `UntrustedNodeAddress` is just the type
/// of node that script expects to receive in a hit test. /// 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 { fn from_script_node(node: TrustedNodeAddress) -> OpaqueNode {
unsafe { 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<Node>) -> OpaqueNode { fn from_jsmanaged(node: &LayoutJS<Node>) -> OpaqueNode {
unsafe { unsafe {
let ptr: uintptr_t = mem::transmute(node.reflector().get_jsobject()); let ptr: uintptr_t = mem::transmute(node.reflector().get_jsobject());
OpaqueNode(ptr) OpaqueNode(ptr)

View file

@ -12,7 +12,7 @@
//! //!
//! 1. Layout is not allowed to mutate the DOM. //! 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. //! onto these objects and cause use-after-free.
//! //!
//! When implementing wrapper functions, be careful that you do not touch the borrow flags, or you //! 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::{HTMLCanvasElementCast, HTMLImageElementCast};
use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLTextAreaElementCast}; use script::dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLTextAreaElementCast};
use script::dom::bindings::codegen::InheritTypes::{NodeCast, TextCast}; 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::{Element, ElementTypeId};
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers}; use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
use script::dom::htmlelement::HTMLElementTypeId; use script::dom::htmlelement::HTMLElementTypeId;
@ -75,15 +75,15 @@ use url::Url;
/// Allows some convenience methods on generic layout nodes. /// Allows some convenience methods on generic layout nodes.
pub trait TLayoutNode { pub trait TLayoutNode {
/// Creates a new layout node with the same lifetime as this layout node. /// Creates a new layout node with the same lifetime as this layout node.
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> Self; unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> Self;
/// Returns the type ID of this node. Fails if this node is borrowed mutably. Returns `None` /// 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`. /// if this is a pseudo-element; otherwise, returns `Some`.
fn type_id(&self) -> Option<NodeTypeId>; fn type_id(&self) -> Option<NodeTypeId>;
/// 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`. /// call and as such is marked `unsafe`.
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node>; unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node>;
/// Returns the interior of this node as a `Node`. This is highly unsafe for layout to call /// Returns the interior of this node as a `Node`. This is highly unsafe for layout to call
/// and as such is marked `unsafe`. /// and as such is marked `unsafe`.
@ -110,8 +110,8 @@ pub trait TLayoutNode {
/// FIXME(pcwalton): Don't copy URLs. /// FIXME(pcwalton): Don't copy URLs.
fn image_url(&self) -> Option<Url> { fn image_url(&self) -> Option<Url> {
unsafe { unsafe {
match HTMLImageElementCast::to_js(self.get_jsmanaged()) { match HTMLImageElementCast::to_js(&self.get_jsmanaged().to_script()) {
Some(elem) => elem.image().as_ref().map(|url| (*url).clone()), Some(elem) => elem.to_layout().image().as_ref().map(|url| (*url).clone()),
None => panic!("not an image!") None => panic!("not an image!")
} }
} }
@ -119,22 +119,22 @@ pub trait TLayoutNode {
fn get_renderer(&self) -> Option<Sender<CanvasMsg>> { fn get_renderer(&self) -> Option<Sender<CanvasMsg>> {
unsafe { unsafe {
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script());
canvas_element.and_then(|elem| elem.get_renderer()) canvas_element.and_then(|elem| elem.to_layout().get_renderer())
} }
} }
fn get_canvas_width(&self) -> u32 { fn get_canvas_width(&self) -> u32 {
unsafe { unsafe {
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script());
canvas_element.unwrap().get_canvas_width() canvas_element.unwrap().to_layout().get_canvas_width()
} }
} }
fn get_canvas_height(&self) -> u32 { fn get_canvas_height(&self) -> u32 {
unsafe { unsafe {
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged()); let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(&self.get_jsmanaged().to_script());
canvas_element.unwrap().get_canvas_height() canvas_element.unwrap().to_layout().get_canvas_height()
} }
} }
@ -143,7 +143,7 @@ pub trait TLayoutNode {
fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) { fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) {
unsafe { unsafe {
let iframe_element: JS<HTMLIFrameElement> = let iframe_element: JS<HTMLIFrameElement> =
match HTMLIFrameElementCast::to_js(self.get_jsmanaged()) { match HTMLIFrameElementCast::to_js(&self.get_jsmanaged().to_script()) {
Some(elem) => elem, Some(elem) => elem,
None => panic!("not an iframe element!") 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 /// 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)] #[derive(Copy)]
pub struct LayoutNode<'a> { pub struct LayoutNode<'a> {
/// The wrapped node. /// The wrapped node.
node: JS<Node>, node: LayoutJS<Node>,
/// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping. /// Being chained to a ContravariantLifetime prevents `LayoutNode`s from escaping.
pub chain: ContravariantLifetime<'a>, pub chain: ContravariantLifetime<'a>,
@ -189,7 +189,7 @@ impl<'a> PartialEq for LayoutNode<'a> {
} }
impl<'ln> TLayoutNode for LayoutNode<'ln> { impl<'ln> TLayoutNode for LayoutNode<'ln> {
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> LayoutNode<'ln> { unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> LayoutNode<'ln> {
LayoutNode { LayoutNode {
node: node.transmute_copy(), node: node.transmute_copy(),
chain: self.chain, chain: self.chain,
@ -202,7 +202,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
} }
} }
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
&self.node &self.node
} }
@ -214,15 +214,15 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
fn text(&self) -> String { fn text(&self) -> String {
unsafe { unsafe {
let text: Option<JS<Text>> = TextCast::to_js(self.get_jsmanaged()); let text: Option<JS<Text>> = TextCast::to_js(&self.get_jsmanaged().to_script());
if let Some(text) = text { if let Some(text) = text {
return (*text.unsafe_get()).characterdata().data_for_layout().to_owned(); return (*text.unsafe_get()).characterdata().data_for_layout().to_owned();
} }
let input: Option<JS<HTMLInputElement>> = HTMLInputElementCast::to_js(self.get_jsmanaged()); let input: Option<JS<HTMLInputElement>> = HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script());
if let Some(input) = input { if let Some(input) = input {
return input.get_value_for_layout(); return input.get_value_for_layout();
} }
let area: Option<JS<HTMLTextAreaElement>> = HTMLTextAreaElementCast::to_js(self.get_jsmanaged()); let area: Option<JS<HTMLTextAreaElement>> = HTMLTextAreaElementCast::to_js(&self.get_jsmanaged().to_script());
if let Some(area) = area { if let Some(area) = area {
return area.get_value_for_layout(); return area.get_value_for_layout();
} }
@ -294,7 +294,7 @@ impl<'ln> LayoutNode<'ln> {
} }
pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { pub unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
&self.node &self.node
} }
@ -371,8 +371,8 @@ impl<'ln> TNode<'ln, LayoutElement<'ln>> for LayoutNode<'ln> {
#[inline] #[inline]
fn as_element(self) -> LayoutElement<'ln> { fn as_element(self) -> LayoutElement<'ln> {
unsafe { unsafe {
let elem: JS<Element> = match ElementCast::to_js(&self.node) { let elem: LayoutJS<Element> = match ElementCast::to_js(&self.node.to_script()) {
Some(elem) => elem, Some(elem) => elem.to_layout(),
None => panic!("not an element") 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 { fn is_html_element_in_html_document(self) -> bool {
unsafe { unsafe {
match ElementCast::to_js(&self.node) { match ElementCast::to_js(&self.node.to_script()) {
Some(elem) => elem.html_element_in_html_document_for_layout(), Some(elem) => elem.to_layout().html_element_in_html_document_for_layout(),
None => false None => false
} }
} }
@ -707,7 +707,7 @@ pub struct ThreadSafeLayoutNode<'ln> {
impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> { impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
/// Creates a new layout node with the same lifetime as this layout node. /// Creates a new layout node with the same lifetime as this layout node.
unsafe fn new_with_this_lifetime(&self, node: &JS<Node>) -> ThreadSafeLayoutNode<'ln> { unsafe fn new_with_this_lifetime(&self, node: &LayoutJS<Node>) -> ThreadSafeLayoutNode<'ln> {
ThreadSafeLayoutNode { ThreadSafeLayoutNode {
node: LayoutNode { node: LayoutNode {
node: node.transmute_copy(), node: node.transmute_copy(),
@ -726,7 +726,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
self.node.type_id() self.node.type_id()
} }
unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> { unsafe fn get_jsmanaged<'a>(&'a self) -> &'a LayoutJS<Node> {
self.node.get_jsmanaged() self.node.get_jsmanaged()
} }
@ -824,7 +824,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
#[inline] #[inline]
pub fn as_element(&self) -> ThreadSafeLayoutElement<'ln> { pub fn as_element(&self) -> ThreadSafeLayoutElement<'ln> {
unsafe { 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(), Some(e) => e.unsafe_get(),
None => panic!("not an element") None => panic!("not an element")
}; };
@ -936,7 +936,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
pub fn is_ignorable_whitespace(&self) -> bool { pub fn is_ignorable_whitespace(&self) -> bool {
unsafe { unsafe {
let text: JS<Text> = match TextCast::to_js(self.get_jsmanaged()) { let text: JS<Text> = match TextCast::to_js(&self.get_jsmanaged().to_script()) {
Some(text) => text, Some(text) => text,
None => return false None => return false
}; };
@ -960,9 +960,9 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
pub fn get_input_value(&self) -> String { pub fn get_input_value(&self) -> String {
unsafe { unsafe {
let input: Option<JS<HTMLInputElement>> = HTMLInputElementCast::to_js(self.get_jsmanaged()); let input: Option<JS<HTMLInputElement>> = HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script());
match input { match input {
Some(input) => input.get_value_for_layout(), Some(input) => input.to_layout().get_value_for_layout(),
None => panic!("not an input element!") None => panic!("not an input element!")
} }
} }
@ -970,8 +970,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
pub fn get_input_size(&self) -> u32 { pub fn get_input_size(&self) -> u32 {
unsafe { unsafe {
match HTMLInputElementCast::to_js(self.get_jsmanaged()) { match HTMLInputElementCast::to_js(&self.get_jsmanaged().to_script()) {
Some(input) => input.get_size_for_layout(), Some(input) => input.to_layout().get_size_for_layout(),
None => panic!("not an input element!") None => panic!("not an input element!")
} }
} }
@ -980,7 +980,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
pub fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute) pub fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute)
-> Option<u32> { -> Option<u32> {
unsafe { unsafe {
let elem: Option<JS<Element>> = ElementCast::to_js(self.get_jsmanaged()); let elem: Option<JS<Element>> = ElementCast::to_js(&self.get_jsmanaged().to_script());
match elem { match elem {
Some(element) => { Some(element) => {
(*element.unsafe_get()).get_unsigned_integer_attribute_for_layout(attribute) (*element.unsafe_get()).get_unsigned_integer_attribute_for_layout(attribute)

View file

@ -144,6 +144,14 @@ pub struct LayoutJS<T> {
ptr: NonZero<*const T> ptr: NonZero<*const T>
} }
impl<T> LayoutJS<T> {
pub fn to_script(self) -> JS<T> {
JS {
ptr: self.ptr
}
}
}
impl<T> Copy for JS<T> {} impl<T> Copy for JS<T> {}
impl<T> Copy for LayoutJS<T> {} impl<T> Copy for LayoutJS<T> {}