aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/css/matching.rs32
-rw-r--r--src/components/main/css/node_style.rs2
-rw-r--r--src/components/main/css/node_util.rs2
-rw-r--r--src/components/main/layout/construct.rs2
-rw-r--r--src/components/main/layout/extra.rs2
-rw-r--r--src/components/main/layout/inline.rs3
-rw-r--r--src/components/main/layout/util.rs2
-rw-r--r--src/components/script/dom/node.rs78
8 files changed, 77 insertions, 46 deletions
diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs
index 4ca64a8a138..efd84f36b7e 100644
--- a/src/components/main/css/matching.rs
+++ b/src/components/main/css/matching.rs
@@ -4,18 +4,19 @@
// High-level interface to CSS selector matching.
-use std::cell::Cell;
-use std::comm;
-use std::task;
-use std::vec;
-use std::rt;
-use extra::arc::{Arc, RWArc};
-
use css::node_style::StyledNode;
use layout::incremental;
use layout::util::LayoutDataAccess;
+use extra::arc::{Arc, RWArc};
use script::dom::node::LayoutNode;
+use std::cast;
+use std::cell::Cell;
+use std::comm;
+use std::libc::uintptr_t;
+use std::rt;
+use std::task;
+use std::vec;
use style::{TNode, Stylist, cascade};
pub trait MatchMethods {
@@ -26,7 +27,7 @@ pub trait MatchMethods {
fn cascade_subtree(&self, parent: Option<LayoutNode>);
}
-impl MatchMethods for LayoutNode {
+impl<'self> MatchMethods for LayoutNode<'self> {
fn match_node(&self, stylist: &Stylist) {
let applicable_declarations = do self.with_element |element| {
let style_attribute = match element.style_attribute {
@@ -63,7 +64,20 @@ impl MatchMethods for LayoutNode {
if nodes.len() > 0 {
let chan = chan.clone();
let stylist = stylist.clone();
- do task::spawn_with((nodes, stylist)) |(nodes, stylist)| {
+
+ // FIXME(pcwalton): This transmute is to work around the fact that we have no
+ // mechanism for safe fork/join parallelism. If we had such a thing, then we could
+ // close over the lifetime-bounded `LayoutNode`. But we can't, so we force it with
+ // a transmute.
+ let evil: uintptr_t = unsafe {
+ cast::transmute(nodes)
+ };
+
+ do task::spawn_with((evil, stylist)) |(evil, stylist)| {
+ let nodes: ~[LayoutNode] = unsafe {
+ cast::transmute(evil)
+ };
+
let nodes = Cell::new(nodes);
do stylist.read |stylist| {
for node in nodes.take().move_iter() {
diff --git a/src/components/main/css/node_style.rs b/src/components/main/css/node_style.rs
index 6e2abaa81d1..824b50e991a 100644
--- a/src/components/main/css/node_style.rs
+++ b/src/components/main/css/node_style.rs
@@ -17,7 +17,7 @@ pub trait StyledNode {
fn restyle_damage(&self) -> RestyleDamage;
}
-impl StyledNode for LayoutNode {
+impl<'self> StyledNode for LayoutNode<'self> {
#[inline]
fn style<'a>(&'a self) -> &'a Arc<ComputedValues> {
self.get_css_select_results()
diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs
index 3b24f85e9de..72acf5dc08c 100644
--- a/src/components/main/css/node_util.rs
+++ b/src/components/main/css/node_util.rs
@@ -18,7 +18,7 @@ pub trait NodeUtil {
fn set_restyle_damage(self, damage: RestyleDamage);
}
-impl NodeUtil for LayoutNode {
+impl<'self> NodeUtil for LayoutNode<'self> {
/**
* Provides the computed style for the given node. If CSS selector
* Returns the style results for the given node. If CSS selector
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index e2182886f29..9c6f285047e 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -528,7 +528,7 @@ trait NodeUtils {
fn swap_out_construction_result(self) -> ConstructionResult;
}
-impl NodeUtils for LayoutNode {
+impl<'self> NodeUtils for LayoutNode<'self> {
fn is_replaced_content(self) -> bool {
match self.type_id() {
TextNodeTypeId |
diff --git a/src/components/main/layout/extra.rs b/src/components/main/layout/extra.rs
index 7bc4847f5d3..bef668c6788 100644
--- a/src/components/main/layout/extra.rs
+++ b/src/components/main/layout/extra.rs
@@ -14,7 +14,7 @@ pub trait LayoutAuxMethods {
fn initialize_style_for_subtree(self);
}
-impl LayoutAuxMethods for LayoutNode {
+impl<'self> LayoutAuxMethods for LayoutNode<'self> {
/// Resets layout data and styles for the node.
///
/// FIXME(pcwalton): Do this as part of box building instead of in a traversal.
diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs
index c270d90df60..5d5022eaf30 100644
--- a/src/components/main/layout/inline.rs
+++ b/src/components/main/layout/inline.rs
@@ -441,10 +441,11 @@ pub struct InlineFlow {
// these ranges are disjoint, and are the result of inline layout.
// also some metadata used for positioning lines
lines: ~[LineBox],
+
// vec of ranges into boxes that represent elements. These ranges
// must be well-nested, and are only related to the content of
// boxes (not lines). Ranges are only kept for non-leaf elements.
- elems: ElementMapping
+ elems: ElementMapping,
}
impl InlineFlow {
diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs
index 4621578e481..36168117e0a 100644
--- a/src/components/main/layout/util.rs
+++ b/src/components/main/layout/util.rs
@@ -163,7 +163,7 @@ pub trait LayoutDataAccess {
fn mutate_layout_data<'a>(&'a self) -> MutSlotRef<'a,Option<~LayoutData>>;
}
-impl LayoutDataAccess for LayoutNode {
+impl<'self> LayoutDataAccess for LayoutNode<'self> {
#[inline(always)]
unsafe fn borrow_layout_data_unchecked<'a>(&'a self) -> &'a Option<~LayoutData> {
cast::transmute(self.get().layout_data.borrow_unchecked())
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index e9c60433a61..cbc7595b609 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -30,23 +30,33 @@ use std::util;
use style::TNode;
//
-// The basic Node structure
+// Layout's immutable, sanitized view of nodes.
//
-/// A wrapper so that layout can access only the properties that it should have access to. Layout
-/// should only ever see this.
+/// A nonsense constant for layout nodes to point to just to establish a lifetime.
+///
+/// FIXME(pcwalton): Phantom lifetimes in Rust would be useful...
+static HEAVY_IRON_BALL: () = ();
+
+/// 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`.
#[deriving(Clone, Eq)]
-pub struct LayoutNode {
+pub struct LayoutNode<'self> {
+ /// The wrapped node.
priv node: AbstractNode,
+
+ /// Being chained to a `HEAVY_IRON_BALL` prevents `LayoutNode`s from escaping.
+ priv chain: &'self (),
}
-impl LayoutNode {
+impl<'self> LayoutNode<'self> {
/// NB: Do not make this public.
///
/// FIXME(pcwalton): Probably this should be marked `unsafe`.
- /*PRIVATE-FOR-SECURITY-REASONS*/ fn new(node: AbstractNode) -> LayoutNode {
+ /*PRIVATE-FOR-SECURITY-REASONS*/ fn new(node: AbstractNode) -> LayoutNode<'static> {
LayoutNode {
node: node,
+ chain: &HEAVY_IRON_BALL,
}
}
@@ -57,26 +67,26 @@ impl LayoutNode {
}
/// Returns the first child of this node.
- pub fn first_child(&self) -> Option<LayoutNode> {
+ pub fn first_child(&self) -> Option<LayoutNode<'self>> {
self.node.first_child().map(|node| LayoutNode::new(node))
}
/// Returns the first child of this node.
- pub fn last_child(&self) -> Option<LayoutNode> {
+ pub fn last_child(&self) -> Option<LayoutNode<'self>> {
self.node.last_child().map(|node| LayoutNode::new(node))
}
/// Iterates over this node and all its descendants, in preorder.
///
/// FIXME(pcwalton): Terribly inefficient. We should use parallelism.
- pub fn traverse_preorder(&self) -> LayoutTreeIterator {
+ pub fn traverse_preorder(&self) -> LayoutTreeIterator<'self> {
let mut nodes = ~[];
gather_layout_nodes(self, &mut nodes, false);
LayoutTreeIterator::new(nodes)
}
/// Returns an iterator over this node's children.
- pub fn children(&self) -> LayoutNodeChildrenIterator {
+ pub fn children(&self) -> LayoutNodeChildrenIterator<'self> {
LayoutNodeChildrenIterator {
current_node: self.first_child(),
}
@@ -177,16 +187,16 @@ impl LayoutNode {
}
}
-impl TNode<Element> for LayoutNode {
- fn parent_node(&self) -> Option<LayoutNode> {
+impl<'self> TNode<Element> for LayoutNode<'self> {
+ fn parent_node(&self) -> Option<LayoutNode<'self>> {
self.node.node().parent_node.map(|node| LayoutNode::new(node))
}
- fn prev_sibling(&self) -> Option<LayoutNode> {
+ fn prev_sibling(&self) -> Option<LayoutNode<'self>> {
self.node.node().prev_sibling.map(|node| LayoutNode::new(node))
}
- fn next_sibling(&self) -> Option<LayoutNode> {
+ fn next_sibling(&self) -> Option<LayoutNode<'self>> {
self.node.node().next_sibling.map(|node| LayoutNode::new(node))
}
@@ -204,12 +214,17 @@ impl TNode<Element> for LayoutNode {
}
}
+ /// FIXME(pcwalton): Unsafe!
#[inline]
fn with_element<R>(&self, f: &fn(&Element) -> R) -> R {
self.node.with_imm_element(f)
}
}
+//
+// The basic Node structure
+//
+
/// This is what a Node looks like if you do not know what kind of node it is. To unpack it, use
/// downcast().
///
@@ -836,12 +851,12 @@ impl Iterator<AbstractNode> for AbstractNodeChildrenIterator {
}
}
-pub struct LayoutNodeChildrenIterator {
- priv current_node: Option<LayoutNode>,
+pub struct LayoutNodeChildrenIterator<'self> {
+ priv current_node: Option<LayoutNode<'self>>,
}
-impl Iterator<LayoutNode> for LayoutNodeChildrenIterator {
- fn next(&mut self) -> Option<LayoutNode> {
+impl<'self> Iterator<LayoutNode<'self>> for LayoutNodeChildrenIterator<'self> {
+ fn next(&mut self) -> Option<LayoutNode<'self>> {
let node = self.current_node;
self.current_node = do self.current_node.and_then |node| {
node.next_sibling()
@@ -911,13 +926,13 @@ fn gather_abstract_nodes(cur: &AbstractNode, refs: &mut ~[AbstractNode], postord
// Easy for preorder; harder for postorder.
//
// FIXME(pcwalton): Parallelism! Eventually this should just be nuked.
-pub struct LayoutTreeIterator {
- priv nodes: ~[LayoutNode],
+pub struct LayoutTreeIterator<'self> {
+ priv nodes: ~[LayoutNode<'self>],
priv index: uint,
}
-impl LayoutTreeIterator {
- fn new(nodes: ~[LayoutNode]) -> LayoutTreeIterator {
+impl<'self> LayoutTreeIterator<'self> {
+ fn new(nodes: ~[LayoutNode<'self>]) -> LayoutTreeIterator<'self> {
LayoutTreeIterator {
nodes: nodes,
index: 0,
@@ -925,8 +940,8 @@ impl LayoutTreeIterator {
}
}
-impl Iterator<LayoutNode> for LayoutTreeIterator {
- fn next(&mut self) -> Option<LayoutNode> {
+impl<'self> Iterator<LayoutNode<'self>> for LayoutTreeIterator<'self> {
+ fn next(&mut self) -> Option<LayoutNode<'self>> {
if self.index >= self.nodes.len() {
None
} else {
@@ -938,7 +953,7 @@ impl Iterator<LayoutNode> for LayoutTreeIterator {
}
/// FIXME(pcwalton): This is super inefficient.
-fn gather_layout_nodes(cur: &LayoutNode, refs: &mut ~[LayoutNode], postorder: bool) {
+fn gather_layout_nodes<'a>(cur: &LayoutNode<'a>, refs: &mut ~[LayoutNode<'a>], postorder: bool) {
if !postorder {
refs.push(cur.clone());
}
@@ -1617,12 +1632,12 @@ impl Reflectable for Node<ScriptView> {
/// A bottom-up, parallelizable traversal.
pub trait PostorderNodeTraversal {
/// The operation to perform. Return true to continue or false to stop.
- fn process(&self, node: LayoutNode) -> bool;
+ fn process<'a>(&'a self, node: LayoutNode<'a>) -> bool;
/// Returns true if this node should be pruned. If this returns true, we skip the operation
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
/// visited. The default implementation never prunes any nodes.
- fn should_prune(&self, _node: LayoutNode) -> bool {
+ fn should_prune<'a>(&'a self, _node: LayoutNode<'a>) -> bool {
false
}
}
@@ -1630,17 +1645,17 @@ pub trait PostorderNodeTraversal {
/// A bottom-up, parallelizable traversal.
pub trait PostorderNodeMutTraversal {
/// The operation to perform. Return true to continue or false to stop.
- fn process(&mut self, node: LayoutNode) -> bool;
+ fn process<'a>(&'a mut self, node: LayoutNode<'a>) -> bool;
/// Returns true if this node should be pruned. If this returns true, we skip the operation
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
/// visited. The default implementation never prunes any nodes.
- fn should_prune(&self, _node: LayoutNode) -> bool {
+ fn should_prune<'a>(&'a self, _node: LayoutNode<'a>) -> bool {
false
}
}
-impl LayoutNode {
+impl<'self> LayoutNode<'self> {
/// Traverses the tree in postorder.
///
/// TODO(pcwalton): Offer a parallel version with a compatible API.
@@ -1668,7 +1683,8 @@ impl LayoutNode {
/// Traverses the tree in postorder.
///
/// TODO(pcwalton): Offer a parallel version with a compatible API.
- pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(mut self, traversal: &mut T) -> bool {
+ pub fn traverse_postorder_mut<T:PostorderNodeMutTraversal>(mut self, traversal: &mut T)
+ -> bool {
if traversal.should_prune(self) {
return true
}