зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1792501: Part 3 - Let :has contribute to dependencies. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D185676
This commit is contained in:
Родитель
0dfd1143fd
Коммит
aa280d1e29
|
@ -1927,6 +1927,11 @@ impl<Impl: SelectorImpl> Component<Impl> {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
Has(ref list) => {
|
||||
if !visitor.visit_relative_selector_list(list) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use crate::attr::NamespaceConstraint;
|
||||
use crate::parser::{Combinator, Component, Selector, SelectorImpl};
|
||||
use crate::parser::{Combinator, Component, RelativeSelector, Selector, SelectorImpl};
|
||||
|
||||
/// A trait to visit selector properties.
|
||||
///
|
||||
|
@ -34,6 +34,14 @@ pub trait SelectorVisitor: Sized {
|
|||
true
|
||||
}
|
||||
|
||||
/// Visit a nested relative selector list. The caller is responsible to call visit
|
||||
/// into the internal selectors if / as needed.
|
||||
///
|
||||
/// The default implementation skips it altogether.
|
||||
fn visit_relative_selector_list(&mut self, _list: &[RelativeSelector<Self::Impl>]) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Visit a nested selector list. The caller is responsible to call visit
|
||||
/// into the internal selectors if / as needed.
|
||||
///
|
||||
|
@ -73,6 +81,8 @@ bitflags! {
|
|||
/// The visitor is inside :nth-child(.. of <selector list>) or
|
||||
/// :nth-last-child(.. of <selector list>)
|
||||
const NTH_OF = 1 << 3;
|
||||
/// The visitor is inside :has(..)
|
||||
const HAS = 1 << 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,4 +118,19 @@ impl SelectorListKind {
|
|||
pub fn in_nth_of(&self) -> bool {
|
||||
self.intersects(SelectorListKind::NTH_OF)
|
||||
}
|
||||
|
||||
/// Whether the visitor is inside :has(..)
|
||||
pub fn in_has(&self) -> bool {
|
||||
self.intersects(SelectorListKind::HAS)
|
||||
}
|
||||
|
||||
/// Whether this nested selector is relevant for nth-of dependencies.
|
||||
pub fn relevant_to_nth_of_dependencies(&self) -> bool {
|
||||
// Order of nesting for `:has` and `:nth-child(.. of ..)` doesn't matter, because:
|
||||
// * `:has(:nth-child(.. of ..))`: The location of the anchoring element is
|
||||
// independent from where `:nth-child(.. of ..)` is applied.
|
||||
// * `:nth-child(.. of :has(..))`: Invalidations inside `:has` must first use the
|
||||
// `:has` machinary to find the anchor, then carry out the remaining invalidation.
|
||||
self.in_nth_of() && !self.in_has()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2003,6 +2003,25 @@ fn component_needs_revalidation(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> StylistSelectorVisitor<'a> {
|
||||
fn visit_nested_selector(
|
||||
&mut self,
|
||||
in_selector_list_of: SelectorListKind,
|
||||
selector: &Selector<SelectorImpl>
|
||||
) {
|
||||
let old_passed_rightmost_selector = self.passed_rightmost_selector;
|
||||
let old_in_selector_list_of = self.in_selector_list_of;
|
||||
|
||||
self.passed_rightmost_selector = false;
|
||||
self.in_selector_list_of = in_selector_list_of;
|
||||
let _ret = selector.visit(self);
|
||||
debug_assert!(_ret, "We never return false");
|
||||
|
||||
self.passed_rightmost_selector = old_passed_rightmost_selector;
|
||||
self.in_selector_list_of = old_in_selector_list_of;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
|
@ -2026,21 +2045,18 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
|||
) -> bool {
|
||||
let in_selector_list_of = self.in_selector_list_of | list_kind;
|
||||
for selector in list {
|
||||
let mut nested = StylistSelectorVisitor {
|
||||
passed_rightmost_selector: false,
|
||||
needs_revalidation: &mut *self.needs_revalidation,
|
||||
in_selector_list_of,
|
||||
mapped_ids: &mut *self.mapped_ids,
|
||||
nth_of_mapped_ids: &mut *self.nth_of_mapped_ids,
|
||||
attribute_dependencies: &mut *self.attribute_dependencies,
|
||||
nth_of_class_dependencies: &mut *self.nth_of_class_dependencies,
|
||||
nth_of_attribute_dependencies: &mut *self.nth_of_attribute_dependencies,
|
||||
state_dependencies: &mut *self.state_dependencies,
|
||||
nth_of_state_dependencies: &mut *self.nth_of_state_dependencies,
|
||||
document_state_dependencies: &mut *self.document_state_dependencies,
|
||||
};
|
||||
let _ret = selector.visit(&mut nested);
|
||||
debug_assert!(_ret, "We never return false");
|
||||
self.visit_nested_selector(in_selector_list_of, selector);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn visit_relative_selector_list(
|
||||
&mut self,
|
||||
list: &[selectors::parser::RelativeSelector<Self::Impl>],
|
||||
) -> bool {
|
||||
let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
|
||||
for selector in list {
|
||||
self.visit_nested_selector(in_selector_list_of, &selector.selector);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
@ -2051,7 +2067,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
|||
name: &LocalName,
|
||||
lower_name: &LocalName,
|
||||
) -> bool {
|
||||
if self.in_selector_list_of.in_nth_of() {
|
||||
if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
|
||||
self.nth_of_attribute_dependencies.insert(name.clone());
|
||||
if name != lower_name {
|
||||
self.nth_of_attribute_dependencies
|
||||
|
@ -2077,7 +2093,7 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
|||
self.document_state_dependencies
|
||||
.insert(p.document_state_flag());
|
||||
|
||||
if self.in_selector_list_of.in_nth_of() {
|
||||
if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
|
||||
self.nth_of_state_dependencies.insert(p.state_flag());
|
||||
}
|
||||
},
|
||||
|
@ -2097,11 +2113,13 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
|
|||
self.mapped_ids.insert(id.0.clone());
|
||||
}
|
||||
|
||||
if self.in_selector_list_of.in_nth_of() {
|
||||
if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
|
||||
self.nth_of_mapped_ids.insert(id.0.clone());
|
||||
}
|
||||
},
|
||||
Component::Class(ref class) if self.in_selector_list_of.in_nth_of() => {
|
||||
Component::Class(ref class)
|
||||
if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
|
||||
{
|
||||
self.nth_of_class_dependencies.insert(class.0.clone());
|
||||
},
|
||||
_ => {},
|
||||
|
|
Загрузка…
Ссылка в новой задаче