diff --git a/components/style/dom.rs b/components/style/dom.rs index 6bd774a0198..38d75a1eedb 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -110,9 +110,32 @@ where } } +/// An iterator over the DOM descendants of a node in pre-order. +pub struct DomDescendants { + previous: Option, + scope: N, +} + +impl Iterator for DomDescendants +where + N: TNode +{ + type Item = N; + + fn next(&mut self) -> Option { + let prev = match self.previous.take() { + None => return None, + Some(n) => n, + }; + + self.previous = prev.next_in_preorder(Some(self.scope)); + self.previous + } +} + /// The `TNode` trait. This is the main generic trait over which the style /// system can be implemented. -pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo { +pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq { /// The concrete `TElement` type. type ConcreteElement: TElement; @@ -131,11 +154,45 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo { /// Get this node's next sibling. fn next_sibling(&self) -> Option; - /// Iterate over the DOM children of an element. + /// Iterate over the DOM children of a node. fn dom_children(&self) -> DomChildren { DomChildren(self.first_child()) } + /// Iterate over the DOM children of a node, in preorder. + fn dom_descendants(&self) -> DomDescendants { + DomDescendants { + previous: Some(*self), + scope: *self, + } + } + + /// Returns the next children in pre-order, optionally scoped to a subtree + /// root. + fn next_in_preorder(&self, scoped_to: Option) -> Option { + if let Some(c) = self.first_child() { + return Some(c); + } + + if Some(*self) == scoped_to { + return None; + } + + let mut current = *self; + loop { + if let Some(s) = current.next_sibling() { + return Some(s); + } + + let parent = current.parent_node(); + if parent == scoped_to { + return None; + } + + current = parent.expect("Not a descendant of the scope?"); + } + } + /// Get this node's parent element from the perspective of a restyle /// traversal. fn traversal_parent(&self) -> Option; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index c8fc86a5063..9cdcdba9de4 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -104,6 +104,12 @@ use stylist::Stylist; #[derive(Clone, Copy)] pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode); +impl<'ln> PartialEq for GeckoNode<'ln> { + fn eq(&self, other: &Self) -> bool { + self.0 as *const _ == other.0 as *const _ + } +} + impl<'ln> fmt::Debug for GeckoNode<'ln> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(el) = self.as_element() {