1use 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#[derive(Clone, Copy)]
40pub enum DomMutationOperation {
41 Insert,
43 Append,
45 Remove,
47 SideEffectPrevSibling,
49 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 Self::SideEffectPrevSibling => {
62 !e.relative_selector_search_direction().is_empty()
63 && d.right_combinator_is_next_sibling()
64 },
65 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
80struct 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 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 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 let iter = dependency.selector.iter_from(dependency.selector_offset);
124 for c in iter {
125 if c.has_indexed_selector_in_subject() {
126 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 return true;
144 }
145 if combinator.is_sibling() && matches!(self.operation, DomMutationOperation::Append) {
146 return true;
149 }
150 }
151
152 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 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 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 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 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
240pub struct RelativeSelectorInvalidator<'a, 'b: 'a, E>
242where
243 E: TElement,
244{
245 pub element: E,
247 pub quirks_mode: QuirksMode,
249 pub snapshots: Option<&'a Snapshots<'b>>,
252 pub invalidated: fn(E, &InvalidationResult),
254 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: E,
274 host: Option<OpaqueElement>,
276 dependency: &'a Dependency,
278 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 fn update(&mut self, element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) {
299 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
317pub struct RelativeSelectorDependencyCollector<'a, E>
319where
320 E: TElement,
321{
322 dependencies: FxHashMap<E, ElementDependencies<'a>>,
325 invalidations: AlreadyInvalidated<'a, E>,
327 top: E,
329 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: Dependencies<'a, E>,
340 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 if a.relative_invalidation_kind() != b.relative_invalidation_kind() {
364 return false;
365 }
366
367 if SelectorKey::new(&a.selector) != SelectorKey::new(&b.selector) {
369 return false;
370 }
371
372 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 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 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 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 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 let both_in_subtree = in_subtree && entry.element != self.top;
453 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 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 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 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 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 if dependency.state.may_be_optimized() {
655 if operation.is_side_effect() {
656 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 #[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 #[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 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 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 fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
954 element
955 .relative_selector_search_direction()
956 .intersects(desired)
957 }
958
959 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 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 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 if matches!(
1018 outer_dependency.invalidation_kind(),
1019 DependencyInvalidationKind::Normal(..)
1020 ) && !Self::is_subject(&x.as_ref().slice()[0])
1021 {
1022 return false;
1024 }
1025 }
1026 outer_dependency
1027 .selector
1028 .is_rightmost(outer_dependency.selector_offset)
1029 }
1030}
1031
1032pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
1036 pub element: E,
1038 pub host: Option<OpaqueElement>,
1040 pub data: &'a mut ElementData,
1042 pub dependency: &'b Dependency,
1044 pub matching_context: MatchingContext<'a, E::Impl>,
1046 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 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 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 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
1206pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 's, E>
1208where
1209 E: TElement,
1210{
1211 matching_context: MatchingContext<'b, E::Impl>,
1213 snapshots: Option<&'b Snapshots<'s>>,
1215 dependencies: &'b ElementDependencies<'a>,
1217 invalidations: InnerInvalidations<'a, E>,
1219 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 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.dom_descendants.push(invalidation)
1293 },
1294 NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
1295 _ => (),
1300 }
1301 }
1302
1303 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 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 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}