style: Add TNode::children_and_traversal_children_might_differ. draft
authorCameron McCormack <cam@mcc.id.au>
Fri, 09 Jun 2017 13:43:52 +0800
changeset 591538 51985af543acb92c4746355a7eeb785f3bd0a43f
parent 591537 eae0475ea3a26a13112ac0e30dae5be9c62dc53d
child 591539 6f8f591c155887802817fb7fc8888bf3e7cc679e
push id63078
push userbmo:cam@mcc.id.au
push dateFri, 09 Jun 2017 06:22:34 +0000
milestone55.0a1
style: Add TNode::children_and_traversal_children_might_differ. This will be used to optimize out traversing the real DOM children when propagating restyle hints. MozReview-Commit-ID: FaDNjxMoPk3
servo/components/script/layout_wrapper.rs
servo/components/style/dom.rs
servo/components/style/gecko/wrapper.rs
--- a/servo/components/script/layout_wrapper.rs
+++ b/servo/components/script/layout_wrapper.rs
@@ -180,16 +180,22 @@ impl<'ln> TNode for ServoLayoutNode<'ln>
     fn traversal_parent(&self) -> Option<ServoLayoutElement<'ln>> {
         self.parent_node().and_then(|n| n.as_element())
     }
 
     fn traversal_children(&self) -> LayoutIterator<ServoChildrenIterator<'ln>> {
         self.children()
     }
 
+    fn children_and_traversal_children_might_differ(&self) -> bool {
+        // Servo doesn't have to worry about nodes being rearranged in the
+        // flattened tree like Gecko does (for XBL and Shadow DOM).  Yet.
+        false
+    }
+
     fn opaque(&self) -> OpaqueNode {
         unsafe { self.get_jsmanaged().opaque() }
     }
 
     fn debug_id(self) -> usize {
         self.opaque().0
     }
 
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -121,16 +121,20 @@ pub trait TNode : Sized + Copy + Clone +
 
     /// 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;
@@ -266,16 +267,20 @@ impl<'ln> TNode for GeckoNode<'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!()
     }