aboutsummaryrefslogtreecommitdiffstats
path: root/components/selectors/parser.rs
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2020-05-20 23:53:34 +0000
committerEmilio Cobos Álvarez <emilio@crisal.io>2020-06-04 01:50:36 +0200
commitbd23e05c47913d235db5794dba54daec5ec82b36 (patch)
treed27c0a911b2afafc6fc15af6b5404c8e923a93d4 /components/selectors/parser.rs
parenta40b2b610a854ef257144a868f5dfb164d25272c (diff)
downloadservo-bd23e05c47913d235db5794dba54daec5ec82b36.tar.gz
servo-bd23e05c47913d235db5794dba54daec5ec82b36.zip
style: Fix a no-longer valid assumption in pseudo-element matching / invalidation code.
After bug 1632647, we can have pseudo-classes inside :not / :is / :where, which the invalidation and matching code weren't handling. Add a few tests for this stuff working as expected. Differential Revision: https://phabricator.services.mozilla.com/D76160
Diffstat (limited to 'components/selectors/parser.rs')
-rw-r--r--components/selectors/parser.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs
index 74f4a48de04..e2ad8e30caf 100644
--- a/components/selectors/parser.rs
+++ b/components/selectors/parser.rs
@@ -1054,6 +1054,47 @@ impl<Impl: SelectorImpl> Component<Impl> {
}
}
+ /// Whether this component is valid after a pseudo-element. Only intended
+ /// for sanity-checking.
+ pub fn maybe_allowed_after_pseudo_element(&self) -> bool {
+ match *self {
+ Component::NonTSPseudoClass(..) => true,
+ Component::Negation(ref components) => components.iter().all(|c| c.maybe_allowed_after_pseudo_element()),
+ Component::Is(ref selectors) |
+ Component::Where(ref selectors) => {
+ selectors.iter().all(|selector| {
+ selector.iter_raw_match_order().all(|c| c.maybe_allowed_after_pseudo_element())
+ })
+ },
+ _ => false,
+ }
+ }
+
+ /// Whether a given selector should match for stateless pseudo-elements.
+ ///
+ /// This is a bit subtle: Only selectors that return true in
+ /// `maybe_allowed_after_pseudo_element` should end up here, and
+ /// `NonTSPseudoClass` never matches (as it is a stateless pseudo after
+ /// all).
+ pub(crate) fn matches_for_stateless_pseudo_element(&self) -> bool {
+ debug_assert!(
+ self.maybe_allowed_after_pseudo_element(),
+ "Someone messed up pseudo-element parsing: {:?}",
+ *self
+ );
+ match *self {
+ Component::Negation(ref components) => {
+ !components.iter().all(|c| c.matches_for_stateless_pseudo_element())
+ },
+ Component::Is(ref selectors) | Component::Where(ref selectors) => {
+ selectors.iter().any(|selector| {
+ selector.iter_raw_match_order().all(|c| c.matches_for_stateless_pseudo_element())
+ })
+ },
+ _ => false,
+ }
+ }
+
pub fn visit<V>(&self, visitor: &mut V) -> bool
where
V: SelectorVisitor<Impl = Impl>,