style: Record attribute dependencies within the selector list of :nth-child(... of <selector list>)

There are separate filters for IDs, classes, attribute local names, and
element state.

Also, we invalidate siblings of elements matched against the selector
list of :nth-child(... of <selector list>) by marking matched elements
with NODE_HAS_SLOW_SELECTOR_NTH_OF.

The only remaining invalidation case invalidation case is
`:nth-child(An+B of :has())` (bug 1818155), which should not block
shipping `layout.css.nth-child-of.enabled`, because :has(...) is still
being implemented (bug 418039).

Depends on D172352

Differential Revision: https://phabricator.services.mozilla.com/D171936
This commit is contained in:
Zach Hoffman 2023-03-15 06:56:21 +00:00 committed by Martin Robinson
parent c7f8845665
commit 356e886d26
7 changed files with 261 additions and 28 deletions

View file

@ -4,13 +4,17 @@
//! Element an snapshot common logic.
use crate::dom::TElement;
use crate::gecko_bindings::bindings;
use crate::gecko_bindings::structs::{self, nsAtom};
use crate::invalidation::element::element_wrapper::ElementSnapshot;
use crate::selector_parser::SnapshotMap;
use crate::string_cache::WeakAtom;
use crate::values::AtomIdent;
use crate::Atom;
use crate::CaseSensitivityExt;
use selectors::attr::CaseSensitivity;
use smallvec::SmallVec;
/// A function that, given an element of type `T`, allows you to get a single
/// class or a class list.
@ -166,3 +170,27 @@ where
}
}
}
/// Returns a list of classes that were either added to or removed from the
/// element since the snapshot.
pub fn classes_changed<E: TElement>(element: &E, snapshots: &SnapshotMap) -> SmallVec<[Atom; 8]> {
debug_assert!(element.has_snapshot(), "Why bothering?");
let snapshot = snapshots.get(element).expect("has_snapshot lied");
if !snapshot.class_changed() {
return SmallVec::new();
}
let mut classes_changed = SmallVec::<[Atom; 8]>::new();
snapshot.each_class(|c| {
if !element.has_class(c, CaseSensitivity::CaseSensitive) {
classes_changed.push(c.0.clone());
}
});
element.each_class(|c| {
if !snapshot.has_class(c, CaseSensitivity::CaseSensitive) {
classes_changed.push(c.0.clone());
}
});
classes_changed
}

View file

@ -910,6 +910,9 @@ fn selector_flags_to_node_flags(flags: ElementSelectorFlags) -> u32 {
if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
gecko_flags |= NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS as u32;
}
if flags.contains(ElementSelectorFlags::HAS_SLOW_SELECTOR_NTH_OF) {
gecko_flags |= NODE_HAS_SLOW_SELECTOR_NTH_OF as u32;
}
if flags.contains(ElementSelectorFlags::HAS_EDGE_CHILD_SELECTOR) {
gecko_flags |= NODE_HAS_EDGE_CHILD_SELECTOR as u32;
}