diff options
author | Ting-Yu Lin <tlin@mozilla.com> | 2017-08-15 20:35:08 +0800 |
---|---|---|
committer | Ting-Yu Lin <tlin@mozilla.com> | 2017-08-16 14:25:01 +0800 |
commit | 0e82ca1d3a540ba96f01e8647d314dfd8d05cc47 (patch) | |
tree | b5dd4569f3ca4db9e9825268ce49cf62171bb93d | |
parent | dc654c991238305d6fc0524173c85f40d7b9e90f (diff) | |
download | servo-0e82ca1d3a540ba96f01e8647d314dfd8d05cc47.tar.gz servo-0e82ca1d3a540ba96f01e8647d314dfd8d05cc47.zip |
style: Skip matching :nth-child if element is the root of anonymous subtree
This implement the logic in Gecko's nsNthIndexCache::GetNthIndex().
MozReview-Commit-ID: 8lzK9iIbfzo
-rw-r--r-- | components/selectors/matching.rs | 4 | ||||
-rw-r--r-- | components/selectors/tree.rs | 6 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 13 |
3 files changed, 21 insertions, 2 deletions
diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 8f6b2fa6aa5..ead73c6a7fb 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -776,6 +776,10 @@ fn matches_generic_nth_child<E, F>(element: &E, where E: Element, F: FnMut(&E, ElementSelectorFlags), { + if element.ignores_nth_child_selectors() { + return false; + } + flags_setter(element, if is_from_end { HAS_SLOW_SELECTOR } else { diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs index 7827dc6bbe6..23238237b2f 100644 --- a/components/selectors/tree.rs +++ b/components/selectors/tree.rs @@ -86,6 +86,12 @@ pub trait Element: Sized + Debug { /// if the parent node is a `DocumentFragment`. fn is_root(&self) -> bool; + /// Returns whether this element should ignore matching nth child + /// selector. + fn ignores_nth_child_selectors(&self) -> bool { + false + } + /// Return true if we want to stop lookup ancestor of the current /// element while matching complex selectors with descendant/child /// combinator. diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index e4ccac1a2ba..6b7e2ca6030 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -729,6 +729,12 @@ impl<'le> GeckoElement<'le> { debug!("(Element not styled, discarding hints)"); } } + + /// This logic is duplicated in Gecko's nsIContent::IsRootOfAnonymousSubtree. + fn is_root_of_anonymous_subtree(&self) -> bool { + use gecko_bindings::structs::NODE_IS_ANONYMOUS_ROOT; + self.flags() & (NODE_IS_ANONYMOUS_ROOT as u32) != 0 + } } /// Converts flags from the layout used by rust-selectors to the layout used @@ -1970,9 +1976,12 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { node.owner_doc().mType == structs::root::nsIDocument_Type::eHTML } + fn ignores_nth_child_selectors(&self) -> bool { + self.is_root_of_anonymous_subtree() + } + fn blocks_ancestor_combinators(&self) -> bool { - use gecko_bindings::structs::NODE_IS_ANONYMOUS_ROOT; - if self.flags() & (NODE_IS_ANONYMOUS_ROOT as u32) == 0 { + if !self.is_root_of_anonymous_subtree() { return false } |