tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

relative_selector.rs (55526B)


      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 //! Invalidation of element styles relative selectors.
      6 
      7 use crate::data::ElementData;
      8 use crate::dom::{TElement, TNode};
      9 #[cfg(feature = "gecko")]
     10 use crate::gecko_bindings::structs::ServoElementSnapshotTable;
     11 use crate::invalidation::element::element_wrapper::ElementWrapper;
     12 use crate::invalidation::element::invalidation_map::{
     13    AdditionalRelativeSelectorInvalidationMap, Dependency, DependencyInvalidationKind,
     14    InvalidationMap, NormalDependencyInvalidationKind, RelativeDependencyInvalidationKind,
     15    ScopeDependencyInvalidationKind, TSStateForInvalidation,
     16 };
     17 use crate::invalidation::element::invalidator::{
     18    note_scope_dependency_force_at_subject, DescendantInvalidationLists, Invalidation,
     19    InvalidationProcessor, InvalidationResult, InvalidationVector, SiblingTraversalMap,
     20    TreeStyleInvalidator,
     21 };
     22 use crate::invalidation::element::restyle_hints::RestyleHint;
     23 use crate::invalidation::element::state_and_attributes::{
     24    check_dependency, dependency_may_be_relevant, invalidated_descendants, invalidated_self,
     25    invalidated_sibling, push_invalidation, should_process_descendants,
     26 };
     27 #[cfg(feature = "servo")]
     28 use crate::selector_parser::SnapshotMap as ServoElementSnapshotTable;
     29 use crate::stylist::{CascadeData, Stylist};
     30 use dom::ElementState;
     31 use rustc_hash::FxHashMap;
     32 use selectors::matching::{
     33    early_reject_by_local_name, matches_selector, ElementSelectorFlags,
     34    IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
     35    NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
     36 };
     37 use selectors::parser::SelectorKey;
     38 use selectors::OpaqueElement;
     39 use smallvec::{smallvec, SmallVec};
     40 use std::ops::DerefMut;
     41 
     42 /// Kind of DOM mutation this relative selector invalidation is being carried out in.
     43 #[derive(Clone, Copy)]
     44 pub enum DomMutationOperation {
     45    /// Insertion operation, can cause side effect, but presumed already happened.
     46    Insert,
     47    /// Append operation, cannot cause side effect.
     48    Append,
     49    /// Removal operation, can cause side effect, but presumed already happened. Sibling relationships are destroyed.
     50    Remove,
     51    /// Invalidating for side effect of a DOM operation, for the previous sibling.
     52    SideEffectPrevSibling,
     53    /// Invalidating for side effect of a DOM operation, for the next sibling.
     54    SideEffectNextSibling,
     55 }
     56 
     57 impl DomMutationOperation {
     58    fn accept<E: TElement>(&self, d: &Dependency, e: E) -> bool {
     59        match self {
     60            Self::Insert | Self::Append | Self::Remove => {
     61                !e.relative_selector_search_direction().is_empty()
     62            },
     63            // `:has(+ .a + .b)` with `.anchor + .a + .remove + .b` - `.a` would be present
     64            // in the search path.
     65            Self::SideEffectPrevSibling => {
     66                !e.relative_selector_search_direction().is_empty()
     67                    && d.right_combinator_is_next_sibling()
     68            },
     69            // If an element is being removed and would cause next-sibling match to happen,
     70            // e.g. `:has(+ .a)` with `.anchor + .remove + .a`, `.a` isn't yet searched
     71            // for relative selector matching.
     72            Self::SideEffectNextSibling => d.dependency_is_relative_with_single_next_sibling(),
     73        }
     74    }
     75 
     76    fn is_side_effect(&self) -> bool {
     77        match self {
     78            Self::Insert | Self::Append | Self::Remove => false,
     79            Self::SideEffectPrevSibling | Self::SideEffectNextSibling => true,
     80        }
     81    }
     82 }
     83 
     84 /// Context required to try and optimize away relative dependencies.
     85 struct OptimizationContext<'a, E: TElement> {
     86    sibling_traversal_map: &'a SiblingTraversalMap<E>,
     87    quirks_mode: QuirksMode,
     88    operation: DomMutationOperation,
     89 }
     90 
     91 impl<'a, E: TElement> OptimizationContext<'a, E> {
     92    fn can_be_ignored(
     93        &self,
     94        is_subtree: bool,
     95        element: E,
     96        host: Option<OpaqueElement>,
     97        dependency: &Dependency,
     98        leftmost_collapse_offset: usize,
     99    ) -> bool {
    100        if is_subtree {
    101            // Subtree elements don't have unaffected sibling to look at.
    102            return false;
    103        }
    104        debug_assert!(
    105            matches!(
    106                dependency.invalidation_kind(),
    107                DependencyInvalidationKind::Relative(..)
    108            ),
    109            "Non-relative selector being evaluated for optimization"
    110        );
    111        // This optimization predecates on the fact that there may be a sibling that can readily
    112        // "take over" this element.
    113        let sibling = match self.sibling_traversal_map.prev_sibling_for(&element) {
    114            None => {
    115                if matches!(self.operation, DomMutationOperation::Append) {
    116                    return false;
    117                }
    118                match self.sibling_traversal_map.next_sibling_for(&element) {
    119                    Some(s) => s,
    120                    None => return false,
    121                }
    122            },
    123            Some(s) => s,
    124        };
    125        {
    126            // Run through the affected compund.
    127            let mut iter = dependency.selector.iter_from(dependency.selector_offset);
    128            while let Some(c) = iter.next() {
    129                if c.has_indexed_selector_in_subject() {
    130                    // We do not calculate indices during invalidation as they're wasteful - as a side effect,
    131                    // such selectors always return true, breaking this optimization. Note that we only check
    132                    // this compound only because the check to skip compares against this element's sibling.
    133                    // i.e. Given `:has(:nth-child(2) .foo)`, we'd try to find `.foo`'s sibling, which
    134                    // shares `:nth-child` up the selector.
    135                    return false;
    136                }
    137            }
    138        }
    139        let dependency_is_rightmost = dependency.selector_offset == 0;
    140        if !dependency_is_rightmost {
    141            let combinator = dependency
    142                .selector
    143                .combinator_at_match_order(dependency.selector_offset - 1);
    144            if combinator.is_ancestor() {
    145                // We can safely ignore these, since we're about to traverse the
    146                // rest of the affected tree anyway to find the rightmost invalidated element.
    147                return true;
    148            }
    149            if combinator.is_sibling() && matches!(self.operation, DomMutationOperation::Append) {
    150                // If we're at the top of the DOM tree being mutated, we can ignore it if the
    151                // operation is append - we know we'll cover all the later siblings and their descendants.
    152                return true;
    153            }
    154        }
    155 
    156        // We have a situation like `:has(.item .item + .item + .item)`, where the first element in the sibling
    157        // chain position (i.e. The element matched by the second `.item` from the left) mutates. By the time we
    158        // get here, we've collapsed the 4 dependencies for each of `.item` position into one at the rightmost
    159        // position. Before we look for a standin, we need to find which `.item` this element matches - Doing
    160        // that would generate more work than it saves.
    161        if dependency_is_rightmost
    162            && leftmost_collapse_offset != dependency.selector_offset
    163            && self
    164                .sibling_traversal_map
    165                .next_sibling_for(&element)
    166                .is_some()
    167        {
    168            return false;
    169        }
    170 
    171        let mut caches = SelectorCaches::default();
    172        let mut matching_context = MatchingContext::new(
    173            MatchingMode::Normal,
    174            None,
    175            &mut caches,
    176            self.quirks_mode,
    177            NeedsSelectorFlags::No,
    178            MatchingForInvalidation::Yes,
    179        );
    180        matching_context.current_host = host;
    181        let sibling_matches = matches_selector(
    182            &dependency.selector,
    183            dependency.selector_offset,
    184            None,
    185            &sibling,
    186            &mut matching_context,
    187        );
    188        if sibling_matches {
    189            // Remember that at this point, we know that the combinator to the right of this
    190            // compound is a sibling combinator. Effectively, we've found a standin for the
    191            // element we're mutating.
    192            // e.g. Given `:has(... .a ~ .b ...)`, we're the mutating element matching `... .a`,
    193            // if we find a sibling that matches the `... .a`, it can stand in for us.
    194            debug_assert!(
    195                dependency.next.is_some(),
    196                "No relative selector outer dependency?"
    197            );
    198            return dependency.next.as_ref().map_or(false, |deps| {
    199                // ... However, if the standin sibling can be the anchor, we can't skip it, since
    200                // that sibling should be invlidated to become the anchor.
    201                let next = &deps.as_ref().slice()[0];
    202                !matches_selector(
    203                    &next.selector,
    204                    next.selector_offset,
    205                    None,
    206                    &sibling,
    207                    &mut matching_context,
    208                )
    209            });
    210        }
    211        // Ok, there's no standin element - but would this element have matched the upstream
    212        // selector anyway? If we don't, either the match exists somewhere far from us
    213        // (In which case our mutation doesn't really matter), or it doesn't exist at all,
    214        // so we can just skip the invalidation.
    215        let (combinator, prev_offset) = {
    216            let mut iter = dependency.selector.iter_from(dependency.selector_offset);
    217            let mut o = dependency.selector_offset;
    218            while iter.next().is_some() {
    219                o += 1;
    220            }
    221            let combinator = iter.next_sequence();
    222            o += 1;
    223            debug_assert!(
    224                combinator.is_some(),
    225                "Should at least see a relative combinator"
    226            );
    227            (combinator.unwrap(), o)
    228        };
    229        if combinator.is_sibling() && prev_offset >= dependency.selector.len() - 1 {
    230            // Hit the relative combinator - we don't have enough information to
    231            // see if there's going to be a downstream match.
    232            return false;
    233        }
    234        !matches_selector(
    235            &dependency.selector,
    236            dependency.selector_offset,
    237            None,
    238            &element,
    239            &mut matching_context,
    240        )
    241    }
    242 }
    243 
    244 /// Overall invalidator for handling relative selector invalidations.
    245 pub struct RelativeSelectorInvalidator<'a, 'b, E>
    246 where
    247    E: TElement + 'a,
    248 {
    249    /// Element triggering the invalidation.
    250    pub element: E,
    251    /// Quirks mode of the current invalidation.
    252    pub quirks_mode: QuirksMode,
    253    /// Snapshot containing changes to invalidate against.
    254    /// Can be None if it's a DOM mutation.
    255    pub snapshot_table: Option<&'b ServoElementSnapshotTable>,
    256    /// Callback to trigger when the subject element is invalidated.
    257    pub invalidated: fn(E, &InvalidationResult),
    258    /// The traversal map that should be used to process invalidations.
    259    pub sibling_traversal_map: SiblingTraversalMap<E>,
    260    /// Marker for 'a lifetime.
    261    pub _marker: ::std::marker::PhantomData<&'a ()>,
    262 }
    263 
    264 struct RelativeSelectorInvalidation<'a> {
    265    host: Option<OpaqueElement>,
    266    kind: RelativeDependencyInvalidationKind,
    267    dependency: &'a Dependency,
    268 }
    269 
    270 type ElementDependencies<'a> = SmallVec<[(Option<OpaqueElement>, &'a Dependency); 1]>;
    271 type Dependencies<'a, E> = SmallVec<[(E, ElementDependencies<'a>); 1]>;
    272 type AlreadyInvalidated<'a, E> = SmallVec<[AlreadyInvalidatedEntry<'a, E>; 2]>;
    273 
    274 struct AlreadyInvalidatedEntry<'a, E>
    275 where
    276    E: TElement + 'a,
    277 {
    278    /// Element where the invalidation will begin.
    279    element: E,
    280    /// The current shadow host.
    281    host: Option<OpaqueElement>,
    282    /// Dependency chain for this invalidation.
    283    dependency: &'a Dependency,
    284    /// The offset, of the leftmost dependencies that this
    285    /// invalidation collapsed. See the `update()` function
    286    /// for more information.
    287    leftmost_collapse_offset: usize,
    288 }
    289 
    290 impl<'a, E> AlreadyInvalidatedEntry<'a, E>
    291 where
    292    E: TElement + 'a,
    293 {
    294    fn new(element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) -> Self {
    295        Self {
    296            element,
    297            host,
    298            dependency,
    299            leftmost_collapse_offset: dependency.selector_offset,
    300        }
    301    }
    302 
    303    /// Update this invalidation with a new invalidation that may collapse with it.
    304    fn update(&mut self, element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) {
    305        // This dependency should invalidate the same way - Collapse the invalidation
    306        // to a more general case so we don't do duplicate work.
    307        // e.g. For `:has(.item .item + .item + .item)`, since the anchor would be located
    308        // in the ancestor chain for any invalidation triggered by any `.item` compound,
    309        // 4 entries can collapse into one - but keep track of the leftmost offset.
    310        if self.dependency.selector_offset > dependency.selector_offset {
    311            *self = Self {
    312                element,
    313                host,
    314                dependency,
    315                leftmost_collapse_offset: self.leftmost_collapse_offset,
    316            };
    317        } else if self.leftmost_collapse_offset < dependency.selector_offset {
    318            self.leftmost_collapse_offset = dependency.selector_offset;
    319        }
    320    }
    321 }
    322 
    323 /// Interface for collecting relative selector dependencies.
    324 pub struct RelativeSelectorDependencyCollector<'a, E>
    325 where
    326    E: TElement,
    327 {
    328    /// Dependencies that need to run through the normal invalidation that may generate
    329    /// a relative selector invalidation.
    330    dependencies: FxHashMap<E, ElementDependencies<'a>>,
    331    /// Dependencies that created an invalidation right away.
    332    invalidations: AlreadyInvalidated<'a, E>,
    333    /// The top element in the subtree being invalidated.
    334    top: E,
    335    /// Optional context that will be used to try and skip invalidations
    336    /// by running selector matches.
    337    optimization_context: Option<OptimizationContext<'a, E>>,
    338 }
    339 
    340 type Invalidations<'a> = SmallVec<[RelativeSelectorInvalidation<'a>; 1]>;
    341 type InnerInvalidations<'a, E> = SmallVec<[(E, RelativeSelectorInvalidation<'a>); 1]>;
    342 
    343 struct ToInvalidate<'a, E: TElement + 'a> {
    344    /// Dependencies to run through normal invalidator.
    345    dependencies: Dependencies<'a, E>,
    346    /// Dependencies already invalidated.
    347    invalidations: Invalidations<'a>,
    348 }
    349 
    350 impl<'a, E: TElement + 'a> Default for ToInvalidate<'a, E> {
    351    fn default() -> Self {
    352        Self {
    353            dependencies: Dependencies::default(),
    354            invalidations: Invalidations::default(),
    355        }
    356    }
    357 }
    358 
    359 fn invalidation_can_collapse(
    360    a: &Dependency,
    361    b: &Dependency,
    362    allow_indexed_selectors: bool,
    363 ) -> bool {
    364    // We want to detect identical dependencies that occur at different
    365    // compounds but has the identical compound in the same selector,
    366    // e.g. :has(.item .item).
    367 
    368    // If they trigger different invalidations, they shouldn't be collapsed.
    369    if a.relative_invalidation_kind() != b.relative_invalidation_kind() {
    370        return false;
    371    }
    372 
    373    // Not in the same selector, trivially skipped.
    374    if SelectorKey::new(&a.selector) != SelectorKey::new(&b.selector) {
    375        return false;
    376    }
    377 
    378    // Check that this is in the same nesting.
    379    // TODO(dshin): @scope probably brings more subtleties...
    380    let mut a_next = a.next.as_ref();
    381    let mut b_next = b.next.as_ref();
    382    while let (Some(a_deps), Some(b_deps)) = (a_next, b_next) {
    383        // This is a bit subtle - but we don't need to do the checks we do at higher levels.
    384        // Cases like `:is(.item .foo) :is(.item .foo)` where `.item` invalidates would
    385        // point to different dependencies, pointing to the same outer selector, but
    386        // differing in selector offset.
    387        let a_n = &a_deps.as_ref().slice()[0];
    388        let b_n = &b_deps.as_ref().slice()[0];
    389        if SelectorKey::new(&a_n.selector) != SelectorKey::new(&b_n.selector) {
    390            return false;
    391        }
    392        a_next = a_n.next.as_ref();
    393        b_next = b_n.next.as_ref();
    394    }
    395    if a_next.is_some() || b_next.is_some() {
    396        return false;
    397    }
    398 
    399    // Ok, now, do the compounds actually match?
    400    // This can get expensive quickly, but we're assuming that:
    401    //
    402    //   * In most cases, authors don't generally duplicate compounds in a selector, so
    403    //     this fails quickly
    404    //   * In cases where compounds are duplicated, reducing the number of invalidations
    405    //     has a payoff that offsets the comparison cost
    406    //
    407    // Note, `.a.b` != `.b.a` - doesn't affect correctness, though.
    408    // TODO(dshin): Caching this may be worth it as well?
    409    let mut a_iter = a.selector.iter_from(a.selector_offset);
    410    let mut b_iter = b.selector.iter_from(b.selector_offset);
    411    loop {
    412        let a_component = a_iter.next();
    413        let b_component = b_iter.next();
    414 
    415        if a_component != b_component {
    416            return false;
    417        }
    418        let Some(component) = a_component else {
    419            return true;
    420        };
    421        if !allow_indexed_selectors && component.has_indexed_selector_in_subject() {
    422            // The element's positioning matters, so can't collapse.
    423            return false;
    424        }
    425    }
    426 }
    427 
    428 impl<'a, E> RelativeSelectorDependencyCollector<'a, E>
    429 where
    430    E: TElement,
    431 {
    432    fn new(top: E, optimization_context: Option<OptimizationContext<'a, E>>) -> Self {
    433        Self {
    434            dependencies: FxHashMap::default(),
    435            invalidations: AlreadyInvalidated::default(),
    436            top,
    437            optimization_context,
    438        }
    439    }
    440 
    441    fn insert_invalidation(
    442        &mut self,
    443        element: E,
    444        dependency: &'a Dependency,
    445        host: Option<OpaqueElement>,
    446    ) {
    447        let in_subtree = element != self.top;
    448        if let Some(entry) = self.invalidations.iter_mut().find(|entry| {
    449            // If we're in the subtree of DOM manipulation - worrying the about positioning of this element
    450            // is irrelevant, because the DOM structure is either completely new or about to go away.
    451            let both_in_subtree = in_subtree && entry.element != self.top;
    452            // If we're considering the same element for invalidation, their evaluation of the indexed selector
    453            // is identical by definition.
    454            let same_element = element == entry.element;
    455            invalidation_can_collapse(
    456                dependency,
    457                entry.dependency,
    458                both_in_subtree || same_element,
    459            )
    460        }) {
    461            entry.update(element, host, dependency)
    462        } else {
    463            self.invalidations
    464                .push(AlreadyInvalidatedEntry::new(element, host, dependency));
    465        }
    466    }
    467 
    468    /// Add this dependency, if it is unique (i.e. Different outer dependency or same outer dependency
    469    /// but requires a different invalidation traversal).
    470    pub fn add_dependency(
    471        &mut self,
    472        dependency: &'a Dependency,
    473        element: E,
    474        host: Option<OpaqueElement>,
    475    ) {
    476        match dependency.invalidation_kind() {
    477            DependencyInvalidationKind::FullSelector => unreachable!(),
    478            DependencyInvalidationKind::Normal(..) | DependencyInvalidationKind::Scope(..) => {
    479                self.dependencies
    480                    .entry(element)
    481                    .and_modify(|v| v.push((host, dependency)))
    482                    .or_default()
    483                    .push((host, dependency));
    484            },
    485            DependencyInvalidationKind::Relative(kind) => {
    486                debug_assert!(
    487                    dependency.next.is_some(),
    488                    "Orphaned inner relative selector?"
    489                );
    490                if element != self.top
    491                    && matches!(
    492                        kind,
    493                        RelativeDependencyInvalidationKind::Parent
    494                            | RelativeDependencyInvalidationKind::PrevSibling
    495                            | RelativeDependencyInvalidationKind::EarlierSibling
    496                    )
    497                {
    498                    return;
    499                }
    500                if early_reject_by_local_name(
    501                    &dependency.selector,
    502                    dependency.selector_offset,
    503                    &element,
    504                ) {
    505                    return;
    506                }
    507                self.insert_invalidation(element, dependency, host);
    508            },
    509        };
    510    }
    511 
    512    /// Get the dependencies in a list format.
    513    fn get(self) -> ToInvalidate<'a, E> {
    514        let mut result = ToInvalidate::default();
    515        for invalidation in self.invalidations {
    516            match invalidation.dependency.invalidation_kind() {
    517                DependencyInvalidationKind::FullSelector => unreachable!(),
    518                DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => {
    519                    unreachable!("Inner selector in invalidation?")
    520                },
    521                DependencyInvalidationKind::Relative(kind) => {
    522                    if let Some(context) = self.optimization_context.as_ref() {
    523                        if context.can_be_ignored(
    524                            invalidation.element != self.top,
    525                            invalidation.element,
    526                            invalidation.host,
    527                            invalidation.dependency,
    528                            invalidation.leftmost_collapse_offset,
    529                        ) {
    530                            continue;
    531                        }
    532                    }
    533                    let dependency = &invalidation.dependency.next.as_ref().unwrap().slice()[0];
    534                    result.invalidations.push(RelativeSelectorInvalidation {
    535                        kind,
    536                        host: invalidation.host,
    537                        dependency,
    538                    });
    539                    // We move the invalidation up to the top of the subtree to avoid unnecessary traveral, but
    540                    // this means that we need to take ancestor-earlier sibling invalidations into account, as
    541                    // they'd look into earlier siblings of the top of the subtree as well.
    542                    if invalidation.element != self.top
    543                        && matches!(
    544                            kind,
    545                            RelativeDependencyInvalidationKind::AncestorEarlierSibling
    546                                | RelativeDependencyInvalidationKind::AncestorPrevSibling
    547                        )
    548                    {
    549                        result.invalidations.push(RelativeSelectorInvalidation {
    550                            kind: if matches!(
    551                                kind,
    552                                RelativeDependencyInvalidationKind::AncestorPrevSibling
    553                            ) {
    554                                RelativeDependencyInvalidationKind::PrevSibling
    555                            } else {
    556                                RelativeDependencyInvalidationKind::EarlierSibling
    557                            },
    558                            host: invalidation.host,
    559                            dependency,
    560                        });
    561                    }
    562                },
    563            };
    564        }
    565        for (key, element_dependencies) in self.dependencies {
    566            // At least for now, we don't try to optimize away dependencies emitted from nested selectors.
    567            result.dependencies.push((key, element_dependencies));
    568        }
    569        result
    570    }
    571 
    572    fn collect_all_dependencies_for_element(
    573        &mut self,
    574        element: E,
    575        scope: Option<OpaqueElement>,
    576        quirks_mode: QuirksMode,
    577        map: &'a InvalidationMap,
    578        additional_relative_selector_invalidation_map: &'a AdditionalRelativeSelectorInvalidationMap,
    579        operation: DomMutationOperation,
    580    ) {
    581        element
    582            .id()
    583            .map(|v| match map.id_to_selector.get(v, quirks_mode) {
    584                Some(v) => {
    585                    for dependency in v {
    586                        if !operation.accept(dependency, element) {
    587                            continue;
    588                        }
    589                        self.add_dependency(dependency, element, scope);
    590                    }
    591                },
    592                None => (),
    593            });
    594        element.each_class(|v| match map.class_to_selector.get(v, quirks_mode) {
    595            Some(v) => {
    596                for dependency in v {
    597                    if !operation.accept(dependency, element) {
    598                        continue;
    599                    }
    600                    self.add_dependency(dependency, element, scope);
    601                }
    602            },
    603            None => (),
    604        });
    605        element.each_custom_state(|v| match map.custom_state_affecting_selectors.get(v) {
    606            Some(v) => {
    607                for dependency in v {
    608                    if !operation.accept(dependency, element) {
    609                        continue;
    610                    }
    611                    self.add_dependency(dependency, element, scope);
    612                }
    613            },
    614            None => (),
    615        });
    616        element.each_attr_name(|v| match map.other_attribute_affecting_selectors.get(v) {
    617            Some(v) => {
    618                for dependency in v {
    619                    if !operation.accept(dependency, element) {
    620                        continue;
    621                    }
    622                    self.add_dependency(dependency, element, scope);
    623                }
    624            },
    625            None => (),
    626        });
    627        let state = element.state();
    628        map.state_affecting_selectors.lookup_with_additional(
    629            element,
    630            quirks_mode,
    631            None,
    632            &[],
    633            ElementState::empty(),
    634            |dependency| {
    635                if !dependency.state.intersects(state) {
    636                    return true;
    637                }
    638                if !operation.accept(&dependency.dep, element) {
    639                    return true;
    640                }
    641                self.add_dependency(&dependency.dep, element, scope);
    642                true
    643            },
    644        );
    645 
    646        additional_relative_selector_invalidation_map
    647            .ts_state_to_selector
    648            .lookup_with_additional(
    649                element,
    650                quirks_mode,
    651                None,
    652                &[],
    653                ElementState::empty(),
    654                |dependency| {
    655                    if !operation.accept(&dependency.dep, element) {
    656                        return true;
    657                    }
    658                    // This section contain potential optimization for not running full invalidation -
    659                    // consult documentation in `TSStateForInvalidation`.
    660                    if dependency.state.may_be_optimized() {
    661                        if operation.is_side_effect() {
    662                            // Side effect operations act on element not being mutated, so they can't
    663                            // change the match outcome of these optimizable pseudoclasses.
    664                            return true;
    665                        }
    666                        debug_assert!(
    667                            self.optimization_context.is_some(),
    668                            "Optimization context not available for DOM mutation?"
    669                        );
    670                        if dependency.state.contains(TSStateForInvalidation::EMPTY)
    671                            && element.first_element_child().is_some()
    672                        {
    673                            return true;
    674                        }
    675 
    676                        let sibling_traversal_map = self
    677                            .optimization_context
    678                            .as_ref()
    679                            .unwrap()
    680                            .sibling_traversal_map;
    681                        if dependency
    682                            .state
    683                            .contains(TSStateForInvalidation::NTH_EDGE_FIRST)
    684                            && sibling_traversal_map.prev_sibling_for(&element).is_some()
    685                        {
    686                            return true;
    687                        }
    688 
    689                        if dependency
    690                            .state
    691                            .contains(TSStateForInvalidation::NTH_EDGE_LAST)
    692                            && sibling_traversal_map.next_sibling_for(&element).is_some()
    693                        {
    694                            return true;
    695                        }
    696                    }
    697                    self.add_dependency(&dependency.dep, element, scope);
    698                    true
    699                },
    700            );
    701 
    702        if let Some(v) = additional_relative_selector_invalidation_map
    703            .type_to_selector
    704            .get(element.local_name())
    705        {
    706            for dependency in v {
    707                if !operation.accept(dependency, element) {
    708                    continue;
    709                }
    710                self.add_dependency(dependency, element, scope);
    711            }
    712        }
    713 
    714        for dependency in &additional_relative_selector_invalidation_map.any_to_selector {
    715            if !operation.accept(dependency, element) {
    716                continue;
    717            }
    718            self.add_dependency(dependency, element, scope);
    719        }
    720    }
    721 
    722    fn is_empty(&self) -> bool {
    723        self.invalidations.is_empty() && self.dependencies.is_empty()
    724    }
    725 }
    726 
    727 impl<'a, 'b, E> RelativeSelectorInvalidator<'a, 'b, E>
    728 where
    729    E: TElement + 'a,
    730 {
    731    /// Gather relative selector dependencies for the given element, and invalidate as necessary.
    732    #[inline(never)]
    733    pub fn invalidate_relative_selectors_for_this<F>(
    734        self,
    735        stylist: &'a Stylist,
    736        mut gather_dependencies: F,
    737    ) where
    738        F: FnMut(
    739            &E,
    740            Option<OpaqueElement>,
    741            &'a CascadeData,
    742            QuirksMode,
    743            &mut RelativeSelectorDependencyCollector<'a, E>,
    744        ),
    745    {
    746        let mut collector = RelativeSelectorDependencyCollector::new(self.element, None);
    747        stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
    748            let map = data.relative_invalidation_map_attributes();
    749            if !map.used {
    750                return;
    751            }
    752            gather_dependencies(
    753                &self.element,
    754                scope.map(|e| e.opaque()),
    755                data,
    756                self.quirks_mode,
    757                &mut collector,
    758            );
    759        });
    760        if collector.is_empty() {
    761            return;
    762        }
    763        self.invalidate_from_dependencies(collector.get());
    764    }
    765 
    766    /// Gather relative selector dependencies for the given element (And its subtree) that mutated, and invalidate as necessary.
    767    #[inline(never)]
    768    pub fn invalidate_relative_selectors_for_dom_mutation(
    769        self,
    770        subtree: bool,
    771        stylist: &'a Stylist,
    772        inherited_search_path: ElementSelectorFlags,
    773        operation: DomMutationOperation,
    774    ) {
    775        let mut collector = RelativeSelectorDependencyCollector::new(
    776            self.element,
    777            if operation.is_side_effect() {
    778                None
    779            } else {
    780                Some(OptimizationContext {
    781                    sibling_traversal_map: &self.sibling_traversal_map,
    782                    quirks_mode: self.quirks_mode,
    783                    operation,
    784                })
    785            },
    786        );
    787        let mut traverse_subtree = false;
    788        self.element.apply_selector_flags(inherited_search_path);
    789        stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
    790            let map_attributes = data.relative_invalidation_map_attributes();
    791            if !map_attributes.used {
    792                return;
    793            }
    794            let map = data.relative_selector_invalidation_map();
    795            traverse_subtree |= map_attributes.needs_ancestors_traversal;
    796            collector.collect_all_dependencies_for_element(
    797                self.element,
    798                scope.map(|e| e.opaque()),
    799                self.quirks_mode,
    800                map,
    801                map_attributes,
    802                operation,
    803            );
    804        });
    805 
    806        if subtree && traverse_subtree {
    807            for node in self.element.as_node().dom_descendants() {
    808                let descendant = match node.as_element() {
    809                    Some(e) => e,
    810                    None => continue,
    811                };
    812                descendant.apply_selector_flags(inherited_search_path);
    813                stylist.for_each_cascade_data_with_scope(descendant, |data, scope| {
    814                    let map_attributes = data.relative_invalidation_map_attributes();
    815                    if !map_attributes.used {
    816                        return;
    817                    }
    818                    let map = data.relative_selector_invalidation_map();
    819                    collector.collect_all_dependencies_for_element(
    820                        descendant,
    821                        scope.map(|e| e.opaque()),
    822                        self.quirks_mode,
    823                        map,
    824                        map_attributes,
    825                        operation,
    826                    );
    827                });
    828            }
    829        }
    830        if collector.is_empty() {
    831            return;
    832        }
    833        self.invalidate_from_dependencies(collector.get());
    834    }
    835 
    836    /// Carry out complete invalidation triggered by a relative selector invalidation.
    837    fn invalidate_from_dependencies(&self, to_invalidate: ToInvalidate<'a, E>) {
    838        for (element, dependencies) in to_invalidate.dependencies {
    839            let mut selector_caches = SelectorCaches::default();
    840            let mut processor = RelativeSelectorInnerInvalidationProcessor::new(
    841                self.quirks_mode,
    842                self.snapshot_table,
    843                &dependencies,
    844                &mut selector_caches,
    845                &self.sibling_traversal_map,
    846            );
    847            TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
    848            for (element, invalidation) in processor.take_invalidations() {
    849                self.invalidate_upwards(element, &invalidation);
    850            }
    851        }
    852        for invalidation in to_invalidate.invalidations {
    853            self.invalidate_upwards(self.element, &invalidation);
    854        }
    855    }
    856 
    857    fn invalidate_upwards(&self, element: E, invalidation: &RelativeSelectorInvalidation<'a>) {
    858        // This contains the main reason for why relative selector invalidation is handled
    859        // separately - It travels ancestor and/or earlier sibling direction.
    860        match invalidation.kind {
    861            RelativeDependencyInvalidationKind::Parent => {
    862                element.parent_element().map(|e| {
    863                    if !Self::in_search_direction(
    864                        &e,
    865                        ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
    866                    ) {
    867                        return;
    868                    }
    869                    self.handle_anchor(e, invalidation.dependency, invalidation.host);
    870                });
    871            },
    872            RelativeDependencyInvalidationKind::Ancestors => {
    873                let mut parent = element.parent_element();
    874                while let Some(par) = parent {
    875                    if !Self::in_search_direction(
    876                        &par,
    877                        ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
    878                    ) {
    879                        return;
    880                    }
    881                    self.handle_anchor(par, invalidation.dependency, invalidation.host);
    882                    parent = par.parent_element();
    883                }
    884            },
    885            RelativeDependencyInvalidationKind::PrevSibling => {
    886                self.sibling_traversal_map
    887                    .prev_sibling_for(&element)
    888                    .map(|e| {
    889                        if !Self::in_search_direction(
    890                            &e,
    891                            ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
    892                        ) {
    893                            return;
    894                        }
    895                        self.handle_anchor(e, invalidation.dependency, invalidation.host);
    896                    });
    897            },
    898            RelativeDependencyInvalidationKind::AncestorPrevSibling => {
    899                let mut parent = element.parent_element();
    900                while let Some(par) = parent {
    901                    if !Self::in_search_direction(
    902                        &par,
    903                        ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
    904                    ) {
    905                        return;
    906                    }
    907                    par.prev_sibling_element().map(|e| {
    908                        if !Self::in_search_direction(
    909                            &e,
    910                            ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
    911                        ) {
    912                            return;
    913                        }
    914                        self.handle_anchor(e, invalidation.dependency, invalidation.host);
    915                    });
    916                    parent = par.parent_element();
    917                }
    918            },
    919            RelativeDependencyInvalidationKind::EarlierSibling => {
    920                let mut sibling = self.sibling_traversal_map.prev_sibling_for(&element);
    921                while let Some(sib) = sibling {
    922                    if !Self::in_search_direction(
    923                        &sib,
    924                        ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
    925                    ) {
    926                        return;
    927                    }
    928                    self.handle_anchor(sib, invalidation.dependency, invalidation.host);
    929                    sibling = sib.prev_sibling_element();
    930                }
    931            },
    932            RelativeDependencyInvalidationKind::AncestorEarlierSibling => {
    933                let mut parent = element.parent_element();
    934                while let Some(par) = parent {
    935                    if !Self::in_search_direction(
    936                        &par,
    937                        ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
    938                    ) {
    939                        return;
    940                    }
    941                    let mut sibling = par.prev_sibling_element();
    942                    while let Some(sib) = sibling {
    943                        if !Self::in_search_direction(
    944                            &sib,
    945                            ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
    946                        ) {
    947                            return;
    948                        }
    949                        self.handle_anchor(sib, invalidation.dependency, invalidation.host);
    950                        sibling = sib.prev_sibling_element();
    951                    }
    952                    parent = par.parent_element();
    953                }
    954            },
    955        }
    956    }
    957 
    958    /// Is this element in the direction of the given relative selector search path?
    959    fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
    960        element
    961            .relative_selector_search_direction()
    962            .intersects(desired)
    963    }
    964 
    965    /// Handle a potential relative selector anchor.
    966    fn handle_anchor(
    967        &self,
    968        element: E,
    969        outer_dependency: &Dependency,
    970        host: Option<OpaqueElement>,
    971    ) {
    972        let is_rightmost = Self::is_subject(outer_dependency);
    973        if (is_rightmost
    974            && !element.has_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR))
    975            || (!is_rightmost
    976                && !element.has_selector_flags(
    977                    ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT,
    978                ))
    979        {
    980            // If it was never a relative selector anchor, don't bother.
    981            return;
    982        }
    983        let mut selector_caches = SelectorCaches::default();
    984        let matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
    985            MatchingMode::Normal,
    986            None,
    987            &mut selector_caches,
    988            VisitedHandlingMode::AllLinksVisitedAndUnvisited,
    989            IncludeStartingStyle::No,
    990            self.quirks_mode,
    991            NeedsSelectorFlags::No,
    992            MatchingForInvalidation::Yes,
    993        );
    994        let mut data = match element.mutate_data() {
    995            Some(data) => data,
    996            None => return,
    997        };
    998        let mut processor = RelativeSelectorOuterInvalidationProcessor {
    999            element,
   1000            host,
   1001            data: data.deref_mut(),
   1002            dependency: &*outer_dependency,
   1003            matching_context,
   1004            traversal_map: &self.sibling_traversal_map,
   1005        };
   1006        let result = TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
   1007        (self.invalidated)(element, &result);
   1008    }
   1009 
   1010    /// Does this relative selector dependency have its relative selector in the subject position?
   1011    fn is_subject(outer_dependency: &Dependency) -> bool {
   1012        debug_assert!(
   1013            matches!(
   1014                outer_dependency.invalidation_kind(),
   1015                DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_)
   1016            ),
   1017            "Outer selector of relative selector is relative?"
   1018        );
   1019 
   1020        if let Some(x) = outer_dependency.next.as_ref() {
   1021            // We only care to ensure that we're the subject in the outermost selector of the current
   1022            // selector - Crossing over a scope invalidation would mean moving into a selector inside
   1023            // the current scope block
   1024            if matches!(
   1025                outer_dependency.invalidation_kind(),
   1026                DependencyInvalidationKind::Normal(..)
   1027            ) {
   1028                if !Self::is_subject(&x.as_ref().slice()[0]) {
   1029                    // Not subject in outer selector.
   1030                    return false;
   1031                }
   1032            }
   1033        }
   1034        outer_dependency
   1035            .selector
   1036            .is_rightmost(outer_dependency.selector_offset)
   1037    }
   1038 }
   1039 
   1040 /// Blindly invalidate everything outside of a relative selector.
   1041 /// Consider `:is(.a :has(.b) .c ~ .d) ~ .e .f`, where .b gets deleted.
   1042 /// Since the tree mutated, we cannot rely on snapshots.
   1043 pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
   1044    /// Element being invalidated.
   1045    pub element: E,
   1046    /// The current shadow host, if any.
   1047    pub host: Option<OpaqueElement>,
   1048    /// Data for the element being invalidated.
   1049    pub data: &'a mut ElementData,
   1050    /// Dependency to be processed.
   1051    pub dependency: &'b Dependency,
   1052    /// Matching context to use for invalidation.
   1053    pub matching_context: MatchingContext<'a, E::Impl>,
   1054    /// Traversal map for this invalidation.
   1055    pub traversal_map: &'a SiblingTraversalMap<E>,
   1056 }
   1057 
   1058 impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'b, 'a, E>
   1059    for RelativeSelectorOuterInvalidationProcessor<'a, 'b, E>
   1060 where
   1061    E: TElement,
   1062 {
   1063    fn invalidates_on_pseudo_element(&self) -> bool {
   1064        true
   1065    }
   1066 
   1067    fn check_outer_dependency(
   1068        &mut self,
   1069        _dependency: &Dependency,
   1070        _element: E,
   1071        _: Option<OpaqueElement>,
   1072    ) -> bool {
   1073        // At this point, we know a relative selector invalidated, and are ignoring them.
   1074        true
   1075    }
   1076 
   1077    fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
   1078        &mut self.matching_context
   1079    }
   1080 
   1081    fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
   1082        self.traversal_map
   1083    }
   1084 
   1085    fn collect_invalidations(
   1086        &mut self,
   1087        element: E,
   1088        _self_invalidations: &mut InvalidationVector<'b>,
   1089        descendant_invalidations: &mut DescendantInvalidationLists<'b>,
   1090        sibling_invalidations: &mut InvalidationVector<'b>,
   1091    ) -> bool {
   1092        debug_assert_eq!(element, self.element);
   1093        debug_assert!(
   1094            self.matching_context.matching_for_invalidation(),
   1095            "Not matching for invalidation?"
   1096        );
   1097 
   1098        // Ok, this element can potentially an anchor to the given dependency.
   1099        // Before we do the potentially-costly ancestor/earlier sibling traversal,
   1100        // See if it can actuall be an anchor by trying to match the "rest" of the selector
   1101        // outside and to the left of `:has` in question.
   1102        // e.g. Element under consideration can only be the anchor to `:has` in
   1103        // `.foo .bar ~ .baz:has()`, iff it matches `.foo .bar ~ .baz`.
   1104        let invalidated_self = {
   1105            let mut invalidated = false;
   1106            let mut dependencies_to_invalidate: SmallVec<[&Dependency; 1]> =
   1107                smallvec![self.dependency];
   1108            while let Some(d) = dependencies_to_invalidate.pop() {
   1109                debug_assert!(
   1110                    matches!(
   1111                        d.invalidation_kind(),
   1112                        DependencyInvalidationKind::Normal(_)
   1113                            | DependencyInvalidationKind::Scope(_)
   1114                    ),
   1115                    "Unexpected dependency kind"
   1116                );
   1117                if !dependency_may_be_relevant(d, &element, false) {
   1118                    continue;
   1119                }
   1120                if !matches_selector(
   1121                    &d.selector,
   1122                    d.selector_offset,
   1123                    None,
   1124                    &element,
   1125                    self.matching_context(),
   1126                ) {
   1127                    continue;
   1128                }
   1129 
   1130                let invalidation_kind = d.invalidation_kind();
   1131 
   1132                if let DependencyInvalidationKind::Scope(scope_kind) = invalidation_kind {
   1133                    if d.selector.is_rightmost(d.selector_offset) {
   1134                        if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd {
   1135                            let invalidations = note_scope_dependency_force_at_subject(
   1136                                d,
   1137                                self.matching_context.current_host.clone(),
   1138                                self.matching_context.scope_element,
   1139                                false,
   1140                            );
   1141                            descendant_invalidations
   1142                                .dom_descendants
   1143                                .extend(invalidations);
   1144 
   1145                            invalidated |= true;
   1146                        } else if let Some(ref next) = d.next {
   1147                            dependencies_to_invalidate.extend(next.as_ref().slice());
   1148                        }
   1149                        continue;
   1150                    }
   1151                }
   1152 
   1153                if matches!(
   1154                    invalidation_kind,
   1155                    DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
   1156                ) {
   1157                    if let Some(ref deps) = d.next {
   1158                        // Normal dependencies should only have one next
   1159                        dependencies_to_invalidate.push(&deps.as_ref().slice()[0]);
   1160                        continue;
   1161                    }
   1162                    invalidated |= true;
   1163                    continue;
   1164                }
   1165                debug_assert_ne!(d.selector_offset, 0);
   1166                debug_assert_ne!(d.selector_offset, d.selector.len());
   1167                let invalidation = Invalidation::new(&d, self.host, None);
   1168                invalidated |= push_invalidation(
   1169                    invalidation,
   1170                    d.invalidation_kind(),
   1171                    descendant_invalidations,
   1172                    sibling_invalidations,
   1173                );
   1174            }
   1175            invalidated
   1176        };
   1177 
   1178        if invalidated_self {
   1179            self.data.hint.insert(RestyleHint::RESTYLE_SELF);
   1180        }
   1181        invalidated_self
   1182    }
   1183 
   1184    fn should_process_descendants(&mut self, element: E) -> bool {
   1185        if element == self.element {
   1186            return should_process_descendants(&self.data);
   1187        }
   1188 
   1189        match element.borrow_data() {
   1190            Some(d) => should_process_descendants(&d),
   1191            None => return false,
   1192        }
   1193    }
   1194 
   1195    fn recursion_limit_exceeded(&mut self, _element: E) {
   1196        unreachable!("Unexpected recursion limit");
   1197    }
   1198 
   1199    fn invalidated_descendants(&mut self, element: E, child: E) {
   1200        invalidated_descendants(element, child)
   1201    }
   1202 
   1203    fn invalidated_self(&mut self, element: E) {
   1204        debug_assert_ne!(element, self.element);
   1205        invalidated_self(element);
   1206    }
   1207 
   1208    fn invalidated_sibling(&mut self, element: E, of: E) {
   1209        debug_assert_ne!(element, self.element);
   1210        invalidated_sibling(element, of);
   1211    }
   1212 }
   1213 
   1214 /// Invalidation for the selector(s) inside a relative selector.
   1215 pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
   1216 where
   1217    E: TElement + 'a,
   1218 {
   1219    /// Matching context to be used.
   1220    matching_context: MatchingContext<'b, E::Impl>,
   1221    /// Table of snapshots.
   1222    snapshot_table: Option<&'c ServoElementSnapshotTable>,
   1223    /// Incoming dependencies to be processed.
   1224    dependencies: &'c ElementDependencies<'a>,
   1225    /// Generated invalidations.
   1226    invalidations: InnerInvalidations<'a, E>,
   1227    /// Traversal map for this invalidation.
   1228    traversal_map: &'b SiblingTraversalMap<E>,
   1229 }
   1230 
   1231 impl<'a, 'b, 'c, E> RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
   1232 where
   1233    E: TElement + 'a,
   1234 {
   1235    fn new(
   1236        quirks_mode: QuirksMode,
   1237        snapshot_table: Option<&'c ServoElementSnapshotTable>,
   1238        dependencies: &'c ElementDependencies<'a>,
   1239        selector_caches: &'b mut SelectorCaches,
   1240        traversal_map: &'b SiblingTraversalMap<E>,
   1241    ) -> Self {
   1242        let matching_context = MatchingContext::new_for_visited(
   1243            MatchingMode::Normal,
   1244            None,
   1245            selector_caches,
   1246            VisitedHandlingMode::AllLinksVisitedAndUnvisited,
   1247            IncludeStartingStyle::No,
   1248            quirks_mode,
   1249            NeedsSelectorFlags::No,
   1250            MatchingForInvalidation::Yes,
   1251        );
   1252        Self {
   1253            matching_context,
   1254            snapshot_table,
   1255            dependencies,
   1256            invalidations: InnerInvalidations::default(),
   1257            traversal_map,
   1258        }
   1259    }
   1260 
   1261    fn note_dependency(
   1262        &mut self,
   1263        element: E,
   1264        host: Option<OpaqueElement>,
   1265        dependency: &'a Dependency,
   1266        descendant_invalidations: &mut DescendantInvalidationLists<'a>,
   1267        sibling_invalidations: &mut InvalidationVector<'a>,
   1268    ) {
   1269        match dependency.invalidation_kind() {
   1270            DependencyInvalidationKind::FullSelector => unreachable!(),
   1271            DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => (),
   1272            DependencyInvalidationKind::Relative(kind) => {
   1273                self.found_relative_selector_invalidation(element, kind, dependency);
   1274                return;
   1275            },
   1276        }
   1277        if matches!(
   1278            dependency.normal_invalidation_kind(),
   1279            NormalDependencyInvalidationKind::Element
   1280        ) {
   1281            // Ok, keep heading outwards.
   1282            debug_assert!(
   1283                dependency.next.is_some(),
   1284                "Orphaned inner selector dependency?"
   1285            );
   1286            if let Some(next) = dependency.next.as_ref() {
   1287                self.note_dependency(
   1288                    element,
   1289                    host,
   1290                    &next.as_ref().slice()[0],
   1291                    descendant_invalidations,
   1292                    sibling_invalidations,
   1293                );
   1294            }
   1295            return;
   1296        }
   1297        let invalidation = Invalidation::new(&dependency, None, None);
   1298        match dependency.normal_invalidation_kind() {
   1299            NormalDependencyInvalidationKind::Descendants => {
   1300                // Descendant invalidations are simplified due to pseudo-elements not being available within the relative selector.
   1301                descendant_invalidations.dom_descendants.push(invalidation)
   1302            },
   1303            NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
   1304            // Note(dshin, bug 1940212): Nesting can enabling stuffing pseudo-elements into :has, like `::marker { :has(&) }`.
   1305            // Ideally, we can just not insert the dependency into the invalidation map, but the necessary selector information
   1306            // for this (i.e. `HAS_PSEUDO`) is filtered out in `replace_parent_selector` through
   1307            // `SelectorFlags::forbidden_for_nesting`, so just ignoring such dependencies here is the best we can do.
   1308            _ => (),
   1309        }
   1310    }
   1311 
   1312    /// Take the generated invalidations.
   1313    fn take_invalidations(self) -> InnerInvalidations<'a, E> {
   1314        self.invalidations
   1315    }
   1316 }
   1317 
   1318 impl<'a, 'b, 'c, E> InvalidationProcessor<'a, 'b, E>
   1319    for RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
   1320 where
   1321    E: TElement + 'a,
   1322 {
   1323    fn check_outer_dependency(
   1324        &mut self,
   1325        dependency: &Dependency,
   1326        element: E,
   1327        _: Option<OpaqueElement>,
   1328    ) -> bool {
   1329        if let Some(snapshot_table) = self.snapshot_table {
   1330            let wrapper = ElementWrapper::new(element, snapshot_table);
   1331            return check_dependency(
   1332                dependency,
   1333                &element,
   1334                &wrapper,
   1335                &mut self.matching_context,
   1336                None,
   1337            );
   1338        }
   1339        // Just invalidate if we don't have a snapshot.
   1340        true
   1341    }
   1342 
   1343    fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
   1344        return &mut self.matching_context;
   1345    }
   1346 
   1347    fn collect_invalidations(
   1348        &mut self,
   1349        element: E,
   1350        _self_invalidations: &mut InvalidationVector<'a>,
   1351        descendant_invalidations: &mut DescendantInvalidationLists<'a>,
   1352        sibling_invalidations: &mut InvalidationVector<'a>,
   1353    ) -> bool {
   1354        for (scope, dependency) in self.dependencies {
   1355            self.note_dependency(
   1356                element,
   1357                *scope,
   1358                dependency,
   1359                descendant_invalidations,
   1360                sibling_invalidations,
   1361            )
   1362        }
   1363        false
   1364    }
   1365 
   1366    fn should_process_descendants(&mut self, _element: E) -> bool {
   1367        true
   1368    }
   1369 
   1370    fn recursion_limit_exceeded(&mut self, _element: E) {
   1371        unreachable!("Unexpected recursion limit");
   1372    }
   1373 
   1374    // Don't do anything for normal invalidations.
   1375    fn invalidated_self(&mut self, _element: E) {}
   1376    fn invalidated_sibling(&mut self, _sibling: E, _of: E) {}
   1377    fn invalidated_descendants(&mut self, _element: E, _child: E) {}
   1378 
   1379    fn found_relative_selector_invalidation(
   1380        &mut self,
   1381        element: E,
   1382        kind: RelativeDependencyInvalidationKind,
   1383        dep: &'a Dependency,
   1384    ) {
   1385        debug_assert!(dep.next.is_some(), "Orphaned inners selector?");
   1386        if element.relative_selector_search_direction().is_empty() {
   1387            return;
   1388        }
   1389        self.invalidations.push((
   1390            element,
   1391            RelativeSelectorInvalidation {
   1392                host: self.matching_context.current_host,
   1393                kind,
   1394                dependency: &dep.next.as_ref().unwrap().as_ref().slice()[0],
   1395            },
   1396        ));
   1397    }
   1398 
   1399    fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
   1400        &self.traversal_map
   1401    }
   1402 }