style: Add TNode::children. draft
authorCameron McCormack <cam@mcc.id.au>
Fri, 09 Jun 2017 12:16:59 +0800
changeset 591517 adda4618814e9a6b64fd70ea5dc76ba4df1f98bd
parent 591516 3df83582f1bc375e43aa498011aa773d1e40460e
child 591518 945247649d643850640ce9462282627efe8e8f7b
push id63070
push userbmo:cam@mcc.id.au
push dateFri, 09 Jun 2017 04:24:08 +0000
milestone55.0a1
style: Add TNode::children. Also add children_and_traversal_children_might_differ, which returns whether children() and traversal_children() could return different nodes. This will be used to optimize out traversing the real DOM children when propagating restyle hints. MozReview-Commit-ID: FaDNjxMoPk3
servo/components/style/dom.rs
servo/components/style/gecko/wrapper.rs
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -111,23 +111,30 @@ pub trait TNode : Sized + Copy + Clone +
     /// Get this node's parent node.
     fn parent_node(&self) -> Option<Self>;
 
     /// Get this node's parent element if present.
     fn parent_element(&self) -> Option<Self::ConcreteElement> {
         self.parent_node().and_then(|n| n.as_element())
     }
 
+    /// Returns an iterator over this node's children.
+    fn children(&self) -> LayoutIterator<Self::ConcreteChildrenIterator>;
+
     /// Get this node's parent element from the perspective of a restyle
     /// traversal.
     fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
 
     /// Get this node's children from the perspective of a restyle traversal.
     fn traversal_children(&self) -> LayoutIterator<Self::ConcreteChildrenIterator>;
 
+    /// Returns whether `children()` and `traversal_children()` might return
+    /// iterators over different nodes.
+    fn children_and_traversal_children_might_differ(&self) -> bool;
+
     /// Converts self into an `OpaqueNode`.
     fn opaque(&self) -> OpaqueNode;
 
     /// A debug id, only useful, mm... for debugging.
     fn debug_id(self) -> usize;
 
     /// Get this node as an element, if it's one.
     fn as_element(&self) -> Option<Self::ConcreteElement>;
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -43,16 +43,17 @@ use gecko_bindings::bindings::Gecko_GetH
 use gecko_bindings::bindings::Gecko_GetSMILOverrideDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetStyleContext;
 use gecko_bindings::bindings::Gecko_GetUnvisitedLinkAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_GetVisitedLinkAttrDeclarationBlock;
 use gecko_bindings::bindings::Gecko_IsSignificantChild;
 use gecko_bindings::bindings::Gecko_MatchLang;
 use gecko_bindings::bindings::Gecko_MatchStringArgPseudo;
+use gecko_bindings::bindings::Gecko_NodeHasBindingWithAnonymousContent;
 use gecko_bindings::bindings::Gecko_UnsetDirtyStyleAttr;
 use gecko_bindings::bindings::Gecko_UpdateAnimations;
 use gecko_bindings::structs;
 use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode, RawGeckoXBLBinding};
 use gecko_bindings::structs::{nsIAtom, nsIContent, nsINode_BooleanFlag, nsStyleContext};
 use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
 use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
 use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
@@ -249,29 +250,37 @@ impl<'ln> TNode for GeckoNode<'ln> {
     unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
         GeckoNode(&*(n.0 as *mut RawGeckoNode))
     }
 
     fn parent_node(&self) -> Option<Self> {
         unsafe { self.0.mParent.as_ref().map(GeckoNode) }
     }
 
+    fn children(&self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
+        LayoutIterator(self.dom_children())
+    }
+
     fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
         self.flattened_tree_parent().and_then(|n| n.as_element())
     }
 
     fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
         let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.0) };
         if let Some(iter) = maybe_iter.into_owned_opt() {
             LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter))
         } else {
             LayoutIterator(self.dom_children())
         }
     }
 
+    fn children_and_traversal_children_might_differ(&self) -> bool {
+        unsafe { Gecko_NodeHasBindingWithAnonymousContent(self.0) }
+    }
+
     fn opaque(&self) -> OpaqueNode {
         let ptr: usize = self.0 as *const _ as usize;
         OpaqueNode(ptr)
     }
 
     fn debug_id(self) -> usize {
         unimplemented!()
     }