aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/script/dom/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/script/dom/node.rs')
-rw-r--r--src/components/script/dom/node.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index b0394528d95..a3edd1eb054 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -1217,6 +1217,20 @@ 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: AbstractNode<LayoutView>) -> 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: AbstractNode<LayoutView>) -> bool {
+ false
+ }
+}
+
+
impl AbstractNode<LayoutView> {
/// Traverses the tree in postorder.
///
@@ -1241,4 +1255,29 @@ impl AbstractNode<LayoutView> {
traversal.process(self)
}
+
+ /// 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 {
+ 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_mut(traversal) {
+ return false
+ }
+ opt_kid = kid.next_sibling()
+ }
+ }
+ }
+
+ traversal.process(self)
+ }
+
}