aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Yu Lin <tlin@mozilla.com>2017-08-15 20:35:08 +0800
committerTing-Yu Lin <tlin@mozilla.com>2017-08-16 14:25:01 +0800
commit0e82ca1d3a540ba96f01e8647d314dfd8d05cc47 (patch)
treeb5dd4569f3ca4db9e9825268ce49cf62171bb93d
parentdc654c991238305d6fc0524173c85f40d7b9e90f (diff)
downloadservo-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.rs4
-rw-r--r--components/selectors/tree.rs6
-rw-r--r--components/style/gecko/wrapper.rs13
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
}