style/invalidation/element/
invalidation_map.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Code for invalidations due to state or attribute changes.
6
7use crate::context::QuirksMode;
8use crate::selector_map::{
9    MaybeCaseInsensitiveHashMap, PrecomputedHashMap, SelectorMap, SelectorMapEntry,
10};
11use crate::selector_parser::{NonTSPseudoClass, SelectorImpl};
12use crate::values::AtomIdent;
13use crate::AllocErr;
14use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded};
15use dom::{DocumentState, ElementState};
16use selectors::attr::NamespaceConstraint;
17use selectors::parser::{
18    Combinator, Component, RelativeSelector, RelativeSelectorCombinatorCount,
19    RelativeSelectorMatchHint,
20};
21use selectors::parser::{Selector, SelectorIter};
22use selectors::visitor::{SelectorListKind, SelectorVisitor};
23use servo_arc::ThinArc;
24use smallvec::SmallVec;
25
26/// Mapping between (partial) CompoundSelectors (and the combinator to their
27/// right) and the states and attributes they depend on.
28///
29/// In general, for all selectors in all applicable stylesheets of the form:
30///
31/// |a _ b _ c _ d _ e|
32///
33/// Where:
34///   * |b| and |d| are simple selectors that depend on state (like :hover) or
35///     attributes (like [attr...], .foo, or #foo).
36///   * |a|, |c|, and |e| are arbitrary simple selectors that do not depend on
37///     state or attributes.
38///
39/// We generate a Dependency for both |a _ b:X _| and |a _ b:X _ c _ d:Y _|,
40/// even though those selectors may not appear on their own in any stylesheet.
41/// This allows us to quickly scan through the dependency sites of all style
42/// rules and determine the maximum effect that a given state or attribute
43/// change may have on the style of elements in the document.
44#[derive(Clone, Debug, MallocSizeOf)]
45pub struct Dependency {
46    /// The dependency selector.
47    #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
48    pub selector: Selector<SelectorImpl>,
49
50    /// The offset into the selector that we should match on.
51    pub selector_offset: usize,
52
53    /// The next dependency for a selector chain. For example, consider
54    /// the following:
55    ///
56    ///     .foo .bar:where(.baz span) .qux
57    ///         ^               ^     ^
58    ///         A               B     C
59    ///
60    ///  We'd generate:
61    ///
62    ///    * One dependency for .qux (offset: 0, next: None)
63    ///    * One dependency for .baz pointing to B with next being a
64    ///      dependency pointing to C.
65    ///    * One dependency from .bar pointing to C (next: None)
66    ///    * One dependency from .foo pointing to A (next: None)
67    ///
68    /// Scope blocks can add multiple next entries: e.g. With
69    /// @scope (.a) { .b {/*...*/ } .c { /*...*/ }}
70    /// .a's Dependency would have two entries, for .b and .c.
71    #[ignore_malloc_size_of = "Arc"]
72    pub next: Option<ThinArc<(), Dependency>>,
73
74    /// What kind of selector invalidation this generates.
75    kind: DependencyInvalidationKind,
76}
77
78impl SelectorMapEntry for Dependency {
79    fn selector(&self) -> SelectorIter<SelectorImpl> {
80        self.selector.iter_from(self.selector_offset)
81    }
82}
83
84/// The kind of elements down the tree this dependency may affect.
85#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
86pub enum NormalDependencyInvalidationKind {
87    /// This dependency may affect the element that changed itself.
88    Element,
89    /// This dependency affects the style of the element itself, and also the
90    /// style of its descendants.
91    ///
92    /// TODO(emilio): Each time this feels more of a hack for eager pseudos...
93    ElementAndDescendants,
94    /// This dependency may affect descendants down the tree.
95    Descendants,
96    /// This dependency may affect siblings to the right of the element that
97    /// changed.
98    Siblings,
99    /// This dependency may affect slotted elements of the element that changed.
100    SlottedElements,
101    /// This dependency may affect parts of the element that changed.
102    Parts,
103}
104
105/// The kind of elements up the tree this relative selector dependency may
106/// affect. Because this travels upwards, it's not viable for parallel subtree
107/// traversal, and is handled separately.
108#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
109pub enum RelativeDependencyInvalidationKind {
110    /// This dependency may affect relative selector anchors for ancestors.
111    Ancestors,
112    /// This dependency may affect a relative selector anchor for the parent.
113    Parent,
114    /// This dependency may affect a relative selector anchor for the previous sibling.
115    PrevSibling,
116    /// This dependency may affect relative selector anchors for ancestors' previous siblings.
117    AncestorPrevSibling,
118    /// This dependency may affect relative selector anchors for earlier siblings.
119    EarlierSibling,
120    /// This dependency may affect relative selector anchors for ancestors' earlier siblings.
121    AncestorEarlierSibling,
122}
123
124/// The kind of invalidation the subject of this dependency triggers.
125#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
126pub enum ScopeDependencyInvalidationKind {
127    /// This dependency's subject is an explicit scope root
128    ExplicitScope,
129    /// This dependency's subject is an implicit scope root
130    ImplicitScope,
131}
132
133/// Invalidation kind merging normal and relative dependencies.
134#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
135pub enum DependencyInvalidationKind {
136    /// This dependency is for full selector invalidation.
137    /// It is assuumed that there will be no next dependency to look for.
138    FullSelector,
139    /// This dependency is a normal dependency.
140    Normal(NormalDependencyInvalidationKind),
141    /// This dependency is a relative dependency.
142    Relative(RelativeDependencyInvalidationKind),
143    /// This dependency is a scope dependency.
144    Scope(ScopeDependencyInvalidationKind),
145}
146
147/// The type of invalidation a non-relative selector can generate.
148#[derive(Clone, Copy, Debug, MallocSizeOf)]
149pub enum GeneratedInvalidation<'a> {
150    /// Generates a normal invalidation.
151    Normal,
152    /// Generates a scope invalidation.
153    Scope(Option<&'a ThinArc<(), Dependency>>),
154}
155
156/// Return the type of normal invalidation given a selector & an offset.
157#[inline(always)]
158fn get_non_relative_invalidation_kind(
159    selector: &Selector<SelectorImpl>,
160    selector_offset: usize,
161    is_scope: bool,
162) -> DependencyInvalidationKind {
163    if is_scope {
164        return DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ExplicitScope);
165    }
166    if selector_offset == 0 {
167        return DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element);
168    }
169    let combinator = selector.combinator_at_match_order(selector_offset - 1);
170    DependencyInvalidationKind::Normal(match combinator {
171        Combinator::Child | Combinator::Descendant => NormalDependencyInvalidationKind::Descendants,
172        Combinator::LaterSibling | Combinator::NextSibling => {
173            NormalDependencyInvalidationKind::Siblings
174        },
175        Combinator::PseudoElement => NormalDependencyInvalidationKind::ElementAndDescendants,
176        Combinator::SlotAssignment => NormalDependencyInvalidationKind::SlottedElements,
177        Combinator::Part => NormalDependencyInvalidationKind::Parts,
178    })
179}
180
181impl Dependency {
182    /// Generate a new dependency
183    pub fn new(
184        selector: Selector<SelectorImpl>,
185        selector_offset: usize,
186        next: Option<ThinArc<(), Dependency>>,
187        kind: DependencyInvalidationKind,
188    ) -> Self {
189        Self {
190            selector,
191            selector_offset,
192            next,
193            kind,
194        }
195    }
196    /// Creates a dummy dependency to invalidate the whole selector.
197    ///
198    /// This is necessary because document state invalidation wants to
199    /// invalidate all elements in the document.
200    ///
201    /// The offset is such as that Invalidation::new(self) returns a zero
202    /// offset. That is, it points to a virtual "combinator" outside of the
203    /// selector, so calling combinator() on such a dependency will panic.
204    pub fn for_full_selector_invalidation(selector: Selector<SelectorImpl>) -> Self {
205        Self {
206            selector_offset: selector.len() + 1,
207            selector,
208            next: None,
209            kind: DependencyInvalidationKind::FullSelector,
210        }
211    }
212
213    /// The kind of normal invalidation that this would generate. The dependency
214    /// in question must be a normal dependency.
215    pub fn normal_invalidation_kind(&self) -> NormalDependencyInvalidationKind {
216        if let DependencyInvalidationKind::Normal(kind) = self.kind {
217            return kind;
218        }
219        unreachable!("Querying normal invalidation kind on non-normal dependency.");
220    }
221
222    /// The kind of relative invalidation that this would generate. The dependency
223    /// in question must be a relative dependency.
224    #[inline(always)]
225    pub fn relative_invalidation_kind(&self) -> RelativeDependencyInvalidationKind {
226        if let DependencyInvalidationKind::Relative(kind) = self.kind {
227            return kind;
228        }
229        unreachable!("Querying relative invalidation kind on non-relative dependency.");
230    }
231
232    /// The kind of invalidation that this would generate.
233    pub fn invalidation_kind(&self) -> DependencyInvalidationKind {
234        self.kind
235    }
236
237    /// Is the combinator to the right of this dependency's compound selector
238    /// the next sibling combinator? This matters for insertion/removal in between
239    /// two elements connected through next sibling, e.g. `.foo:has(> .a + .b)`
240    /// where an element gets inserted between `.a` and `.b`.
241    pub fn right_combinator_is_next_sibling(&self) -> bool {
242        if self.selector_offset == 0 {
243            return false;
244        }
245        matches!(
246            self.selector
247                .combinator_at_match_order(self.selector_offset - 1),
248            Combinator::NextSibling
249        )
250    }
251
252    /// Is this dependency's compound selector a single compound in `:has`
253    /// with the next sibling relative combinator i.e. `:has(> .foo)`?
254    /// This matters for insertion between an anchor and an element
255    /// connected through next sibling, e.g. `.a:has(> .b)`.
256    pub fn dependency_is_relative_with_single_next_sibling(&self) -> bool {
257        match self.invalidation_kind() {
258            DependencyInvalidationKind::Relative(kind) => {
259                kind == RelativeDependencyInvalidationKind::PrevSibling
260            },
261            _ => false,
262        }
263    }
264}
265
266/// The same, but for state selectors, which can track more exactly what state
267/// do they track.
268#[derive(Clone, Debug, MallocSizeOf)]
269pub struct StateDependency {
270    /// The other dependency fields.
271    pub dep: Dependency,
272    /// The state this dependency is affected by.
273    pub state: ElementState,
274}
275
276impl SelectorMapEntry for StateDependency {
277    fn selector(&self) -> SelectorIter<SelectorImpl> {
278        self.dep.selector()
279    }
280}
281
282/// The same, but for document state selectors.
283#[derive(Clone, Debug, MallocSizeOf)]
284pub struct DocumentStateDependency {
285    /// We track `Dependency` even though we don't need to track an offset,
286    /// since when it changes it changes for the whole document anyway.
287    #[cfg_attr(
288        feature = "gecko",
289        ignore_malloc_size_of = "CssRules have primary refs, we measure there"
290    )]
291    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
292    pub dependency: Dependency,
293    /// The state this dependency is affected by.
294    pub state: DocumentState,
295}
296
297/// Dependency mapping for classes or IDs.
298pub type IdOrClassDependencyMap = MaybeCaseInsensitiveHashMap<Atom, SmallVec<[Dependency; 1]>>;
299/// Dependency mapping for non-tree-strctural pseudo-class states.
300pub type StateDependencyMap = SelectorMap<StateDependency>;
301/// Dependency mapping for local names.
302pub type LocalNameDependencyMap = PrecomputedHashMap<LocalName, SmallVec<[Dependency; 1]>>;
303/// Dependency mapping for customstates
304pub type CustomStateDependencyMap = PrecomputedHashMap<AtomIdent, SmallVec<[Dependency; 1]>>;
305
306/// A map where we store invalidations.
307///
308/// This is slightly different to a SelectorMap, in the sense of that the same
309/// selector may appear multiple times.
310///
311/// In particular, we want to lookup as few things as possible to get the fewer
312/// selectors the better, so this looks up by id, class, or looks at the list of
313/// state/other attribute affecting selectors.
314#[derive(Clone, Debug, MallocSizeOf)]
315pub struct InvalidationMap {
316    /// A map from a given class name to all the selectors with that class
317    /// selector.
318    pub class_to_selector: IdOrClassDependencyMap,
319    /// A map from a given id to all the selectors with that ID in the
320    /// stylesheets currently applying to the document.
321    pub id_to_selector: IdOrClassDependencyMap,
322    /// A map of all the state dependencies.
323    pub state_affecting_selectors: StateDependencyMap,
324    /// A list of document state dependencies in the rules we represent.
325    pub document_state_selectors: Vec<DocumentStateDependency>,
326    /// A map of other attribute affecting selectors.
327    pub other_attribute_affecting_selectors: LocalNameDependencyMap,
328    /// A map of CSS custom states
329    pub custom_state_affecting_selectors: CustomStateDependencyMap,
330}
331
332/// Tree-structural pseudoclasses that we care about for (Relative selector) invalidation.
333/// Specifically, we need to store information on ones that don't generate the inner selector.
334/// Given the nature of these selectors:
335/// * These are only relevant during DOM mutation invalidations
336/// * Some invalidations may be optimized away.
337#[derive(Clone, Copy, Debug, MallocSizeOf)]
338pub struct TSStateForInvalidation(u8);
339
340bitflags! {
341    impl TSStateForInvalidation : u8 {
342        /// :empty. This only needs to be considered for DOM mutation, and for
343        /// elements that do not have any children.
344        const EMPTY = 1 << 0;
345        /// :nth and related selectors, without of.
346        const NTH = 1 << 1;
347        /// :first-child. This only needs to be considered for DOM mutation, and
348        /// for elements that have no previous sibling.
349        const NTH_EDGE_FIRST = 1 << 2;
350        /// :last-child. This only needs to be considered for DOM mutation,
351        /// and for elements have no next sibling.
352        const NTH_EDGE_LAST = 1 << 3;
353    }
354}
355
356impl TSStateForInvalidation {
357    /// Return true if this state invalidation could be skipped (As per comment
358    /// in the definition of this bitflags)
359    pub fn may_be_optimized(&self) -> bool {
360        (Self::EMPTY | Self::NTH_EDGE_FIRST | Self::NTH_EDGE_LAST).contains(*self)
361    }
362}
363
364/// Dependency for tree-structural pseudo-classes.
365#[derive(Clone, Debug, MallocSizeOf)]
366pub struct TSStateDependency {
367    /// The other dependency fields.
368    pub dep: Dependency,
369    /// The state this dependency is affected by.
370    pub state: TSStateForInvalidation,
371}
372
373impl SelectorMapEntry for TSStateDependency {
374    fn selector(&self) -> SelectorIter<SelectorImpl> {
375        self.dep.selector()
376    }
377}
378
379/// Dependency mapping for tree-structural pseudo-class states.
380pub type TSStateDependencyMap = SelectorMap<TSStateDependency>;
381/// Dependency mapping for * selectors.
382pub type AnyDependencyMap = SmallVec<[Dependency; 1]>;
383
384/// A map to store invalidation dependencies specific to relative selectors.
385/// This keeps a lot more data than the usual map, because any change can generate
386/// upward traversals that need to be handled separately.
387#[derive(Clone, Debug, MallocSizeOf)]
388pub struct AdditionalRelativeSelectorInvalidationMap {
389    /// A map for a given tree-structural pseudo-class to all the relative selector dependencies with that type.
390    pub ts_state_to_selector: TSStateDependencyMap,
391    /// A map from a given type name to all the relative selector dependencies with that type.
392    pub type_to_selector: LocalNameDependencyMap,
393    /// All relative selector dependencies that specify `*`.
394    pub any_to_selector: AnyDependencyMap,
395    /// Flag indicating if any relative selector is used.
396    pub used: bool,
397    /// Flag indicating if invalidating a relative selector requires ancestor traversal.
398    pub needs_ancestors_traversal: bool,
399}
400
401impl AdditionalRelativeSelectorInvalidationMap {
402    /// Creates an empty `InvalidationMap`.
403    pub fn new() -> Self {
404        Self {
405            ts_state_to_selector: TSStateDependencyMap::default(),
406            type_to_selector: LocalNameDependencyMap::default(),
407            any_to_selector: SmallVec::default(),
408            used: false,
409            needs_ancestors_traversal: false,
410        }
411    }
412
413    /// Clears this map, leaving it empty.
414    pub fn clear(&mut self) {
415        self.ts_state_to_selector.clear();
416        self.type_to_selector.clear();
417        self.any_to_selector.clear();
418    }
419
420    /// Shrink the capacity of hash maps if needed.
421    pub fn shrink_if_needed(&mut self) {
422        self.ts_state_to_selector.shrink_if_needed();
423        self.type_to_selector.shrink_if_needed();
424    }
425}
426
427impl InvalidationMap {
428    /// Creates an empty `InvalidationMap`.
429    pub fn new() -> Self {
430        Self {
431            class_to_selector: IdOrClassDependencyMap::new(),
432            id_to_selector: IdOrClassDependencyMap::new(),
433            state_affecting_selectors: StateDependencyMap::new(),
434            document_state_selectors: Vec::new(),
435            other_attribute_affecting_selectors: LocalNameDependencyMap::default(),
436            custom_state_affecting_selectors: CustomStateDependencyMap::default(),
437        }
438    }
439
440    /// Returns the number of dependencies stored in the invalidation map.
441    pub fn len(&self) -> usize {
442        self.state_affecting_selectors.len()
443            + self.document_state_selectors.len()
444            + self
445                .other_attribute_affecting_selectors
446                .iter()
447                .fold(0, |accum, (_, ref v)| accum + v.len())
448            + self
449                .id_to_selector
450                .iter()
451                .fold(0, |accum, (_, ref v)| accum + v.len())
452            + self
453                .class_to_selector
454                .iter()
455                .fold(0, |accum, (_, ref v)| accum + v.len())
456            + self
457                .custom_state_affecting_selectors
458                .iter()
459                .fold(0, |accum, (_, ref v)| accum + v.len())
460    }
461
462    /// Clears this map, leaving it empty.
463    pub fn clear(&mut self) {
464        self.class_to_selector.clear();
465        self.id_to_selector.clear();
466        self.state_affecting_selectors.clear();
467        self.document_state_selectors.clear();
468        self.other_attribute_affecting_selectors.clear();
469        self.custom_state_affecting_selectors.clear();
470    }
471
472    /// Shrink the capacity of hash maps if needed.
473    pub fn shrink_if_needed(&mut self) {
474        self.class_to_selector.shrink_if_needed();
475        self.id_to_selector.shrink_if_needed();
476        self.state_affecting_selectors.shrink_if_needed();
477        self.other_attribute_affecting_selectors.shrink_if_needed();
478        self.custom_state_affecting_selectors.shrink_if_needed();
479    }
480}
481
482/// Adds a selector to the given `InvalidationMap`. Returns Err(..) to signify OOM.
483pub fn note_selector_for_invalidation(
484    selector: &Selector<SelectorImpl>,
485    quirks_mode: QuirksMode,
486    map: &mut InvalidationMap,
487    relative_selector_invalidation_map: &mut InvalidationMap,
488    additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
489    inner_scope_dependencies: Option<&ThinArc<(), Dependency>>,
490) -> Result<Option<Vec<Dependency>>, AllocErr> {
491    let next_dependency = Dependency::for_full_selector_invalidation(selector.clone());
492    let mut document_state = DocumentState::empty();
493    let mut scope_dependencies = ScopeSelectorCollectorState {
494        inner_dependencies: &inner_scope_dependencies.cloned(),
495        this_dependencies: None,
496    };
497
498    {
499        let mut next_stack = NextSelectors::new();
500        let mut alloc_error = None;
501        let mut collector = SelectorDependencyCollector {
502            map,
503            relative_selector_invalidation_map,
504            additional_relative_selector_invalidation_map,
505            document_state: &mut document_state,
506            selector,
507            next_selectors: &mut next_stack,
508            quirks_mode,
509            compound_state: PerCompoundState::new(0),
510            relative_inner_collector: None,
511            scope_dependencies: &mut scope_dependencies,
512            alloc_error: &mut alloc_error,
513        };
514
515        let visit_result = collector.visit_whole_selector();
516
517        debug_assert_eq!(!visit_result, alloc_error.is_some());
518        if let Some(alloc_error) = alloc_error {
519            return Err(alloc_error);
520        }
521    }
522
523    if !document_state.is_empty() {
524        let dep = DocumentStateDependency {
525            state: document_state,
526            dependency: next_dependency,
527        };
528        map.document_state_selectors.try_reserve(1)?;
529        map.document_state_selectors.push(dep);
530    }
531    Ok(scope_dependencies.this_dependencies)
532}
533
534struct PerCompoundState {
535    /// The offset at which our compound starts.
536    offset: usize,
537
538    /// The state this compound selector is affected by.
539    element_state: ElementState,
540}
541
542impl PerCompoundState {
543    fn new(offset: usize) -> Self {
544        Self {
545            offset,
546            element_state: ElementState::empty(),
547        }
548    }
549}
550
551struct NextDependencyEntry {
552    selector: Selector<SelectorImpl>,
553    offset: usize,
554    cached_dependency: Option<ThinArc<(), Dependency>>,
555}
556
557struct RelativeSelectorInnerCollectorState<'a> {
558    next_dependency: &'a ThinArc<(), Dependency>,
559    relative_compound_state: RelativeSelectorCompoundStateAttributes,
560}
561struct ScopeSelectorCollectorState<'a> {
562    // Inner scope dependencies this scope selector need to point to
563    inner_dependencies: &'a Option<ThinArc<(), Dependency>>,
564    // Scope dependencies added by this scope selector
565    this_dependencies: Option<Vec<Dependency>>,
566}
567
568trait Collector {
569    fn dependency(&mut self) -> Dependency;
570    fn id_map(&mut self) -> &mut IdOrClassDependencyMap;
571    fn class_map(&mut self) -> &mut IdOrClassDependencyMap;
572    fn state_map(&mut self) -> &mut StateDependencyMap;
573    fn attribute_map(&mut self) -> &mut LocalNameDependencyMap;
574    fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap;
575    fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>>;
576    fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>>;
577    fn update_states(&mut self, element_state: ElementState, document_state: DocumentState);
578
579    // In normal invalidations, type-based dependencies don't need to be explicitly tracked;
580    // elements don't change their types, and mutations cause invalidations to go descendant
581    // (Where they are about to be styled anyway), and/or later-sibling direction (Where they
582    // siblings after inserted/removed elements get restyled anyway).
583    // However, for relative selectors, a DOM mutation can affect and arbitrary ancestor and/or
584    // earlier siblings, so we need to keep track of them.
585    fn type_map(&mut self) -> &mut LocalNameDependencyMap {
586        unreachable!();
587    }
588
589    // Tree-structural pseudo-selectors generally invalidates in a well-defined way, which are
590    // handled by RestyleManager. However, for relative selectors, as with type invalidations,
591    // the direction of invalidation becomes arbitrary, so we need to keep track of them.
592    fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
593        unreachable!();
594    }
595
596    // Same story as type invalidation maps.
597    fn any_vec(&mut self) -> &mut AnyDependencyMap {
598        unreachable!();
599    }
600}
601
602fn on_attribute<C: Collector>(
603    local_name: &LocalName,
604    local_name_lower: &LocalName,
605    collector: &mut C,
606) -> Result<(), AllocErr> {
607    add_attr_dependency(local_name.clone(), collector)?;
608    if local_name != local_name_lower {
609        add_attr_dependency(local_name_lower.clone(), collector)?;
610    }
611    Ok(())
612}
613
614fn on_id_or_class<C: Collector>(
615    s: &Component<SelectorImpl>,
616    quirks_mode: QuirksMode,
617    collector: &mut C,
618) -> Result<(), AllocErr> {
619    let dependency = collector.dependency();
620
621    let (atom, map) = match *s {
622        Component::ID(ref atom) => (atom, collector.id_map()),
623        Component::Class(ref atom) => (atom, collector.class_map()),
624        _ => unreachable!(),
625    };
626    let entry = map.try_entry(atom.0.clone(), quirks_mode)?;
627    let vec = entry.or_insert_with(SmallVec::new);
628    vec.try_reserve(1)?;
629    vec.push(dependency);
630    Ok(())
631}
632
633fn on_scope<C: Collector>(collector: &mut C) -> Result<(), AllocErr> {
634    let new_dependency = collector.dependency();
635    let this_scope_dependencies = collector.this_scope_dependencies();
636
637    this_scope_dependencies
638        .get_or_insert(Vec::new())
639        .push(new_dependency);
640
641    Ok(())
642}
643
644fn add_attr_dependency<C: Collector>(name: LocalName, collector: &mut C) -> Result<(), AllocErr> {
645    let dependency = collector.dependency();
646    let map = collector.attribute_map();
647    add_local_name(name, dependency, map)
648}
649
650fn add_custom_state_dependency<C: Collector>(
651    name: AtomIdent,
652    collector: &mut C,
653) -> Result<(), AllocErr> {
654    let dependency = collector.dependency();
655    let map = collector.custom_state_map();
656    map.try_reserve(1)?;
657    let vec = map.entry(name).or_default();
658    vec.try_reserve(1)?;
659    vec.push(dependency);
660    Ok(())
661}
662
663fn add_local_name(
664    name: LocalName,
665    dependency: Dependency,
666    map: &mut LocalNameDependencyMap,
667) -> Result<(), AllocErr> {
668    map.try_reserve(1)?;
669    let vec = map.entry(name).or_default();
670    vec.try_reserve(1)?;
671    vec.push(dependency);
672    Ok(())
673}
674
675fn on_pseudo_class<C: Collector>(pc: &NonTSPseudoClass, collector: &mut C) -> Result<(), AllocErr> {
676    collector.update_states(pc.state_flag(), pc.document_state_flag());
677
678    let attr_name = match *pc {
679        #[cfg(feature = "gecko")]
680        NonTSPseudoClass::MozTableBorderNonzero => local_name!("border"),
681        #[cfg(feature = "gecko")]
682        NonTSPseudoClass::MozSelectListBox => {
683            // This depends on two attributes.
684            add_attr_dependency(local_name!("multiple"), collector)?;
685            return add_attr_dependency(local_name!("size"), collector);
686        },
687        NonTSPseudoClass::Lang(..) => local_name!("lang"),
688        NonTSPseudoClass::CustomState(ref name) => {
689            return add_custom_state_dependency(name.0.clone(), collector);
690        },
691        _ => return Ok(()),
692    };
693
694    add_attr_dependency(attr_name, collector)
695}
696
697fn add_pseudo_class_dependency<C: Collector>(
698    element_state: ElementState,
699    quirks_mode: QuirksMode,
700    collector: &mut C,
701) -> Result<(), AllocErr> {
702    if element_state.is_empty() {
703        return Ok(());
704    }
705    let dependency = collector.dependency();
706    collector.state_map().insert(
707        StateDependency {
708            dep: dependency,
709            state: element_state,
710        },
711        quirks_mode,
712    )
713}
714
715/// Visit all the simple selectors in the iter compound
716/// and return the number of simple selectors visited.
717/// We need to return a tuple because we need to keep
718/// track of two things:
719/// 1) Should the traversal continue and
720/// 2) What the offset of the compound state is.
721fn visit_all_in_iter_compound<T: SelectorVisitor<Impl = SelectorImpl>>(
722    visitor: &mut T,
723    iter: &mut SelectorIter<'_, SelectorImpl>,
724) -> (bool, usize) {
725    let mut index = 0;
726    for ss in iter {
727        if !ss.visit(visitor) {
728            return (false, index);
729        }
730        index += 1;
731    }
732    (true, index)
733}
734
735type NextSelectors = SmallVec<[NextDependencyEntry; 5]>;
736
737/// A struct that collects invalidations for a given compound selector.
738struct SelectorDependencyCollector<'a, 'b, 'c> {
739    map: &'a mut InvalidationMap,
740    relative_selector_invalidation_map: &'a mut InvalidationMap,
741    additional_relative_selector_invalidation_map:
742        &'a mut AdditionalRelativeSelectorInvalidationMap,
743
744    /// The document this _complex_ selector is affected by.
745    ///
746    /// We don't need to track state per compound selector, since it's global
747    /// state and it changes for everything.
748    document_state: &'a mut DocumentState,
749
750    /// The current selector and offset we're iterating.
751    selector: &'a Selector<SelectorImpl>,
752
753    /// The stack of next selectors that we have, and at which offset of the
754    /// sequence.
755    ///
756    /// This starts empty. It grows when we find nested :is and :where selector
757    /// lists. The dependency field is cached and reference counted.
758    next_selectors: &'a mut NextSelectors,
759
760    /// The quirks mode of the document where we're inserting dependencies.
761    quirks_mode: QuirksMode,
762
763    /// State relevant to a given compound selector.
764    compound_state: PerCompoundState,
765
766    /// Additional state to keep track of for collecting nested inner selectors of relative selectors
767    /// Holds the next relative selector dependency and the state given to a relative selector.
768    relative_inner_collector: Option<RelativeSelectorInnerCollectorState<'b>>,
769
770    scope_dependencies: &'a mut ScopeSelectorCollectorState<'c>,
771
772    /// The allocation error, if we OOM.
773    alloc_error: &'a mut Option<AllocErr>,
774}
775
776fn next_dependency(
777    next_selector: &mut NextSelectors,
778    next_outer_dependency: Option<&ThinArc<(), Dependency>>,
779    next_scope_dependencies: Option<&ThinArc<(), Dependency>>,
780) -> Option<ThinArc<(), Dependency>> {
781    if next_selector.is_empty() {
782        return match next_outer_dependency {
783            Some(..) => next_outer_dependency.cloned(),
784            None => next_scope_dependencies.cloned(),
785        };
786    }
787
788    fn dependencies_from(
789        entries: &mut [NextDependencyEntry],
790        next_outer_dependency: &Option<&ThinArc<(), Dependency>>,
791        next_scope_dependencies: &Option<&ThinArc<(), Dependency>>,
792    ) -> Option<ThinArc<(), Dependency>> {
793        if entries.is_empty() {
794            return next_scope_dependencies.cloned();
795        }
796
797        let last_index = entries.len() - 1;
798        let (previous, last) = entries.split_at_mut(last_index);
799        let last = &mut last[0];
800        let selector = &last.selector;
801        let selector_offset = last.offset;
802
803        let dependency = Dependency {
804            selector: selector.clone(),
805            selector_offset,
806            next: dependencies_from(previous, next_outer_dependency, next_scope_dependencies),
807            kind: get_non_relative_invalidation_kind(
808                selector,
809                selector_offset,
810                next_scope_dependencies.is_some(),
811            ),
812        };
813
814        Some(
815            last.cached_dependency
816                .get_or_insert_with(|| ThinArc::from_header_and_iter((), [dependency].into_iter()))
817                .clone(),
818        )
819    }
820
821    dependencies_from(
822        next_selector,
823        &next_outer_dependency,
824        &next_scope_dependencies,
825    )
826}
827
828impl<'a, 'b, 'c> Collector for SelectorDependencyCollector<'a, 'b, 'c> {
829    fn dependency(&mut self) -> Dependency {
830        let optional_dependency = self
831            .relative_inner_collector
832            .as_ref()
833            .map(|collector| collector.next_dependency);
834
835        let offset = self.compound_state.offset;
836
837        let scope_dependencies = self.inner_scope_dependencies();
838
839        let next = next_dependency(
840            self.next_selectors,
841            optional_dependency,
842            scope_dependencies.as_ref(),
843        );
844
845        Dependency {
846            selector: self.selector.clone(),
847            selector_offset: offset,
848            next: next,
849            kind: get_non_relative_invalidation_kind(
850                self.selector,
851                offset,
852                scope_dependencies.is_some(),
853            ),
854        }
855    }
856
857    fn id_map(&mut self) -> &mut IdOrClassDependencyMap {
858        if self.relative_inner_collector.is_none() {
859            &mut self.map.id_to_selector
860        } else {
861            &mut self.relative_selector_invalidation_map.id_to_selector
862        }
863    }
864
865    fn class_map(&mut self) -> &mut IdOrClassDependencyMap {
866        if self.relative_inner_collector.is_none() {
867            &mut self.map.class_to_selector
868        } else {
869            &mut self.relative_selector_invalidation_map.class_to_selector
870        }
871    }
872
873    fn state_map(&mut self) -> &mut StateDependencyMap {
874        if self.relative_inner_collector.is_none() {
875            &mut self.map.state_affecting_selectors
876        } else {
877            &mut self
878                .relative_selector_invalidation_map
879                .state_affecting_selectors
880        }
881    }
882
883    fn attribute_map(&mut self) -> &mut LocalNameDependencyMap {
884        if self.relative_inner_collector.is_none() {
885            &mut self.map.other_attribute_affecting_selectors
886        } else {
887            &mut self
888                .relative_selector_invalidation_map
889                .other_attribute_affecting_selectors
890        }
891    }
892
893    fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>> {
894        self.scope_dependencies.inner_dependencies.clone()
895    }
896
897    fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>> {
898        &mut self.scope_dependencies.this_dependencies
899    }
900
901    fn update_states(&mut self, element_state: ElementState, document_state: DocumentState) {
902        self.compound_state.element_state |= element_state;
903        *self.document_state |= document_state;
904    }
905
906    fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap {
907        if self.relative_inner_collector.is_none() {
908            &mut self.map.custom_state_affecting_selectors
909        } else {
910            &mut self
911                .relative_selector_invalidation_map
912                .custom_state_affecting_selectors
913        }
914    }
915
916    fn type_map(&mut self) -> &mut LocalNameDependencyMap {
917        debug_assert!(
918            self.relative_inner_collector.is_some(),
919            "Asking for relative selector invalidation outside of relative selector"
920        );
921        &mut self
922            .additional_relative_selector_invalidation_map
923            .type_to_selector
924    }
925
926    fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
927        debug_assert!(
928            self.relative_inner_collector.is_some(),
929            "Asking for relative selector invalidation outside of relative selector"
930        );
931        &mut self
932            .additional_relative_selector_invalidation_map
933            .ts_state_to_selector
934    }
935
936    fn any_vec(&mut self) -> &mut AnyDependencyMap {
937        debug_assert!(
938            self.relative_inner_collector.is_some(),
939            "Asking for relative selector invalidation outside of relative selector"
940        );
941        &mut self
942            .additional_relative_selector_invalidation_map
943            .any_to_selector
944    }
945}
946
947impl<'a, 'b, 'c> SelectorDependencyCollector<'a, 'b, 'c> {
948    fn visit_whole_selector(&mut self) -> bool {
949        let iter = self.selector.iter();
950        self.visit_whole_selector_from(iter, 0)
951    }
952
953    fn visit_whole_selector_from(
954        &mut self,
955        mut iter: SelectorIter<SelectorImpl>,
956        mut index: usize,
957    ) -> bool {
958        loop {
959            // Reset the compound state.
960            self.compound_state = PerCompoundState::new(index);
961            if let Some(state) = self.relative_inner_collector.as_mut() {
962                state.relative_compound_state = RelativeSelectorCompoundStateAttributes::new();
963            }
964
965            // Visit all the simple selectors in this sequence.
966            let (keep_traversing, index_offset) = visit_all_in_iter_compound(self, &mut iter);
967
968            if !keep_traversing {
969                return false;
970            }
971
972            index += index_offset;
973
974            if let Err(err) = add_pseudo_class_dependency(
975                self.compound_state.element_state,
976                self.quirks_mode,
977                self,
978            ) {
979                *self.alloc_error = Some(err);
980                return false;
981            }
982
983            if let Some(state) = self
984                .relative_inner_collector
985                .as_ref()
986                .map(|state| state.relative_compound_state)
987            {
988                if let Err(err) =
989                    add_ts_pseudo_class_dependency(state.ts_state, self.quirks_mode, self)
990                {
991                    *self.alloc_error = Some(err);
992                    return false;
993                }
994
995                if !state.added_entry {
996                    // Not great - we didn't add any uniquely identifiable information.
997                    if let Err(err) =
998                        add_non_unique_info(&self.selector, self.compound_state.offset, self)
999                    {
1000                        *self.alloc_error = Some(err);
1001                        return false;
1002                    }
1003                }
1004            }
1005
1006            let combinator = iter.next_sequence();
1007            if combinator.is_none() {
1008                return true;
1009            }
1010            index += 1; // account for the combinator
1011        }
1012    }
1013}
1014
1015impl<'a, 'b, 'c> SelectorVisitor for SelectorDependencyCollector<'a, 'b, 'c> {
1016    type Impl = SelectorImpl;
1017
1018    fn visit_selector_list(
1019        &mut self,
1020        _list_kind: SelectorListKind,
1021        list: &[Selector<SelectorImpl>],
1022    ) -> bool {
1023        let next_relative_dependency = self
1024            .relative_inner_collector
1025            .is_some()
1026            .then(|| ThinArc::from_header_and_iter((), std::iter::once(self.dependency())));
1027        for selector in list {
1028            // Here we cheat a bit: We can visit the rightmost compound with
1029            // the "outer" visitor, and it'd be fine. This reduces the amount of
1030            // state and attribute invalidations, and we need to check the outer
1031            // selector to the left anyway to avoid over-invalidation, so it
1032            // avoids matching it twice uselessly.
1033            let mut iter = selector.iter();
1034            let saved_added_entry = self
1035                .relative_inner_collector
1036                .as_ref()
1037                .map(|state| state.relative_compound_state.added_entry);
1038
1039            let (keep_traversing, mut index) = visit_all_in_iter_compound(self, &mut iter);
1040
1041            if !keep_traversing {
1042                return false;
1043            }
1044
1045            if let Some(state) = self.relative_inner_collector.as_mut() {
1046                state.relative_compound_state.added_entry = saved_added_entry.unwrap_or_default();
1047            }
1048            let combinator = iter.next_sequence();
1049            if combinator.is_none() {
1050                continue;
1051            }
1052
1053            index += 1; // account for the combinator.
1054
1055            let offset = self.compound_state.offset;
1056
1057            if self.relative_inner_collector.is_none() {
1058                self.next_selectors.push(NextDependencyEntry {
1059                    selector: self.selector.clone(),
1060                    offset: offset,
1061                    cached_dependency: None,
1062                });
1063            }
1064            debug_assert!(
1065                next_relative_dependency.is_some() == self.relative_inner_collector.is_some(),
1066                "Next relative dependency and relative inner collector must be Some/None at the same time!"
1067            );
1068            let mut nested = SelectorDependencyCollector {
1069                map: &mut *self.map,
1070                relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1071                additional_relative_selector_invalidation_map: &mut *self
1072                    .additional_relative_selector_invalidation_map,
1073                document_state: &mut *self.document_state,
1074                selector,
1075                next_selectors: &mut *self.next_selectors,
1076                quirks_mode: self.quirks_mode,
1077                compound_state: PerCompoundState::new(index),
1078                relative_inner_collector: next_relative_dependency.as_ref().map(
1079                    |next_dependency| RelativeSelectorInnerCollectorState {
1080                        next_dependency,
1081                        relative_compound_state: RelativeSelectorCompoundStateAttributes::new(),
1082                    },
1083                ),
1084                scope_dependencies: &mut self.scope_dependencies,
1085                alloc_error: &mut *self.alloc_error,
1086            };
1087            if !nested.visit_whole_selector_from(iter, index) {
1088                return false;
1089            }
1090            self.next_selectors.pop();
1091        }
1092        true
1093    }
1094
1095    fn visit_relative_selector_list(
1096        &mut self,
1097        list: &[selectors::parser::RelativeSelector<Self::Impl>],
1098    ) -> bool {
1099        // Ignore nested relative selectors. This can happen as a result of nesting.
1100        if self.relative_inner_collector.is_some() {
1101            return true;
1102        }
1103
1104        self.additional_relative_selector_invalidation_map.used = true;
1105        for relative_selector in list {
1106            // We can't cheat here like we do with other selector lists - the rightmost
1107            // compound of a relative selector is not the subject of the invalidation.
1108            self.next_selectors.push(NextDependencyEntry {
1109                selector: self.selector.clone(),
1110                offset: self.compound_state.offset,
1111                cached_dependency: None,
1112            });
1113            let mut nested = RelativeSelectorDependencyCollector {
1114                map: &mut *self.map,
1115                relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1116                additional_relative_selector_invalidation_map: &mut *self
1117                    .additional_relative_selector_invalidation_map,
1118                document_state: &mut *self.document_state,
1119                selector: &relative_selector,
1120                combinator_count: RelativeSelectorCombinatorCount::new(relative_selector),
1121                next_selectors: &mut *self.next_selectors,
1122                quirks_mode: self.quirks_mode,
1123                compound_state: PerCompoundState::new(0),
1124                compound_state_attributes: RelativeSelectorCompoundStateAttributes::new(),
1125                scope_dependencies: &mut self.scope_dependencies,
1126                alloc_error: &mut *self.alloc_error,
1127            };
1128            if !nested.visit_whole_selector() {
1129                return false;
1130            }
1131            self.next_selectors.pop();
1132        }
1133        true
1134    }
1135
1136    fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
1137        match on_simple_selector(s, self.quirks_mode, self) {
1138            Ok(result) => {
1139                if let ComponentVisitResult::Handled(state) = result {
1140                    if let Some(inner_collector_state) = self.relative_inner_collector.as_mut() {
1141                        inner_collector_state.relative_compound_state.added_entry = true;
1142                        inner_collector_state
1143                            .relative_compound_state
1144                            .ts_state
1145                            .insert(state);
1146                    }
1147                }
1148                true
1149            },
1150            Err(err) => {
1151                *self.alloc_error = Some(err.into());
1152                false
1153            },
1154        }
1155    }
1156
1157    fn visit_attribute_selector(
1158        &mut self,
1159        _: &NamespaceConstraint<&Namespace>,
1160        local_name: &LocalName,
1161        local_name_lower: &LocalName,
1162    ) -> bool {
1163        if let Some(state) = self.relative_inner_collector.as_mut() {
1164            state.relative_compound_state.added_entry = true;
1165        }
1166        if let Err(err) = on_attribute(local_name, local_name_lower, self) {
1167            *self.alloc_error = Some(err);
1168            return false;
1169        }
1170        true
1171    }
1172}
1173
1174#[derive(Clone, Copy)]
1175struct RelativeSelectorCompoundStateAttributes {
1176    ts_state: TSStateForInvalidation,
1177    added_entry: bool,
1178}
1179
1180impl RelativeSelectorCompoundStateAttributes {
1181    fn new() -> Self {
1182        Self {
1183            ts_state: TSStateForInvalidation::empty(),
1184            added_entry: false,
1185        }
1186    }
1187}
1188
1189/// A struct that collects invalidations for a given compound selector.
1190struct RelativeSelectorDependencyCollector<'a, 'b> {
1191    map: &'a mut InvalidationMap,
1192    relative_selector_invalidation_map: &'a mut InvalidationMap,
1193    additional_relative_selector_invalidation_map:
1194        &'a mut AdditionalRelativeSelectorInvalidationMap,
1195
1196    /// The document this _complex_ selector is affected by.
1197    ///
1198    /// We don't need to track state per compound selector, since it's global
1199    /// state and it changes for everything.
1200    document_state: &'a mut DocumentState,
1201
1202    /// The current inner relative selector and offset we're iterating.
1203    selector: &'a RelativeSelector<SelectorImpl>,
1204    /// Running combinator for this inner relative selector.
1205    combinator_count: RelativeSelectorCombinatorCount,
1206
1207    /// The stack of next selectors that we have, and at which offset of the
1208    /// sequence.
1209    ///
1210    /// This starts empty. It grows when we find nested :is and :where selector
1211    /// lists. The dependency field is cached and reference counted.
1212    next_selectors: &'a mut NextSelectors,
1213
1214    /// The quirks mode of the document where we're inserting dependencies.
1215    quirks_mode: QuirksMode,
1216
1217    /// State relevant to a given compound selector.
1218    compound_state: PerCompoundState,
1219
1220    /// Attributes relevant to the relative compound selector state.
1221    compound_state_attributes: RelativeSelectorCompoundStateAttributes,
1222
1223    scope_dependencies: &'a mut ScopeSelectorCollectorState<'b>,
1224
1225    /// The allocation error, if we OOM.
1226    alloc_error: &'a mut Option<AllocErr>,
1227}
1228
1229fn add_non_unique_info<C: Collector>(
1230    selector: &Selector<SelectorImpl>,
1231    offset: usize,
1232    collector: &mut C,
1233) -> Result<(), AllocErr> {
1234    // Go through this compound again.
1235    for ss in selector.iter_from(offset) {
1236        match ss {
1237            Component::LocalName(ref name) => {
1238                let dependency = collector.dependency();
1239                add_local_name(name.name.clone(), dependency, &mut collector.type_map())?;
1240                if name.name != name.lower_name {
1241                    let dependency = collector.dependency();
1242                    add_local_name(
1243                        name.lower_name.clone(),
1244                        dependency,
1245                        &mut collector.type_map(),
1246                    )?;
1247                }
1248                return Ok(());
1249            },
1250            _ => (),
1251        };
1252    }
1253    // Ouch. Add one for *.
1254    collector.any_vec().try_reserve(1)?;
1255    let dependency = collector.dependency();
1256    collector.any_vec().push(dependency);
1257    Ok(())
1258}
1259
1260fn add_ts_pseudo_class_dependency<C: Collector>(
1261    state: TSStateForInvalidation,
1262    quirks_mode: QuirksMode,
1263    collector: &mut C,
1264) -> Result<(), AllocErr> {
1265    if state.is_empty() {
1266        return Ok(());
1267    }
1268    let dependency = collector.dependency();
1269    collector.ts_state_map().insert(
1270        TSStateDependency {
1271            dep: dependency,
1272            state,
1273        },
1274        quirks_mode,
1275    )
1276}
1277
1278impl<'a, 'b> RelativeSelectorDependencyCollector<'a, 'b> {
1279    fn visit_whole_selector(&mut self) -> bool {
1280        let mut iter = self.selector.selector.iter_skip_relative_selector_anchor();
1281        let mut index = 0;
1282
1283        self.additional_relative_selector_invalidation_map
1284            .needs_ancestors_traversal |= match self.selector.match_hint {
1285            RelativeSelectorMatchHint::InNextSiblingSubtree
1286            | RelativeSelectorMatchHint::InSiblingSubtree
1287            | RelativeSelectorMatchHint::InSubtree => true,
1288            _ => false,
1289        };
1290        loop {
1291            // Reset the compound state.
1292            self.compound_state = PerCompoundState::new(index);
1293
1294            let (keep_traversing, index_offset) = visit_all_in_iter_compound(self, &mut iter);
1295
1296            if !keep_traversing {
1297                return false;
1298            }
1299
1300            index += index_offset;
1301
1302            if let Err(err) = add_pseudo_class_dependency(
1303                self.compound_state.element_state,
1304                self.quirks_mode,
1305                self,
1306            ) {
1307                *self.alloc_error = Some(err);
1308                return false;
1309            }
1310
1311            if let Err(err) = add_ts_pseudo_class_dependency(
1312                self.compound_state_attributes.ts_state,
1313                self.quirks_mode,
1314                self,
1315            ) {
1316                *self.alloc_error = Some(err);
1317                return false;
1318            }
1319
1320            if !self.compound_state_attributes.added_entry {
1321                // Not great - we didn't add any uniquely identifiable information.
1322                if let Err(err) =
1323                    add_non_unique_info(&self.selector.selector, self.compound_state.offset, self)
1324                {
1325                    *self.alloc_error = Some(err);
1326                    return false;
1327                }
1328            }
1329
1330            let combinator = iter.next_sequence();
1331            if let Some(c) = combinator {
1332                match c {
1333                    Combinator::Child | Combinator::Descendant => {
1334                        self.combinator_count.child_or_descendants -= 1
1335                    },
1336                    Combinator::NextSibling | Combinator::LaterSibling => {
1337                        self.combinator_count.adjacent_or_next_siblings -= 1
1338                    },
1339                    Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => (),
1340                }
1341            } else {
1342                return true;
1343            }
1344            index += 1; // account for the combinator
1345        }
1346    }
1347}
1348
1349impl<'a, 'b> Collector for RelativeSelectorDependencyCollector<'a, 'b> {
1350    fn dependency(&mut self) -> Dependency {
1351        let scope_dependencies = self.inner_scope_dependencies();
1352
1353        let next = next_dependency(self.next_selectors, None, scope_dependencies.as_ref());
1354        debug_assert!(
1355            next.as_ref().is_some_and(|d| !matches!(
1356                d.slice()[0].kind,
1357                DependencyInvalidationKind::Relative(_)
1358            )),
1359            "Duplicate relative dependency?"
1360        );
1361        debug_assert!(
1362            next.as_ref().is_some_and(|d| !d.slice().is_empty()),
1363            "Empty dependency?"
1364        );
1365
1366        Dependency {
1367            selector: self.selector.selector.clone(),
1368            selector_offset: self.compound_state.offset,
1369            kind: DependencyInvalidationKind::Relative(
1370                match self.combinator_count.get_match_hint() {
1371                    RelativeSelectorMatchHint::InChild => {
1372                        RelativeDependencyInvalidationKind::Parent
1373                    },
1374                    RelativeSelectorMatchHint::InSubtree => {
1375                        RelativeDependencyInvalidationKind::Ancestors
1376                    },
1377                    RelativeSelectorMatchHint::InNextSibling => {
1378                        RelativeDependencyInvalidationKind::PrevSibling
1379                    },
1380                    RelativeSelectorMatchHint::InSibling => {
1381                        RelativeDependencyInvalidationKind::EarlierSibling
1382                    },
1383                    RelativeSelectorMatchHint::InNextSiblingSubtree => {
1384                        RelativeDependencyInvalidationKind::AncestorPrevSibling
1385                    },
1386                    RelativeSelectorMatchHint::InSiblingSubtree => {
1387                        RelativeDependencyInvalidationKind::AncestorEarlierSibling
1388                    },
1389                },
1390            ),
1391            next: next,
1392        }
1393    }
1394
1395    fn id_map(&mut self) -> &mut IdOrClassDependencyMap {
1396        &mut self.relative_selector_invalidation_map.id_to_selector
1397    }
1398
1399    fn class_map(&mut self) -> &mut IdOrClassDependencyMap {
1400        &mut self.relative_selector_invalidation_map.class_to_selector
1401    }
1402
1403    fn state_map(&mut self) -> &mut StateDependencyMap {
1404        &mut self
1405            .relative_selector_invalidation_map
1406            .state_affecting_selectors
1407    }
1408
1409    fn attribute_map(&mut self) -> &mut LocalNameDependencyMap {
1410        &mut self
1411            .relative_selector_invalidation_map
1412            .other_attribute_affecting_selectors
1413    }
1414
1415    fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap {
1416        &mut self
1417            .relative_selector_invalidation_map
1418            .custom_state_affecting_selectors
1419    }
1420
1421    fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>> {
1422        self.scope_dependencies.inner_dependencies.clone()
1423    }
1424
1425    fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>> {
1426        &mut self.scope_dependencies.this_dependencies
1427    }
1428
1429    fn update_states(&mut self, element_state: ElementState, document_state: DocumentState) {
1430        self.compound_state.element_state |= element_state;
1431        *self.document_state |= document_state;
1432    }
1433
1434    fn type_map(&mut self) -> &mut LocalNameDependencyMap {
1435        &mut self
1436            .additional_relative_selector_invalidation_map
1437            .type_to_selector
1438    }
1439
1440    fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
1441        &mut self
1442            .additional_relative_selector_invalidation_map
1443            .ts_state_to_selector
1444    }
1445
1446    fn any_vec(&mut self) -> &mut AnyDependencyMap {
1447        &mut self
1448            .additional_relative_selector_invalidation_map
1449            .any_to_selector
1450    }
1451}
1452
1453enum ComponentVisitResult {
1454    /// This component is not relevant for building up the invalidation map.
1455    IsIrrelevant,
1456    /// This component has been added to the invalidation map. Any additional
1457    /// tree-structural pseudo-class dependency is also included, if required.
1458    Handled(TSStateForInvalidation),
1459}
1460
1461#[inline(always)]
1462fn on_simple_selector<C: Collector>(
1463    s: &Component<SelectorImpl>,
1464    quirks_mode: QuirksMode,
1465    collector: &mut C,
1466) -> Result<ComponentVisitResult, AllocErr> {
1467    match *s {
1468        Component::ID(..) | Component::Class(..) => {
1469            on_id_or_class(s, quirks_mode, collector)?;
1470            Ok(ComponentVisitResult::Handled(
1471                TSStateForInvalidation::empty(),
1472            ))
1473        },
1474        Component::ImplicitScope | Component::Scope => {
1475            on_scope(collector)?;
1476            Ok(ComponentVisitResult::Handled(
1477                TSStateForInvalidation::empty(),
1478            ))
1479        },
1480        Component::NonTSPseudoClass(ref pc) => {
1481            on_pseudo_class(pc, collector)?;
1482            Ok(ComponentVisitResult::Handled(
1483                TSStateForInvalidation::empty(),
1484            ))
1485        },
1486        Component::Empty => Ok(ComponentVisitResult::Handled(TSStateForInvalidation::EMPTY)),
1487        Component::Nth(data) => {
1488            let kind = if data.is_simple_edge() {
1489                if data.ty.is_from_end() {
1490                    TSStateForInvalidation::NTH_EDGE_LAST
1491                } else {
1492                    TSStateForInvalidation::NTH_EDGE_FIRST
1493                }
1494            } else {
1495                TSStateForInvalidation::NTH
1496            };
1497            Ok(ComponentVisitResult::Handled(kind))
1498        },
1499        Component::RelativeSelectorAnchor => unreachable!("Should not visit this far"),
1500        _ => Ok(ComponentVisitResult::IsIrrelevant),
1501    }
1502}
1503
1504impl<'a, 'b> SelectorVisitor for RelativeSelectorDependencyCollector<'a, 'b> {
1505    type Impl = SelectorImpl;
1506
1507    fn visit_selector_list(
1508        &mut self,
1509        _list_kind: SelectorListKind,
1510        list: &[Selector<SelectorImpl>],
1511    ) -> bool {
1512        let mut next_stack = NextSelectors::new();
1513        let next_dependency = ThinArc::from_header_and_iter((), [self.dependency()].into_iter());
1514        for selector in list {
1515            let mut iter = selector.iter();
1516            let saved_added_entry = self.compound_state_attributes.added_entry;
1517
1518            let (keep_traversing, mut index) = visit_all_in_iter_compound(self, &mut iter);
1519
1520            if !keep_traversing {
1521                return false;
1522            }
1523
1524            let combinator = iter.next_sequence();
1525
1526            // We want to preserve added_entry, to handle all DOM manipulations
1527            // correctly. For example, given `.anchor:has(:not(.foo))`, and a
1528            // DOM tree `.anchor > .foo`, insertion of _any_ element without
1529            // `.foo` as `.anchor`'s child must trigger an invalidation.
1530            self.compound_state_attributes.added_entry = saved_added_entry;
1531            if combinator.is_none() {
1532                continue;
1533            }
1534
1535            index += 1; // account for the combinator.
1536
1537            let mut nested = SelectorDependencyCollector {
1538                map: &mut *self.map,
1539                relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1540                additional_relative_selector_invalidation_map: self
1541                    .additional_relative_selector_invalidation_map,
1542                document_state: &mut *self.document_state,
1543                selector,
1544                next_selectors: &mut next_stack,
1545                quirks_mode: self.quirks_mode,
1546                compound_state: PerCompoundState::new(index),
1547                relative_inner_collector: Some(RelativeSelectorInnerCollectorState {
1548                    next_dependency: &next_dependency,
1549                    relative_compound_state: RelativeSelectorCompoundStateAttributes::new(),
1550                }),
1551                scope_dependencies: &mut self.scope_dependencies,
1552                alloc_error: &mut *self.alloc_error,
1553            };
1554            if !nested.visit_whole_selector_from(iter, index) {
1555                return false;
1556            }
1557        }
1558        true
1559    }
1560
1561    fn visit_relative_selector_list(
1562        &mut self,
1563        _list: &[selectors::parser::RelativeSelector<Self::Impl>],
1564    ) -> bool {
1565        // Ignore nested relative selectors. These can happen as a result of nesting.
1566        true
1567    }
1568
1569    fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
1570        match on_simple_selector(s, self.quirks_mode, self) {
1571            Ok(result) => {
1572                if let ComponentVisitResult::Handled(state) = result {
1573                    self.compound_state_attributes.added_entry = true;
1574                    self.compound_state_attributes.ts_state.insert(state);
1575                }
1576                true
1577            },
1578            Err(err) => {
1579                *self.alloc_error = Some(err.into());
1580                false
1581            },
1582        }
1583    }
1584
1585    fn visit_attribute_selector(
1586        &mut self,
1587        _: &NamespaceConstraint<&Namespace>,
1588        local_name: &LocalName,
1589        local_name_lower: &LocalName,
1590    ) -> bool {
1591        self.compound_state_attributes.added_entry = true;
1592        if let Err(err) = on_attribute(local_name, local_name_lower, self) {
1593            *self.alloc_error = Some(err);
1594            return false;
1595        }
1596        true
1597    }
1598}