diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-05-20 23:53:34 +0000 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-06-04 01:50:36 +0200 |
commit | bd23e05c47913d235db5794dba54daec5ec82b36 (patch) | |
tree | d27c0a911b2afafc6fc15af6b5404c8e923a93d4 /components/selectors/parser.rs | |
parent | a40b2b610a854ef257144a868f5dfb164d25272c (diff) | |
download | servo-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.rs | 41 |
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>, |