diff options
author | bors-servo <release+servo@mozilla.com> | 2013-11-13 00:07:16 -0800 |
---|---|---|
committer | bors-servo <release+servo@mozilla.com> | 2013-11-13 00:07:16 -0800 |
commit | 4eb84496211bb48d2804a0ddcd16849536546103 (patch) | |
tree | 28fa0cc3f96eb20958d12fdecbb728a4e82d9083 /src/components/script/dom | |
parent | 01262861e39b0597ce44494af3a25c3537585b50 (diff) | |
parent | 6ff7b4a6a67ba31ceb36f7a16e00e4e3a09aa1ea (diff) | |
download | servo-4eb84496211bb48d2804a0ddcd16849536546103.tar.gz servo-4eb84496211bb48d2804a0ddcd16849536546103.zip |
auto merge of #1208 : pcwalton/servo/any-layout-data, r=metajack
Breaks the dependency between `gfx` and `script`, which is nice.
This exposed some performance issues with Rust's `Any` type, which I've filed:
https://github.com/mozilla/rust/issues/10382
Diffstat (limited to 'src/components/script/dom')
-rw-r--r-- | src/components/script/dom/node.rs | 89 |
1 files changed, 32 insertions, 57 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs index c6ce48ed395..f08c91c817b 100644 --- a/src/components/script/dom/node.rs +++ b/src/components/script/dom/node.rs @@ -21,12 +21,8 @@ use dom::text::Text; use std::cast; use std::cast::transmute; use std::unstable::raw::Box; -use extra::arc::Arc; use js::jsapi::{JSObject, JSContext}; -use style::{ComputedValues, PropertyDeclaration}; use servo_util::tree::{TreeNode, TreeNodeRef, TreeNodeRefAsElement}; -use servo_util::range::Range; -use gfx::display_list::DisplayList; // // The basic Node structure @@ -93,7 +89,7 @@ pub struct Node<View> { child_list: Option<@mut NodeList>, /// Layout information. Only the layout task may touch this data. - priv layout_data: LayoutData, + layout_data: Option<~Any>, } /// The different types of nodes. @@ -543,7 +539,7 @@ impl Node<ScriptView> { owner_doc: doc, child_list: None, - layout_data: LayoutData::new(), + layout_data: None, } } } @@ -1092,62 +1088,41 @@ impl Reflectable for Node<ScriptView> { } } -// This stuff is notionally private to layout, but we put it here because it needs -// to be stored in a Node, and we can't have cross-crate cyclic dependencies. +/// A bottom-up, parallelizable traversal. +pub trait PostorderNodeTraversal { + /// The operation to perform. Return true to continue or false to stop. + fn process(&mut self, node: AbstractNode<LayoutView>) -> bool; -pub struct DisplayBoxes { - display_list: Option<Arc<DisplayList<AbstractNode<()>>>>, - range: Option<Range>, -} - -/// Data that layout associates with a node. -pub struct LayoutData { - /// The results of CSS matching for this node. - applicable_declarations: ~[Arc<~[PropertyDeclaration]>], - - /// The results of CSS styling for this node. - style: Option<ComputedValues>, - - /// Description of how to account for recent style changes. - restyle_damage: Option<int>, - - /// The boxes assosiated with this flow. - /// Used for getBoundingClientRect and friends. - boxes: DisplayBoxes, -} - -impl LayoutData { - /// Creates new layout data. - pub fn new() -> LayoutData { - LayoutData { - applicable_declarations: ~[], - style: None, - restyle_damage: None, - boxes: DisplayBoxes { - display_list: None, - range: None, - }, - } + /// 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(&mut self, _node: AbstractNode<LayoutView>) -> bool { + false } } -// This serves as a static assertion that layout data remains sendable. If this is not done, then -// we can have memory unsafety, which usually manifests as shutdown crashes. -fn assert_is_sendable<T:Send>(_: T) {} -fn assert_layout_data_is_sendable() { - assert_is_sendable(LayoutData::new()) -} - impl AbstractNode<LayoutView> { - // These accessors take a continuation rather than returning a reference, because - // an AbstractNode doesn't have a lifetime parameter relating to the underlying - // Node. Also this makes it easier to switch to RWArc if we decide that is - // necessary. - pub fn read_layout_data<R>(self, blk: &fn(data: &LayoutData) -> R) -> R { - blk(&self.node().layout_data) - } + /// Traverses the tree in postorder. + /// + /// TODO(pcwalton): Offer a parallel version with a compatible API. + pub fn traverse_postorder<T:PostorderNodeTraversal>(self, traversal: &mut T) -> bool { + if traversal.should_prune(self) { + return true + } + + let mut opt_kid = self.first_child(); + loop { + match opt_kid { + None => break, + Some(kid) => { + if !kid.traverse_postorder(traversal) { + return false + } + opt_kid = kid.next_sibling() + } + } + } - pub fn write_layout_data<R>(self, blk: &fn(data: &mut LayoutData) -> R) -> R { - blk(&mut self.mut_node().layout_data) + traversal.process(self) } } |