style: Use placement new/delete StyleChildrenIterator FFI functions. draft
authorCameron McCormack <cam@mcc.id.au>
Tue, 27 Jun 2017 17:08:29 -0700
changeset 601020 bd9737794ee82b24959b5c4b45ce1052fb14242f
parent 601019 6bdba71dafcb2a10d4a8c67b690579a1d722df62
child 635159 808b9e5aaa76f46a932c1d05a980510b7be557c3
push id65946
push userbmo:cam@mcc.id.au
push dateWed, 28 Jun 2017 00:09:35 +0000
milestone56.0a1
style: Use placement new/delete StyleChildrenIterator FFI functions. MozReview-Commit-ID: L0bhymGJqRx
servo/components/style/gecko/wrapper.rs
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -25,17 +25,17 @@ use dom::{OpaqueNode, PresentationalHint
 use element_state::ElementState;
 use error_reporting::create_error_reporter;
 use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
 use gecko::data::PerDocumentStyleData;
 use gecko::global_style_data::GLOBAL_STYLE_DATA;
 use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
 use gecko::snapshot_helpers;
 use gecko_bindings::bindings;
-use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
+use gecko_bindings::bindings::{Gecko_ConstructStyleChildrenIterator, Gecko_DestroyStyleChildrenIterator};
 use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetLastChild, Gecko_GetNextStyleChild};
 use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement, Gecko_Namespace};
 use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
 use gecko_bindings::bindings::Gecko_ClassOrClassList;
 use gecko_bindings::bindings::Gecko_ElementHasAnimations;
 use gecko_bindings::bindings::Gecko_ElementHasCSSAnimations;
 use gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
 use gecko_bindings::bindings::Gecko_GetActiveLinkAttrDeclarationBlock;
@@ -275,22 +275,33 @@ impl<'ln> TNode for GeckoNode<'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())
+        if let Some(element) = self.as_element() {
+            // This condition is similar to the check that
+            // StyleChildrenIterator::IsNeeded does, except that it might return
+            // true if we used to (but no longer) have anonymous content from
+            // ::before/::after, XBL bindings, or nsIAnonymousContentCreators.
+            if self.is_in_anonymous_subtree() ||
+               element.has_xbl_binding_with_content() ||
+               self.may_have_anonymous_children() {
+                unsafe {
+                    let mut iter: structs::StyleChildrenIterator = ::std::mem::zeroed();
+                    Gecko_ConstructStyleChildrenIterator(element.0, &mut iter);
+                    return LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter));
+                }
+            }
         }
+
+        LayoutIterator(self.dom_children())
     }
 
     fn opaque(&self) -> OpaqueNode {
         let ptr: usize = self.0 as *const _ as usize;
         OpaqueNode(ptr)
     }
 
     fn debug_id(self) -> usize {
@@ -344,24 +355,24 @@ impl<'ln> TNode for GeckoNode<'ln> {
 /// FIXME(emilio): If we take into account shadow DOM, we're going to need the
 /// flat tree pretty much always. We can try to optimize the case where there's
 /// no shadow root sibling, probably.
 pub enum GeckoChildrenIterator<'a> {
     /// A simple iterator that tracks the current node being iterated and
     /// replaces it with the next sibling when requested.
     Current(Option<GeckoNode<'a>>),
     /// A Gecko-implemented iterator we need to drop appropriately.
-    GeckoIterator(bindings::StyleChildrenIteratorOwned),
+    GeckoIterator(structs::StyleChildrenIterator),
 }
 
 impl<'a> Drop for GeckoChildrenIterator<'a> {
     fn drop(&mut self) {
-        if let GeckoChildrenIterator::GeckoIterator(ref it) = *self {
+        if let GeckoChildrenIterator::GeckoIterator(ref mut it) = *self {
             unsafe {
-                Gecko_DropStyleChildrenIterator(ptr::read(it as *const _));
+                Gecko_DestroyStyleChildrenIterator(it);
             }
         }
     }
 }
 
 impl<'a> Iterator for GeckoChildrenIterator<'a> {
     type Item = GeckoNode<'a>;
     fn next(&mut self) -> Option<GeckoNode<'a>> {