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