Skip to main content

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