mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
layout: Stop exposing raw Element
types to layout as well.
This should make layout memory-safe as is, though we will need to do more stuff for incremental reflow and parallelism.
This commit is contained in:
parent
9e2b63ddd3
commit
8f886e599e
7 changed files with 59 additions and 39 deletions
|
@ -30,7 +30,7 @@ pub trait MatchMethods {
|
||||||
impl<'self> MatchMethods for LayoutNode<'self> {
|
impl<'self> MatchMethods for LayoutNode<'self> {
|
||||||
fn match_node(&self, stylist: &Stylist) {
|
fn match_node(&self, stylist: &Stylist) {
|
||||||
let applicable_declarations = do self.with_element |element| {
|
let applicable_declarations = do self.with_element |element| {
|
||||||
let style_attribute = match element.style_attribute {
|
let style_attribute = match *element.style_attribute() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref style_attribute) => Some(style_attribute)
|
Some(ref style_attribute) => Some(style_attribute)
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
//! onto these objects and cause use-after-free.
|
//! onto these objects and cause use-after-free.
|
||||||
|
|
||||||
use extra::url::Url;
|
use extra::url::Url;
|
||||||
use script::dom::element::Element;
|
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
||||||
|
use script::dom::element::{HTMLLinkElementTypeId};
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use script::dom::htmlimageelement::HTMLImageElement;
|
use script::dom::htmlimageelement::HTMLImageElement;
|
||||||
use script::dom::node::{AbstractNode, DocumentNodeTypeId, ElementNodeTypeId, LayoutView, Node};
|
use script::dom::node::{AbstractNode, DocumentNodeTypeId, ElementNodeTypeId, LayoutView, Node};
|
||||||
|
@ -23,7 +24,7 @@ use script::dom::node::{NodeTypeId};
|
||||||
use script::dom::text::Text;
|
use script::dom::text::Text;
|
||||||
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
use servo_msg::constellation_msg::{PipelineId, SubpageId};
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use style::TNode;
|
use style::{PropertyDeclarationBlock, TElement, TNode};
|
||||||
|
|
||||||
/// 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 `AbstractNode`.
|
/// only ever see these and must never see instances of `AbstractNode`.
|
||||||
|
@ -227,7 +228,7 @@ impl<'self> LayoutNode<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> TNode<Element> for LayoutNode<'self> {
|
impl<'self> TNode<LayoutElement<'self>> for LayoutNode<'self> {
|
||||||
fn parent_node(&self) -> Option<LayoutNode<'self>> {
|
fn parent_node(&self) -> Option<LayoutNode<'self>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.node.node().parent_node.map(|node| self.new_with_this_lifetime(node))
|
self.node.node().parent_node.map(|node| self.new_with_this_lifetime(node))
|
||||||
|
@ -260,10 +261,18 @@ impl<'self> TNode<Element> for LayoutNode<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME(pcwalton): Unsafe!
|
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_element<R>(&self, f: &fn(&Element) -> R) -> R {
|
fn with_element<R>(&self, f: &fn(&LayoutElement<'self>) -> R) -> R {
|
||||||
self.node.with_imm_element(f)
|
self.node.with_imm_element(|element| {
|
||||||
|
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
|
||||||
|
// implementations.
|
||||||
|
unsafe {
|
||||||
|
f(&LayoutElement {
|
||||||
|
element: cast::transmute_region(element),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,3 +359,40 @@ pub trait PostorderNodeMutTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper around elements that ensures layout can only ever access safe properties.
|
||||||
|
pub struct LayoutElement<'self> {
|
||||||
|
priv element: &'self Element,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> LayoutElement<'self> {
|
||||||
|
pub fn style_attribute(&self) -> &'self Option<PropertyDeclarationBlock> {
|
||||||
|
&self.element.style_attribute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> TElement for LayoutElement<'self> {
|
||||||
|
fn get_local_name<'a>(&'a self) -> &'a str {
|
||||||
|
self.element.tag_name.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_namespace_url<'a>(&'a self) -> &'a str {
|
||||||
|
self.element.namespace.to_str().unwrap_or("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str> {
|
||||||
|
self.element.get_attr(ns_url, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_link(&self) -> Option<~str> {
|
||||||
|
// FIXME: This is HTML only.
|
||||||
|
match self.element.node.type_id {
|
||||||
|
// http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#
|
||||||
|
// selector-link
|
||||||
|
ElementNodeTypeId(HTMLAnchorElementTypeId) |
|
||||||
|
ElementNodeTypeId(HTMLAreaElementTypeId) |
|
||||||
|
ElementNodeTypeId(HTMLLinkElementTypeId) => self.get_attr(None, "href"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ use std::cast;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::str::eq_slice;
|
use std::str::eq_slice;
|
||||||
use std::unstable::raw::Box;
|
use std::unstable::raw::Box;
|
||||||
use style::{TElement, TNode};
|
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
pub enum DocumentTypeId {
|
pub enum DocumentTypeId {
|
||||||
|
|
|
@ -20,7 +20,6 @@ use dom::namespace::Namespace;
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
|
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
|
||||||
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
|
use layout_interface::{ContentBoxesResponse, ContentChangedDocumentDamage};
|
||||||
use layout_interface::{MatchSelectorsDocumentDamage};
|
use layout_interface::{MatchSelectorsDocumentDamage};
|
||||||
use style::{TElement, TNode};
|
|
||||||
use style;
|
use style;
|
||||||
|
|
||||||
use std::comm;
|
use std::comm;
|
||||||
|
@ -125,31 +124,6 @@ pub enum ElementTypeId {
|
||||||
// Element methods
|
// Element methods
|
||||||
//
|
//
|
||||||
|
|
||||||
impl TElement for Element {
|
|
||||||
fn get_local_name<'a>(&'a self) -> &'a str {
|
|
||||||
self.tag_name.as_slice()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_namespace_url<'a>(&'a self) -> &'a str {
|
|
||||||
self.namespace.to_str().unwrap_or("")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str> {
|
|
||||||
self.get_attribute(ns_url, name).map(|attr| attr.value.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_link(&self) -> Option<~str>{
|
|
||||||
// FIXME: This is HTML only.
|
|
||||||
match self.node.type_id {
|
|
||||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-link
|
|
||||||
ElementNodeTypeId(HTMLAnchorElementTypeId) |
|
|
||||||
ElementNodeTypeId(HTMLAreaElementTypeId) |
|
|
||||||
ElementNodeTypeId(HTMLLinkElementTypeId)
|
|
||||||
=> self.get_attr(None, "href"),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'self> Element {
|
impl<'self> Element {
|
||||||
pub fn new_inherited(type_id: ElementTypeId, tag_name: ~str, namespace: Namespace, document: AbstractDocument) -> Element {
|
pub fn new_inherited(type_id: ElementTypeId, tag_name: ~str, namespace: Namespace, document: AbstractDocument) -> Element {
|
||||||
|
@ -187,6 +161,11 @@ impl<'self> Element {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(pcwalton): This is kind of confusingly named relative to the above...
|
||||||
|
pub fn get_attr(&self, ns_url: Option<~str>, name: &str) -> Option<~str> {
|
||||||
|
self.get_attribute(ns_url, name).map(|attr| attr.value.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_attr(&mut self, abstract_self: AbstractNode, name: DOMString, value: DOMString)
|
pub fn set_attr(&mut self, abstract_self: AbstractNode, name: DOMString, value: DOMString)
|
||||||
-> ErrorResult {
|
-> ErrorResult {
|
||||||
self.set_attribute(abstract_self, namespace::Null, name, value)
|
self.set_attribute(abstract_self, namespace::Null, name, value)
|
||||||
|
|
|
@ -25,7 +25,6 @@ use std::cast::transmute;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::unstable::raw::Box;
|
use std::unstable::raw::Box;
|
||||||
use std::util;
|
use std::util;
|
||||||
use style::TNode;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The basic Node structure
|
// The basic Node structure
|
||||||
|
|
|
@ -52,7 +52,6 @@ use std::ptr;
|
||||||
use std::str::eq_slice;
|
use std::str::eq_slice;
|
||||||
use std::task::{spawn_sched, SingleThreaded};
|
use std::task::{spawn_sched, SingleThreaded};
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
use style::{TElement, TNode};
|
|
||||||
|
|
||||||
/// Messages used to control the script task.
|
/// Messages used to control the script task.
|
||||||
pub enum ScriptMsg {
|
pub enum ScriptMsg {
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between script and
|
//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and
|
||||||
//! style.
|
//! style.
|
||||||
|
|
||||||
/// FIXME(pcwalton): Should not require `Clone` and should instead return references. When this
|
|
||||||
/// happens this will need to only be implemented for `AbstractNode<LayoutView>`.
|
|
||||||
pub trait TNode<E:TElement> : Clone {
|
pub trait TNode<E:TElement> : Clone {
|
||||||
fn parent_node(&self) -> Option<Self>;
|
fn parent_node(&self) -> Option<Self>;
|
||||||
fn prev_sibling(&self) -> Option<Self>;
|
fn prev_sibling(&self) -> Option<Self>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue