style: Refactor children handling.

Moving traversal_children away from TNode I can make TNode trivial enough, in
order to share a QuerySelector implementation between Servo and Gecko.
This commit is contained in:
Emilio Cobos Álvarez 2017-10-16 14:25:25 +02:00
parent 7c2265360f
commit a11d268468
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
9 changed files with 149 additions and 158 deletions

View file

@ -158,32 +158,6 @@ impl<'ln> GeckoNode<'ln> {
unsafe { &*self.node_info().mDocument }
}
#[inline]
fn first_child(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mFirstChild.as_ref().map(GeckoNode::from_content) }
}
#[inline]
fn last_child(&self) -> Option<GeckoNode<'ln>> {
unsafe { Gecko_GetLastChild(self.0).map(GeckoNode) }
}
#[inline]
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mPreviousSibling.as_ref().map(GeckoNode::from_content) }
}
#[inline]
fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe { self.0.mNextSibling.as_ref().map(GeckoNode::from_content) }
}
/// Simple iterator over all this node's children. Unlike `.children()`, this iterator does
/// not filter out nodes that don't need layout.
fn dom_children(self) -> GeckoChildrenIterator<'ln> {
GeckoChildrenIterator::Current(self.first_child())
}
/// WARNING: This logic is duplicated in Gecko's FlattenedTreeParentIsParent.
/// Make sure to mirror any modifications in both places.
fn flattened_tree_parent_is_parent(&self) -> bool {
@ -222,11 +196,6 @@ impl<'ln> GeckoNode<'ln> {
fn contains_non_whitespace_content(&self) -> bool {
unsafe { Gecko_IsSignificantChild(self.0, true, false) }
}
#[inline]
fn may_have_anonymous_children(&self) -> bool {
self.get_bool_flag(nsINode_BooleanFlag::ElementMayHaveAnonymousChildren)
}
}
impl<'ln> NodeInfo for GeckoNode<'ln> {
@ -244,40 +213,35 @@ impl<'ln> NodeInfo for GeckoNode<'ln> {
impl<'ln> TNode for GeckoNode<'ln> {
type ConcreteElement = GeckoElement<'ln>;
type ConcreteChildrenIterator = GeckoChildrenIterator<'ln>;
fn parent_node(&self) -> Option<Self> {
unsafe { self.0.mParent.as_ref().map(GeckoNode) }
}
fn children(&self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
LayoutIterator(self.dom_children())
#[inline]
fn first_child(&self) -> Option<Self> {
unsafe { self.0.mFirstChild.as_ref().map(GeckoNode::from_content) }
}
#[inline]
fn last_child(&self) -> Option<Self> {
unsafe { Gecko_GetLastChild(self.0).map(GeckoNode) }
}
#[inline]
fn prev_sibling(&self) -> Option<Self> {
unsafe { self.0.mPreviousSibling.as_ref().map(GeckoNode::from_content) }
}
#[inline]
fn next_sibling(&self) -> Option<Self> {
unsafe { self.0.mNextSibling.as_ref().map(GeckoNode::from_content) }
}
fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
self.flattened_tree_parent().and_then(|n| n.as_element())
}
fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
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 element.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)
@ -447,6 +411,11 @@ impl<'le> fmt::Debug for GeckoElement<'le> {
}
impl<'le> GeckoElement<'le> {
#[inline]
fn may_have_anonymous_children(&self) -> bool {
self.as_node().get_bool_flag(nsINode_BooleanFlag::ElementMayHaveAnonymousChildren)
}
/// Parse the style attribute of an element.
pub fn parse_style_attribute<R>(
value: &str,
@ -883,6 +852,7 @@ impl structs::FontSizePrefs {
impl<'le> TElement for GeckoElement<'le> {
type ConcreteNode = GeckoNode<'le>;
type FontMetricsProvider = GeckoFontMetricsProvider;
type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
fn inheritance_parent(&self) -> Option<Self> {
if self.is_native_anonymous() {
@ -894,6 +864,24 @@ impl<'le> TElement for GeckoElement<'le> {
}
}
fn traversal_children(&self) -> LayoutIterator<GeckoChildrenIterator<'le>> {
// 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() ||
self.has_xbl_binding_with_content() ||
self.may_have_anonymous_children() {
unsafe {
let mut iter: structs::StyleChildrenIterator = ::std::mem::zeroed();
Gecko_ConstructStyleChildrenIterator(self.0, &mut iter);
return LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter));
}
}
LayoutIterator(GeckoChildrenIterator::Current(self.as_node().first_child()))
}
fn before_pseudo_element(&self) -> Option<Self> {
self.get_before_or_after_pseudo(/* is_before = */ true)
}