mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
style: :has
relative selector matching, with no caching/filtering
Differential Revision: https://phabricator.services.mozilla.com/D172019
This commit is contained in:
parent
a68766197f
commit
3756e3b027
4 changed files with 334 additions and 64 deletions
|
@ -17,7 +17,7 @@
|
|||
//! is non-trivial. This module encapsulates those details and presents an
|
||||
//! easy-to-use API for the parser.
|
||||
|
||||
use crate::parser::{Combinator, Component, Selector, SelectorImpl};
|
||||
use crate::parser::{Combinator, Component, RelativeSelector, Selector, SelectorImpl};
|
||||
use crate::sink::Push;
|
||||
use bitflags::bitflags;
|
||||
use derive_more::{Add, AddAssign};
|
||||
|
@ -337,25 +337,29 @@ where
|
|||
// specificity of a regular pseudo-class with that of its
|
||||
// selector argument S.
|
||||
specificity.class_like_selectors += 1;
|
||||
let sf = selector_list_specificity_and_flags(nth_of_data.selectors());
|
||||
let sf = selector_list_specificity_and_flags(nth_of_data.selectors().iter());
|
||||
*specificity += Specificity::from(sf.specificity);
|
||||
flags.insert(sf.flags);
|
||||
},
|
||||
// https://drafts.csswg.org/selectors/#specificity-rules:
|
||||
//
|
||||
// The specificity of an :is(), :not(), or :has() pseudo-class
|
||||
// is replaced by the specificity of the most specific complex
|
||||
// selector in its selector list argument.
|
||||
Component::Where(ref list) |
|
||||
Component::Negation(ref list) |
|
||||
Component::Is(ref list) |
|
||||
Component::Has(ref list) => {
|
||||
// https://drafts.csswg.org/selectors/#specificity-rules:
|
||||
//
|
||||
// The specificity of an :is(), :not(), or :has() pseudo-class
|
||||
// is replaced by the specificity of the most specific complex
|
||||
// selector in its selector list argument.
|
||||
let sf = selector_list_specificity_and_flags(list);
|
||||
Component::Is(ref list) => {
|
||||
let sf = selector_list_specificity_and_flags(list.iter());
|
||||
if !matches!(*simple_selector, Component::Where(..)) {
|
||||
*specificity += Specificity::from(sf.specificity);
|
||||
}
|
||||
flags.insert(sf.flags);
|
||||
},
|
||||
Component::Has(ref relative_selectors) => {
|
||||
let sf = relative_selector_list_specificity_and_flags(relative_selectors);
|
||||
*specificity += Specificity::from(sf.specificity);
|
||||
flags.insert(sf.flags);
|
||||
},
|
||||
Component::ExplicitUniversalType |
|
||||
Component::ExplicitAnyNamespace |
|
||||
Component::ExplicitNoNamespace |
|
||||
|
@ -379,12 +383,13 @@ where
|
|||
}
|
||||
|
||||
/// Finds the maximum specificity of elements in the list and returns it.
|
||||
pub(crate) fn selector_list_specificity_and_flags<Impl: SelectorImpl>(
|
||||
list: &[Selector<Impl>],
|
||||
) -> SpecificityAndFlags {
|
||||
pub(crate) fn selector_list_specificity_and_flags<'a, Impl: SelectorImpl>(
|
||||
itr: impl Iterator<Item = &'a Selector<Impl>>,
|
||||
) -> SpecificityAndFlags
|
||||
{
|
||||
let mut specificity = 0;
|
||||
let mut flags = SelectorFlags::empty();
|
||||
for selector in list.iter() {
|
||||
for selector in itr {
|
||||
specificity = std::cmp::max(specificity, selector.specificity());
|
||||
if selector.has_parent_selector() {
|
||||
flags.insert(SelectorFlags::HAS_PARENT);
|
||||
|
@ -392,3 +397,9 @@ pub(crate) fn selector_list_specificity_and_flags<Impl: SelectorImpl>(
|
|||
}
|
||||
SpecificityAndFlags { specificity, flags }
|
||||
}
|
||||
|
||||
pub(crate) fn relative_selector_list_specificity_and_flags<Impl: SelectorImpl>(
|
||||
list: &[RelativeSelector<Impl>],
|
||||
) -> SpecificityAndFlags {
|
||||
selector_list_specificity_and_flags(list.iter().map(|rel| &rel.selector))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue