style: Add simple parsing and matching support for :has

Parsing is behind a config value `layout.css.has-selectors.enabled`. This
change does not support p:has(> a) combinators, but will handle them
gracefully, just not matching on them.

Differential Revision: https://phabricator.services.mozilla.com/D149515
This commit is contained in:
Tiaan Louw 2022-06-20 08:53:02 +00:00 committed by Martin Robinson
parent dcdf9f33d5
commit 3d0cf4dbf9
8 changed files with 85 additions and 10 deletions

View file

@ -326,6 +326,32 @@ where
matches!(result, SelectorMatchingResult::Matched)
}
/// Traverse all descendents of the given element and return true as soon as any of them match
/// the given list of selectors.
fn has_children_matching<E: Element>(
selectors: &[Selector<E::Impl>],
element: &E,
context: &mut MatchingContext<E::Impl>,
) -> bool {
let mut current = element.first_element_child();
while let Some(el) = current {
for selector in selectors {
if matches_complex_selector(selector.iter(), &el, context) {
return true;
}
}
if has_children_matching(selectors, &el, context) {
return true;
}
current = el.next_sibling_element();
}
false
}
/// Whether the :hover and :active quirk applies.
///
/// https://quirks.spec.whatwg.org/#the-active-and-hover-quirk
@ -833,6 +859,9 @@ where
}
true
}),
Component::Has(ref list) => context.shared.nest(|context| {
has_children_matching(list, element, context)
}),
Component::Combinator(_) => unsafe {
debug_unreachable!("Shouldn't try to selector-match combinators")
},