style: Use placement new/delete StyleChildrenIterator FFI functions.
draft
style: Use placement new/delete StyleChildrenIterator FFI functions.
MozReview-Commit-ID: L0bhymGJqRx
--- 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>> {