1use crate::data::ElementData;
8use crate::dom::{TElement, TNode};
9#[cfg(feature = "gecko")]
10use crate::gecko_bindings::structs::ServoElementSnapshotTable;
11use crate::invalidation::element::element_wrapper::ElementWrapper;
12use crate::invalidation::element::invalidation_map::{
13 AdditionalRelativeSelectorInvalidationMap, Dependency, DependencyInvalidationKind,
14 InvalidationMap, NormalDependencyInvalidationKind, RelativeDependencyInvalidationKind,
15 ScopeDependencyInvalidationKind, TSStateForInvalidation,
16};
17use crate::invalidation::element::invalidator::{
18 note_scope_dependency_force_at_subject, DescendantInvalidationLists, Invalidation,
19 InvalidationProcessor, InvalidationResult, InvalidationVector, SiblingTraversalMap,
20 TreeStyleInvalidator,
21};
22use crate::invalidation::element::restyle_hints::RestyleHint;
23use crate::invalidation::element::state_and_attributes::{
24 check_dependency, dependency_may_be_relevant, invalidated_descendants, invalidated_self,
25 invalidated_sibling, push_invalidation, should_process_descendants,
26};
27#[cfg(feature = "servo")]
28use crate::selector_parser::SnapshotMap as ServoElementSnapshotTable;
29use crate::stylist::{CascadeData, Stylist};
30use dom::ElementState;
31use rustc_hash::FxHashMap;
32use selectors::matching::{
33 early_reject_by_local_name, matches_selector, ElementSelectorFlags,
34 IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
35 NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
36};
37use selectors::parser::SelectorKey;
38use selectors::OpaqueElement;
39use smallvec::{smallvec, SmallVec};
40use std::ops::DerefMut;
41
42#[derive(Clone, Copy)]
44pub enum DomMutationOperation {
45 Insert,
47 Append,
49 Remove,
51 SideEffectPrevSibling,
53 SideEffectNextSibling,
55}
56
57impl DomMutationOperation {
58 fn accept<E: TElement>(&self, d: &Dependency, e: E) -> bool {
59 match self {
60 Self::Insert | Self::Append | Self::Remove => {
61 !e.relative_selector_search_direction().is_empty()
62 },
63 Self::SideEffectPrevSibling => {
66 !e.relative_selector_search_direction().is_empty()
67 && d.right_combinator_is_next_sibling()
68 },
69 Self::SideEffectNextSibling => d.dependency_is_relative_with_single_next_sibling(),
73 }
74 }
75
76 fn is_side_effect(&self) -> bool {
77 match self {
78 Self::Insert | Self::Append | Self::Remove => false,
79 Self::SideEffectPrevSibling | Self::SideEffectNextSibling => true,
80 }
81 }
82}
83
84struct OptimizationContext<'a, E: TElement> {
86 sibling_traversal_map: &'a SiblingTraversalMap<E>,
87 quirks_mode: QuirksMode,
88 operation: DomMutationOperation,
89}
90
91impl<'a, E: TElement> OptimizationContext<'a, E> {
92 fn can_be_ignored(
93 &self,
94 is_subtree: bool,
95 element: E,
96 host: Option<OpaqueElement>,
97 dependency: &Dependency,
98 leftmost_collapse_offset: usize,
99 ) -> bool {
100 if is_subtree {
101 return false;
103 }
104 debug_assert!(
105 matches!(
106 dependency.invalidation_kind(),
107 DependencyInvalidationKind::Relative(..)
108 ),
109 "Non-relative selector being evaluated for optimization"
110 );
111 let sibling = match self.sibling_traversal_map.prev_sibling_for(&element) {
114 None => {
115 if matches!(self.operation, DomMutationOperation::Append) {
116 return false;
117 }
118 match self.sibling_traversal_map.next_sibling_for(&element) {
119 Some(s) => s,
120 None => return false,
121 }
122 },
123 Some(s) => s,
124 };
125 {
126 let mut iter = dependency.selector.iter_from(dependency.selector_offset);
128 while let Some(c) = iter.next() {
129 if c.has_indexed_selector_in_subject() {
130 return false;
136 }
137 }
138 }
139 let dependency_is_rightmost = dependency.selector_offset == 0;
140 if !dependency_is_rightmost {
141 let combinator = dependency
142 .selector
143 .combinator_at_match_order(dependency.selector_offset - 1);
144 if combinator.is_ancestor() {
145 return true;
148 }
149 if combinator.is_sibling() && matches!(self.operation, DomMutationOperation::Append) {
150 return true;
153 }
154 }
155
156 if dependency_is_rightmost
162 && leftmost_collapse_offset != dependency.selector_offset
163 && self
164 .sibling_traversal_map
165 .next_sibling_for(&element)
166 .is_some()
167 {
168 return false;
169 }
170
171 let mut caches = SelectorCaches::default();
172 let mut matching_context = MatchingContext::new(
173 MatchingMode::Normal,
174 None,
175 &mut caches,
176 self.quirks_mode,
177 NeedsSelectorFlags::No,
178 MatchingForInvalidation::Yes,
179 );
180 matching_context.current_host = host;
181 let sibling_matches = matches_selector(
182 &dependency.selector,
183 dependency.selector_offset,
184 None,
185 &sibling,
186 &mut matching_context,
187 );
188 if sibling_matches {
189 debug_assert!(
195 dependency.next.is_some(),
196 "No relative selector outer dependency?"
197 );
198 return dependency.next.as_ref().map_or(false, |deps| {
199 let next = &deps.as_ref().slice()[0];
202 !matches_selector(
203 &next.selector,
204 next.selector_offset,
205 None,
206 &sibling,
207 &mut matching_context,
208 )
209 });
210 }
211 let (combinator, prev_offset) = {
216 let mut iter = dependency.selector.iter_from(dependency.selector_offset);
217 let mut o = dependency.selector_offset;
218 while iter.next().is_some() {
219 o += 1;
220 }
221 let combinator = iter.next_sequence();
222 o += 1;
223 debug_assert!(
224 combinator.is_some(),
225 "Should at least see a relative combinator"
226 );
227 (combinator.unwrap(), o)
228 };
229 if combinator.is_sibling() && prev_offset >= dependency.selector.len() - 1 {
230 return false;
233 }
234 !matches_selector(
235 &dependency.selector,
236 dependency.selector_offset,
237 None,
238 &element,
239 &mut matching_context,
240 )
241 }
242}
243
244pub struct RelativeSelectorInvalidator<'a, 'b, E>
246where
247 E: TElement + 'a,
248{
249 pub element: E,
251 pub quirks_mode: QuirksMode,
253 pub snapshot_table: Option<&'b ServoElementSnapshotTable>,
256 pub invalidated: fn(E, &InvalidationResult),
258 pub sibling_traversal_map: SiblingTraversalMap<E>,
260 pub _marker: ::std::marker::PhantomData<&'a ()>,
262}
263
264struct RelativeSelectorInvalidation<'a> {
265 host: Option<OpaqueElement>,
266 kind: RelativeDependencyInvalidationKind,
267 dependency: &'a Dependency,
268}
269
270type ElementDependencies<'a> = SmallVec<[(Option<OpaqueElement>, &'a Dependency); 1]>;
271type Dependencies<'a, E> = SmallVec<[(E, ElementDependencies<'a>); 1]>;
272type AlreadyInvalidated<'a, E> = SmallVec<[AlreadyInvalidatedEntry<'a, E>; 2]>;
273
274struct AlreadyInvalidatedEntry<'a, E>
275where
276 E: TElement + 'a,
277{
278 element: E,
280 host: Option<OpaqueElement>,
282 dependency: &'a Dependency,
284 leftmost_collapse_offset: usize,
288}
289
290impl<'a, E> AlreadyInvalidatedEntry<'a, E>
291where
292 E: TElement + 'a,
293{
294 fn new(element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) -> Self {
295 Self {
296 element,
297 host,
298 dependency,
299 leftmost_collapse_offset: dependency.selector_offset,
300 }
301 }
302
303 fn update(&mut self, element: E, host: Option<OpaqueElement>, dependency: &'a Dependency) {
305 if self.dependency.selector_offset > dependency.selector_offset {
311 *self = Self {
312 element,
313 host,
314 dependency,
315 leftmost_collapse_offset: self.leftmost_collapse_offset,
316 };
317 } else if self.leftmost_collapse_offset < dependency.selector_offset {
318 self.leftmost_collapse_offset = dependency.selector_offset;
319 }
320 }
321}
322
323pub struct RelativeSelectorDependencyCollector<'a, E>
325where
326 E: TElement,
327{
328 dependencies: FxHashMap<E, ElementDependencies<'a>>,
331 invalidations: AlreadyInvalidated<'a, E>,
333 top: E,
335 optimization_context: Option<OptimizationContext<'a, E>>,
338}
339
340type Invalidations<'a> = SmallVec<[RelativeSelectorInvalidation<'a>; 1]>;
341type InnerInvalidations<'a, E> = SmallVec<[(E, RelativeSelectorInvalidation<'a>); 1]>;
342
343struct ToInvalidate<'a, E: TElement + 'a> {
344 dependencies: Dependencies<'a, E>,
346 invalidations: Invalidations<'a>,
348}
349
350impl<'a, E: TElement + 'a> Default for ToInvalidate<'a, E> {
351 fn default() -> Self {
352 Self {
353 dependencies: Dependencies::default(),
354 invalidations: Invalidations::default(),
355 }
356 }
357}
358
359fn invalidation_can_collapse(
360 a: &Dependency,
361 b: &Dependency,
362 allow_indexed_selectors: bool,
363) -> bool {
364 if a.relative_invalidation_kind() != b.relative_invalidation_kind() {
370 return false;
371 }
372
373 if SelectorKey::new(&a.selector) != SelectorKey::new(&b.selector) {
375 return false;
376 }
377
378 let mut a_next = a.next.as_ref();
381 let mut b_next = b.next.as_ref();
382 while let (Some(a_deps), Some(b_deps)) = (a_next, b_next) {
383 let a_nexts = a_deps.as_ref().slice();
388 let b_nexts = b_deps.as_ref().slice();
389 if a_nexts.is_empty()|| b_nexts.is_empty() {
390 return a_nexts.is_empty() == b_nexts.is_empty();
393 }
394 let a_n = &a_nexts[0];
395 let b_n = &b_nexts[0];
396 if SelectorKey::new(&a_n.selector) != SelectorKey::new(&b_n.selector) {
397 return false;
398 }
399 a_next = a_n.next.as_ref();
400 b_next = b_n.next.as_ref();
401 }
402 if a_next.is_some() || b_next.is_some() {
403 return false;
404 }
405
406 let mut a_iter = a.selector.iter_from(a.selector_offset);
417 let mut b_iter = b.selector.iter_from(b.selector_offset);
418 loop {
419 let a_component = a_iter.next();
420 let b_component = b_iter.next();
421
422 if a_component != b_component {
423 return false;
424 }
425 let Some(component) = a_component else {
426 return true;
427 };
428 if !allow_indexed_selectors && component.has_indexed_selector_in_subject() {
429 return false;
431 }
432 }
433}
434
435impl<'a, E> RelativeSelectorDependencyCollector<'a, E>
436where
437 E: TElement,
438{
439 fn new(top: E, optimization_context: Option<OptimizationContext<'a, E>>) -> Self {
440 Self {
441 dependencies: FxHashMap::default(),
442 invalidations: AlreadyInvalidated::default(),
443 top,
444 optimization_context,
445 }
446 }
447
448 fn insert_invalidation(
449 &mut self,
450 element: E,
451 dependency: &'a Dependency,
452 host: Option<OpaqueElement>,
453 ) {
454 let in_subtree = element != self.top;
455 if let Some(entry) = self.invalidations.iter_mut().find(|entry| {
456 let both_in_subtree = in_subtree && entry.element != self.top;
459 let same_element = element == entry.element;
462 invalidation_can_collapse(
463 dependency,
464 entry.dependency,
465 both_in_subtree || same_element,
466 )
467 }) {
468 entry.update(element, host, dependency)
469 } else {
470 self.invalidations
471 .push(AlreadyInvalidatedEntry::new(element, host, dependency));
472 }
473 }
474
475 pub fn add_dependency(
478 &mut self,
479 dependency: &'a Dependency,
480 element: E,
481 host: Option<OpaqueElement>,
482 ) {
483 match dependency.invalidation_kind() {
484 DependencyInvalidationKind::FullSelector => unreachable!(),
485 DependencyInvalidationKind::Normal(..) | DependencyInvalidationKind::Scope(..) => {
486 self.dependencies
487 .entry(element)
488 .and_modify(|v| v.push((host, dependency)))
489 .or_default()
490 .push((host, dependency));
491 },
492 DependencyInvalidationKind::Relative(kind) => {
493 debug_assert!(
494 dependency.next.is_some(),
495 "Orphaned inner relative selector?"
496 );
497 if element != self.top
498 && matches!(
499 kind,
500 RelativeDependencyInvalidationKind::Parent
501 | RelativeDependencyInvalidationKind::PrevSibling
502 | RelativeDependencyInvalidationKind::EarlierSibling
503 )
504 {
505 return;
506 }
507 if early_reject_by_local_name(
508 &dependency.selector,
509 dependency.selector_offset,
510 &element,
511 ) {
512 return;
513 }
514 self.insert_invalidation(element, dependency, host);
515 },
516 };
517 }
518
519 fn get(self) -> ToInvalidate<'a, E> {
521 let mut result = ToInvalidate::default();
522 for invalidation in self.invalidations {
523 match invalidation.dependency.invalidation_kind() {
524 DependencyInvalidationKind::FullSelector => unreachable!(),
525 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => {
526 unreachable!("Inner selector in invalidation?")
527 },
528 DependencyInvalidationKind::Relative(kind) => {
529 if let Some(context) = self.optimization_context.as_ref() {
530 if context.can_be_ignored(
531 invalidation.element != self.top,
532 invalidation.element,
533 invalidation.host,
534 invalidation.dependency,
535 invalidation.leftmost_collapse_offset,
536 ) {
537 continue;
538 }
539 }
540 let dependency = &invalidation.dependency.next.as_ref().unwrap().slice()[0];
541 result.invalidations.push(RelativeSelectorInvalidation {
542 kind,
543 host: invalidation.host,
544 dependency,
545 });
546 if invalidation.element != self.top
550 && matches!(
551 kind,
552 RelativeDependencyInvalidationKind::AncestorEarlierSibling
553 | RelativeDependencyInvalidationKind::AncestorPrevSibling
554 )
555 {
556 result.invalidations.push(RelativeSelectorInvalidation {
557 kind: if matches!(
558 kind,
559 RelativeDependencyInvalidationKind::AncestorPrevSibling
560 ) {
561 RelativeDependencyInvalidationKind::PrevSibling
562 } else {
563 RelativeDependencyInvalidationKind::EarlierSibling
564 },
565 host: invalidation.host,
566 dependency,
567 });
568 }
569 },
570 };
571 }
572 for (key, element_dependencies) in self.dependencies {
573 result.dependencies.push((key, element_dependencies));
575 }
576 result
577 }
578
579 fn collect_all_dependencies_for_element(
580 &mut self,
581 element: E,
582 scope: Option<OpaqueElement>,
583 quirks_mode: QuirksMode,
584 map: &'a InvalidationMap,
585 additional_relative_selector_invalidation_map: &'a AdditionalRelativeSelectorInvalidationMap,
586 operation: DomMutationOperation,
587 ) {
588 element
589 .id()
590 .map(|v| match map.id_to_selector.get(v, quirks_mode) {
591 Some(v) => {
592 for dependency in v {
593 if !operation.accept(dependency, element) {
594 continue;
595 }
596 self.add_dependency(dependency, element, scope);
597 }
598 },
599 None => (),
600 });
601 element.each_class(|v| match map.class_to_selector.get(v, quirks_mode) {
602 Some(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 None => (),
611 });
612 element.each_custom_state(|v| match map.custom_state_affecting_selectors.get(v) {
613 Some(v) => {
614 for dependency in v {
615 if !operation.accept(dependency, element) {
616 continue;
617 }
618 self.add_dependency(dependency, element, scope);
619 }
620 },
621 None => (),
622 });
623 element.each_attr_name(|v| match map.other_attribute_affecting_selectors.get(v) {
624 Some(v) => {
625 for dependency in v {
626 if !operation.accept(dependency, element) {
627 continue;
628 }
629 self.add_dependency(dependency, element, scope);
630 }
631 },
632 None => (),
633 });
634 let state = element.state();
635 map.state_affecting_selectors.lookup_with_additional(
636 element,
637 quirks_mode,
638 None,
639 &[],
640 ElementState::empty(),
641 |dependency| {
642 if !dependency.state.intersects(state) {
643 return true;
644 }
645 if !operation.accept(&dependency.dep, element) {
646 return true;
647 }
648 self.add_dependency(&dependency.dep, element, scope);
649 true
650 },
651 );
652
653 additional_relative_selector_invalidation_map
654 .ts_state_to_selector
655 .lookup_with_additional(
656 element,
657 quirks_mode,
658 None,
659 &[],
660 ElementState::empty(),
661 |dependency| {
662 if !operation.accept(&dependency.dep, element) {
663 return true;
664 }
665 if dependency.state.may_be_optimized() {
668 if operation.is_side_effect() {
669 return true;
672 }
673 debug_assert!(
674 self.optimization_context.is_some(),
675 "Optimization context not available for DOM mutation?"
676 );
677 if dependency.state.contains(TSStateForInvalidation::EMPTY)
678 && element.first_element_child().is_some()
679 {
680 return true;
681 }
682
683 let sibling_traversal_map = self
684 .optimization_context
685 .as_ref()
686 .unwrap()
687 .sibling_traversal_map;
688 if dependency
689 .state
690 .contains(TSStateForInvalidation::NTH_EDGE_FIRST)
691 && sibling_traversal_map.prev_sibling_for(&element).is_some()
692 {
693 return true;
694 }
695
696 if dependency
697 .state
698 .contains(TSStateForInvalidation::NTH_EDGE_LAST)
699 && sibling_traversal_map.next_sibling_for(&element).is_some()
700 {
701 return true;
702 }
703 }
704 self.add_dependency(&dependency.dep, element, scope);
705 true
706 },
707 );
708
709 if let Some(v) = additional_relative_selector_invalidation_map
710 .type_to_selector
711 .get(element.local_name())
712 {
713 for dependency in v {
714 if !operation.accept(dependency, element) {
715 continue;
716 }
717 self.add_dependency(dependency, element, scope);
718 }
719 }
720
721 for dependency in &additional_relative_selector_invalidation_map.any_to_selector {
722 if !operation.accept(dependency, element) {
723 continue;
724 }
725 self.add_dependency(dependency, element, scope);
726 }
727 }
728
729 fn is_empty(&self) -> bool {
730 self.invalidations.is_empty() && self.dependencies.is_empty()
731 }
732}
733
734impl<'a, 'b, E> RelativeSelectorInvalidator<'a, 'b, E>
735where
736 E: TElement + 'a,
737{
738 #[inline(never)]
740 pub fn invalidate_relative_selectors_for_this<F>(
741 self,
742 stylist: &'a Stylist,
743 mut gather_dependencies: F,
744 ) where
745 F: FnMut(
746 &E,
747 Option<OpaqueElement>,
748 &'a CascadeData,
749 QuirksMode,
750 &mut RelativeSelectorDependencyCollector<'a, E>,
751 ),
752 {
753 let mut collector = RelativeSelectorDependencyCollector::new(self.element, None);
754 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
755 let map = data.relative_invalidation_map_attributes();
756 if !map.used {
757 return;
758 }
759 gather_dependencies(
760 &self.element,
761 scope.map(|e| e.opaque()),
762 data,
763 self.quirks_mode,
764 &mut collector,
765 );
766 });
767 if collector.is_empty() {
768 return;
769 }
770 self.invalidate_from_dependencies(collector.get());
771 }
772
773 #[inline(never)]
775 pub fn invalidate_relative_selectors_for_dom_mutation(
776 self,
777 subtree: bool,
778 stylist: &'a Stylist,
779 inherited_search_path: ElementSelectorFlags,
780 operation: DomMutationOperation,
781 ) {
782 let mut collector = RelativeSelectorDependencyCollector::new(
783 self.element,
784 if operation.is_side_effect() {
785 None
786 } else {
787 Some(OptimizationContext {
788 sibling_traversal_map: &self.sibling_traversal_map,
789 quirks_mode: self.quirks_mode,
790 operation,
791 })
792 },
793 );
794 let mut traverse_subtree = false;
795 self.element.apply_selector_flags(inherited_search_path);
796 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
797 let map_attributes = data.relative_invalidation_map_attributes();
798 if !map_attributes.used {
799 return;
800 }
801 let map = data.relative_selector_invalidation_map();
802 traverse_subtree |= map_attributes.needs_ancestors_traversal;
803 collector.collect_all_dependencies_for_element(
804 self.element,
805 scope.map(|e| e.opaque()),
806 self.quirks_mode,
807 map,
808 map_attributes,
809 operation,
810 );
811 });
812
813 if subtree && traverse_subtree {
814 for node in self.element.as_node().dom_descendants() {
815 let descendant = match node.as_element() {
816 Some(e) => e,
817 None => continue,
818 };
819 descendant.apply_selector_flags(inherited_search_path);
820 stylist.for_each_cascade_data_with_scope(descendant, |data, scope| {
821 let map_attributes = data.relative_invalidation_map_attributes();
822 if !map_attributes.used {
823 return;
824 }
825 let map = data.relative_selector_invalidation_map();
826 collector.collect_all_dependencies_for_element(
827 descendant,
828 scope.map(|e| e.opaque()),
829 self.quirks_mode,
830 map,
831 map_attributes,
832 operation,
833 );
834 });
835 }
836 }
837 if collector.is_empty() {
838 return;
839 }
840 self.invalidate_from_dependencies(collector.get());
841 }
842
843 fn invalidate_from_dependencies(&self, to_invalidate: ToInvalidate<'a, E>) {
845 for (element, dependencies) in to_invalidate.dependencies {
846 let mut selector_caches = SelectorCaches::default();
847 let mut processor = RelativeSelectorInnerInvalidationProcessor::new(
848 self.quirks_mode,
849 self.snapshot_table,
850 &dependencies,
851 &mut selector_caches,
852 &self.sibling_traversal_map,
853 );
854 TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
855 for (element, invalidation) in processor.take_invalidations() {
856 self.invalidate_upwards(element, &invalidation);
857 }
858 }
859 for invalidation in to_invalidate.invalidations {
860 self.invalidate_upwards(self.element, &invalidation);
861 }
862 }
863
864 fn invalidate_upwards(&self, element: E, invalidation: &RelativeSelectorInvalidation<'a>) {
865 match invalidation.kind {
868 RelativeDependencyInvalidationKind::Parent => {
869 element.parent_element().map(|e| {
870 if !Self::in_search_direction(
871 &e,
872 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
873 ) {
874 return;
875 }
876 self.handle_anchor(e, invalidation.dependency, invalidation.host);
877 });
878 },
879 RelativeDependencyInvalidationKind::Ancestors => {
880 let mut parent = element.parent_element();
881 while let Some(par) = parent {
882 if !Self::in_search_direction(
883 &par,
884 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
885 ) {
886 return;
887 }
888 self.handle_anchor(par, invalidation.dependency, invalidation.host);
889 parent = par.parent_element();
890 }
891 },
892 RelativeDependencyInvalidationKind::PrevSibling => {
893 self.sibling_traversal_map
894 .prev_sibling_for(&element)
895 .map(|e| {
896 if !Self::in_search_direction(
897 &e,
898 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
899 ) {
900 return;
901 }
902 self.handle_anchor(e, invalidation.dependency, invalidation.host);
903 });
904 },
905 RelativeDependencyInvalidationKind::AncestorPrevSibling => {
906 let mut parent = element.parent_element();
907 while let Some(par) = parent {
908 if !Self::in_search_direction(
909 &par,
910 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
911 ) {
912 return;
913 }
914 par.prev_sibling_element().map(|e| {
915 if !Self::in_search_direction(
916 &e,
917 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
918 ) {
919 return;
920 }
921 self.handle_anchor(e, invalidation.dependency, invalidation.host);
922 });
923 parent = par.parent_element();
924 }
925 },
926 RelativeDependencyInvalidationKind::EarlierSibling => {
927 let mut sibling = self.sibling_traversal_map.prev_sibling_for(&element);
928 while let Some(sib) = sibling {
929 if !Self::in_search_direction(
930 &sib,
931 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
932 ) {
933 return;
934 }
935 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
936 sibling = sib.prev_sibling_element();
937 }
938 },
939 RelativeDependencyInvalidationKind::AncestorEarlierSibling => {
940 let mut parent = element.parent_element();
941 while let Some(par) = parent {
942 if !Self::in_search_direction(
943 &par,
944 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
945 ) {
946 return;
947 }
948 let mut sibling = par.prev_sibling_element();
949 while let Some(sib) = sibling {
950 if !Self::in_search_direction(
951 &sib,
952 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
953 ) {
954 return;
955 }
956 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
957 sibling = sib.prev_sibling_element();
958 }
959 parent = par.parent_element();
960 }
961 },
962 }
963 }
964
965 fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
967 element
968 .relative_selector_search_direction()
969 .intersects(desired)
970 }
971
972 fn handle_anchor(
974 &self,
975 element: E,
976 outer_dependency: &Dependency,
977 host: Option<OpaqueElement>,
978 ) {
979 let is_rightmost = Self::is_subject(outer_dependency);
980 if (is_rightmost
981 && !element.has_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR))
982 || (!is_rightmost
983 && !element.has_selector_flags(
984 ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT,
985 ))
986 {
987 return;
989 }
990 let mut selector_caches = SelectorCaches::default();
991 let matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
992 MatchingMode::Normal,
993 None,
994 &mut selector_caches,
995 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
996 IncludeStartingStyle::No,
997 self.quirks_mode,
998 NeedsSelectorFlags::No,
999 MatchingForInvalidation::Yes,
1000 );
1001 let mut data = match element.mutate_data() {
1002 Some(data) => data,
1003 None => return,
1004 };
1005 let mut processor = RelativeSelectorOuterInvalidationProcessor {
1006 element,
1007 host,
1008 data: data.deref_mut(),
1009 dependency: &*outer_dependency,
1010 matching_context,
1011 traversal_map: &self.sibling_traversal_map,
1012 };
1013 let result = TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
1014 (self.invalidated)(element, &result);
1015 }
1016
1017 fn is_subject(outer_dependency: &Dependency) -> bool {
1019 debug_assert!(
1020 matches!(
1021 outer_dependency.invalidation_kind(),
1022 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_)
1023 ),
1024 "Outer selector of relative selector is relative?"
1025 );
1026
1027 if let Some(x) = outer_dependency.next.as_ref() {
1028 if matches!(
1032 outer_dependency.invalidation_kind(),
1033 DependencyInvalidationKind::Normal(..)
1034 ) {
1035 if !Self::is_subject(&x.as_ref().slice()[0]) {
1036 return false;
1038 }
1039 }
1040 }
1041 outer_dependency
1042 .selector
1043 .is_rightmost(outer_dependency.selector_offset)
1044 }
1045}
1046
1047pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
1051 pub element: E,
1053 pub host: Option<OpaqueElement>,
1055 pub data: &'a mut ElementData,
1057 pub dependency: &'b Dependency,
1059 pub matching_context: MatchingContext<'a, E::Impl>,
1061 pub traversal_map: &'a SiblingTraversalMap<E>,
1063}
1064
1065impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'b, 'a, E>
1066 for RelativeSelectorOuterInvalidationProcessor<'a, 'b, E>
1067where
1068 E: TElement,
1069{
1070 fn invalidates_on_pseudo_element(&self) -> bool {
1071 true
1072 }
1073
1074 fn check_outer_dependency(
1075 &mut self,
1076 _dependency: &Dependency,
1077 _element: E,
1078 _: Option<OpaqueElement>,
1079 ) -> bool {
1080 true
1082 }
1083
1084 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
1085 &mut self.matching_context
1086 }
1087
1088 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1089 self.traversal_map
1090 }
1091
1092 fn collect_invalidations(
1093 &mut self,
1094 element: E,
1095 _self_invalidations: &mut InvalidationVector<'b>,
1096 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1097 sibling_invalidations: &mut InvalidationVector<'b>,
1098 ) -> bool {
1099 debug_assert_eq!(element, self.element);
1100 debug_assert!(
1101 self.matching_context.matching_for_invalidation(),
1102 "Not matching for invalidation?"
1103 );
1104
1105 let invalidated_self = {
1112 let mut invalidated = false;
1113 let mut dependencies_to_invalidate: SmallVec<[&Dependency; 1]> =
1114 smallvec![self.dependency];
1115 while let Some(d) = dependencies_to_invalidate.pop() {
1116 debug_assert!(
1117 matches!(
1118 d.invalidation_kind(),
1119 DependencyInvalidationKind::Normal(_)
1120 | DependencyInvalidationKind::Scope(_)
1121 ),
1122 "Unexpected dependency kind"
1123 );
1124 if !dependency_may_be_relevant(d, &element, false) {
1125 continue;
1126 }
1127 if !matches_selector(
1128 &d.selector,
1129 d.selector_offset,
1130 None,
1131 &element,
1132 self.matching_context(),
1133 ) {
1134 continue;
1135 }
1136
1137 let invalidation_kind = d.invalidation_kind();
1138
1139 if let DependencyInvalidationKind::Scope(scope_kind) = invalidation_kind {
1140 if d.selector.is_rightmost(d.selector_offset) {
1141 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd {
1142 let invalidations = note_scope_dependency_force_at_subject(
1143 d,
1144 self.matching_context.current_host.clone(),
1145 self.matching_context.scope_element,
1146 false,
1147 );
1148 descendant_invalidations
1149 .dom_descendants
1150 .extend(invalidations);
1151
1152 invalidated |= true;
1153 } else if let Some(ref next) = d.next {
1154 dependencies_to_invalidate.extend(next.as_ref().slice());
1155 }
1156 continue;
1157 }
1158 }
1159
1160 if matches!(
1161 invalidation_kind,
1162 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1163 ) {
1164 if let Some(ref deps) = d.next {
1165 dependencies_to_invalidate.push(&deps.as_ref().slice()[0]);
1167 continue;
1168 }
1169 invalidated |= true;
1170 continue;
1171 }
1172 debug_assert_ne!(d.selector_offset, 0);
1173 debug_assert_ne!(d.selector_offset, d.selector.len());
1174 let invalidation = Invalidation::new(&d, self.host, None);
1175 invalidated |= push_invalidation(
1176 invalidation,
1177 d.invalidation_kind(),
1178 descendant_invalidations,
1179 sibling_invalidations,
1180 );
1181 }
1182 invalidated
1183 };
1184
1185 if invalidated_self {
1186 self.data.hint.insert(RestyleHint::RESTYLE_SELF);
1187 }
1188 invalidated_self
1189 }
1190
1191 fn should_process_descendants(&mut self, element: E) -> bool {
1192 if element == self.element {
1193 return should_process_descendants(&self.data);
1194 }
1195
1196 match element.borrow_data() {
1197 Some(d) => should_process_descendants(&d),
1198 None => return false,
1199 }
1200 }
1201
1202 fn recursion_limit_exceeded(&mut self, _element: E) {
1203 unreachable!("Unexpected recursion limit");
1204 }
1205
1206 fn invalidated_descendants(&mut self, element: E, child: E) {
1207 invalidated_descendants(element, child)
1208 }
1209
1210 fn invalidated_self(&mut self, element: E) {
1211 debug_assert_ne!(element, self.element);
1212 invalidated_self(element);
1213 }
1214
1215 fn invalidated_sibling(&mut self, element: E, of: E) {
1216 debug_assert_ne!(element, self.element);
1217 invalidated_sibling(element, of);
1218 }
1219}
1220
1221pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1223where
1224 E: TElement + 'a,
1225{
1226 matching_context: MatchingContext<'b, E::Impl>,
1228 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1230 dependencies: &'c ElementDependencies<'a>,
1232 invalidations: InnerInvalidations<'a, E>,
1234 traversal_map: &'b SiblingTraversalMap<E>,
1236}
1237
1238impl<'a, 'b, 'c, E> RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1239where
1240 E: TElement + 'a,
1241{
1242 fn new(
1243 quirks_mode: QuirksMode,
1244 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1245 dependencies: &'c ElementDependencies<'a>,
1246 selector_caches: &'b mut SelectorCaches,
1247 traversal_map: &'b SiblingTraversalMap<E>,
1248 ) -> Self {
1249 let matching_context = MatchingContext::new_for_visited(
1250 MatchingMode::Normal,
1251 None,
1252 selector_caches,
1253 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
1254 IncludeStartingStyle::No,
1255 quirks_mode,
1256 NeedsSelectorFlags::No,
1257 MatchingForInvalidation::Yes,
1258 );
1259 Self {
1260 matching_context,
1261 snapshot_table,
1262 dependencies,
1263 invalidations: InnerInvalidations::default(),
1264 traversal_map,
1265 }
1266 }
1267
1268 fn note_dependency(
1269 &mut self,
1270 element: E,
1271 host: Option<OpaqueElement>,
1272 dependency: &'a Dependency,
1273 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1274 sibling_invalidations: &mut InvalidationVector<'a>,
1275 ) {
1276 match dependency.invalidation_kind() {
1277 DependencyInvalidationKind::FullSelector => unreachable!(),
1278 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => (),
1279 DependencyInvalidationKind::Relative(kind) => {
1280 self.found_relative_selector_invalidation(element, kind, dependency);
1281 return;
1282 },
1283 }
1284 if matches!(
1285 dependency.normal_invalidation_kind(),
1286 NormalDependencyInvalidationKind::Element
1287 ) {
1288 debug_assert!(
1290 dependency.next.is_some(),
1291 "Orphaned inner selector dependency?"
1292 );
1293 if let Some(next) = dependency.next.as_ref() {
1294 self.note_dependency(
1295 element,
1296 host,
1297 &next.as_ref().slice()[0],
1298 descendant_invalidations,
1299 sibling_invalidations,
1300 );
1301 }
1302 return;
1303 }
1304 let invalidation = Invalidation::new(&dependency, None, None);
1305 match dependency.normal_invalidation_kind() {
1306 NormalDependencyInvalidationKind::Descendants => {
1307 descendant_invalidations.dom_descendants.push(invalidation)
1309 },
1310 NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
1311 _ => (),
1316 }
1317 }
1318
1319 fn take_invalidations(self) -> InnerInvalidations<'a, E> {
1321 self.invalidations
1322 }
1323}
1324
1325impl<'a, 'b, 'c, E> InvalidationProcessor<'a, 'b, E>
1326 for RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1327where
1328 E: TElement + 'a,
1329{
1330 fn check_outer_dependency(
1331 &mut self,
1332 dependency: &Dependency,
1333 element: E,
1334 _: Option<OpaqueElement>,
1335 ) -> bool {
1336 if let Some(snapshot_table) = self.snapshot_table {
1337 let wrapper = ElementWrapper::new(element, snapshot_table);
1338 return check_dependency(
1339 dependency,
1340 &element,
1341 &wrapper,
1342 &mut self.matching_context,
1343 None,
1344 );
1345 }
1346 true
1348 }
1349
1350 fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
1351 return &mut self.matching_context;
1352 }
1353
1354 fn collect_invalidations(
1355 &mut self,
1356 element: E,
1357 _self_invalidations: &mut InvalidationVector<'a>,
1358 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1359 sibling_invalidations: &mut InvalidationVector<'a>,
1360 ) -> bool {
1361 for (scope, dependency) in self.dependencies {
1362 self.note_dependency(
1363 element,
1364 *scope,
1365 dependency,
1366 descendant_invalidations,
1367 sibling_invalidations,
1368 )
1369 }
1370 false
1371 }
1372
1373 fn should_process_descendants(&mut self, _element: E) -> bool {
1374 true
1375 }
1376
1377 fn recursion_limit_exceeded(&mut self, _element: E) {
1378 unreachable!("Unexpected recursion limit");
1379 }
1380
1381 fn invalidated_self(&mut self, _element: E) {}
1383 fn invalidated_sibling(&mut self, _sibling: E, _of: E) {}
1384 fn invalidated_descendants(&mut self, _element: E, _child: E) {}
1385
1386 fn found_relative_selector_invalidation(
1387 &mut self,
1388 element: E,
1389 kind: RelativeDependencyInvalidationKind,
1390 dep: &'a Dependency,
1391 ) {
1392 debug_assert!(dep.next.is_some(), "Orphaned inners selector?");
1393 if element.relative_selector_search_direction().is_empty() {
1394 return;
1395 }
1396 self.invalidations.push((
1397 element,
1398 RelativeSelectorInvalidation {
1399 host: self.matching_context.current_host,
1400 kind,
1401 dependency: &dep.next.as_ref().unwrap().as_ref().slice()[0],
1402 },
1403 ));
1404 }
1405
1406 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1407 &self.traversal_map
1408 }
1409}