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 matches_selector, ElementSelectorFlags, IncludeStartingStyle, MatchingContext,
34 MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, QuirksMode, SelectorCaches,
35 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_n = &a_deps.as_ref().slice()[0];
388 let b_n = &b_deps.as_ref().slice()[0];
389 if SelectorKey::new(&a_n.selector) != SelectorKey::new(&b_n.selector) {
390 return false;
391 }
392 a_next = a_n.next.as_ref();
393 b_next = b_n.next.as_ref();
394 }
395 if a_next.is_some() || b_next.is_some() {
396 return false;
397 }
398
399 let mut a_iter = a.selector.iter_from(a.selector_offset);
410 let mut b_iter = b.selector.iter_from(b.selector_offset);
411 loop {
412 let a_component = a_iter.next();
413 let b_component = b_iter.next();
414
415 if a_component != b_component {
416 return false;
417 }
418 let Some(component) = a_component else {
419 return true;
420 };
421 if !allow_indexed_selectors && component.has_indexed_selector_in_subject() {
422 return false;
424 }
425 }
426}
427
428impl<'a, E> RelativeSelectorDependencyCollector<'a, E>
429where
430 E: TElement,
431{
432 fn new(top: E, optimization_context: Option<OptimizationContext<'a, E>>) -> Self {
433 Self {
434 dependencies: FxHashMap::default(),
435 invalidations: AlreadyInvalidated::default(),
436 top,
437 optimization_context,
438 }
439 }
440
441 fn insert_invalidation(
442 &mut self,
443 element: E,
444 dependency: &'a Dependency,
445 host: Option<OpaqueElement>,
446 ) {
447 let in_subtree = element != self.top;
448 if let Some(entry) = self.invalidations.iter_mut().find(|entry| {
449 let both_in_subtree = in_subtree && entry.element != self.top;
452 let same_element = element == entry.element;
455 invalidation_can_collapse(
456 dependency,
457 entry.dependency,
458 both_in_subtree || same_element,
459 )
460 }) {
461 entry.update(element, host, dependency)
462 } else {
463 self.invalidations
464 .push(AlreadyInvalidatedEntry::new(element, host, dependency));
465 }
466 }
467
468 pub fn add_dependency(
471 &mut self,
472 dependency: &'a Dependency,
473 element: E,
474 host: Option<OpaqueElement>,
475 ) {
476 match dependency.invalidation_kind() {
477 DependencyInvalidationKind::FullSelector => unreachable!(),
478 DependencyInvalidationKind::Normal(..) | DependencyInvalidationKind::Scope(..) => {
479 self.dependencies
480 .entry(element)
481 .and_modify(|v| v.push((host, dependency)))
482 .or_default()
483 .push((host, dependency));
484 },
485 DependencyInvalidationKind::Relative(kind) => {
486 debug_assert!(
487 dependency.next.is_some(),
488 "Orphaned inner relative selector?"
489 );
490 if element != self.top
491 && matches!(
492 kind,
493 RelativeDependencyInvalidationKind::Parent
494 | RelativeDependencyInvalidationKind::PrevSibling
495 | RelativeDependencyInvalidationKind::EarlierSibling
496 )
497 {
498 return;
499 }
500 self.insert_invalidation(element, dependency, host);
501 },
502 };
503 }
504
505 fn get(self) -> ToInvalidate<'a, E> {
507 let mut result = ToInvalidate::default();
508 for invalidation in self.invalidations {
509 match invalidation.dependency.invalidation_kind() {
510 DependencyInvalidationKind::FullSelector => unreachable!(),
511 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => {
512 unreachable!("Inner selector in invalidation?")
513 },
514 DependencyInvalidationKind::Relative(kind) => {
515 if let Some(context) = self.optimization_context.as_ref() {
516 if context.can_be_ignored(
517 invalidation.element != self.top,
518 invalidation.element,
519 invalidation.host,
520 invalidation.dependency,
521 invalidation.leftmost_collapse_offset,
522 ) {
523 continue;
524 }
525 }
526 let dependency = &invalidation.dependency.next.as_ref().unwrap().slice()[0];
527 result.invalidations.push(RelativeSelectorInvalidation {
528 kind,
529 host: invalidation.host,
530 dependency,
531 });
532 if invalidation.element != self.top
536 && matches!(
537 kind,
538 RelativeDependencyInvalidationKind::AncestorEarlierSibling
539 | RelativeDependencyInvalidationKind::AncestorPrevSibling
540 )
541 {
542 result.invalidations.push(RelativeSelectorInvalidation {
543 kind: if matches!(
544 kind,
545 RelativeDependencyInvalidationKind::AncestorPrevSibling
546 ) {
547 RelativeDependencyInvalidationKind::PrevSibling
548 } else {
549 RelativeDependencyInvalidationKind::EarlierSibling
550 },
551 host: invalidation.host,
552 dependency,
553 });
554 }
555 },
556 };
557 }
558 for (key, element_dependencies) in self.dependencies {
559 result.dependencies.push((key, element_dependencies));
561 }
562 result
563 }
564
565 fn collect_all_dependencies_for_element(
566 &mut self,
567 element: E,
568 scope: Option<OpaqueElement>,
569 quirks_mode: QuirksMode,
570 map: &'a InvalidationMap,
571 additional_relative_selector_invalidation_map: &'a AdditionalRelativeSelectorInvalidationMap,
572 operation: DomMutationOperation,
573 ) {
574 element
575 .id()
576 .map(|v| match map.id_to_selector.get(v, quirks_mode) {
577 Some(v) => {
578 for dependency in v {
579 if !operation.accept(dependency, element) {
580 continue;
581 }
582 self.add_dependency(dependency, element, scope);
583 }
584 },
585 None => (),
586 });
587 element.each_class(|v| match map.class_to_selector.get(v, quirks_mode) {
588 Some(v) => {
589 for dependency in v {
590 if !operation.accept(dependency, element) {
591 continue;
592 }
593 self.add_dependency(dependency, element, scope);
594 }
595 },
596 None => (),
597 });
598 element.each_custom_state(|v| match map.custom_state_affecting_selectors.get(v) {
599 Some(v) => {
600 for dependency in v {
601 if !operation.accept(dependency, element) {
602 continue;
603 }
604 self.add_dependency(dependency, element, scope);
605 }
606 },
607 None => (),
608 });
609 element.each_attr_name(|v| match map.other_attribute_affecting_selectors.get(v) {
610 Some(v) => {
611 for dependency in v {
612 if !operation.accept(dependency, element) {
613 continue;
614 }
615 self.add_dependency(dependency, element, scope);
616 }
617 },
618 None => (),
619 });
620 let state = element.state();
621 map.state_affecting_selectors.lookup_with_additional(
622 element,
623 quirks_mode,
624 None,
625 &[],
626 ElementState::empty(),
627 |dependency| {
628 if !dependency.state.intersects(state) {
629 return true;
630 }
631 if !operation.accept(&dependency.dep, element) {
632 return true;
633 }
634 self.add_dependency(&dependency.dep, element, scope);
635 true
636 },
637 );
638
639 additional_relative_selector_invalidation_map
640 .ts_state_to_selector
641 .lookup_with_additional(
642 element,
643 quirks_mode,
644 None,
645 &[],
646 ElementState::empty(),
647 |dependency| {
648 if !operation.accept(&dependency.dep, element) {
649 return true;
650 }
651 if dependency.state.may_be_optimized() {
654 if operation.is_side_effect() {
655 return true;
658 }
659 debug_assert!(
660 self.optimization_context.is_some(),
661 "Optimization context not available for DOM mutation?"
662 );
663 if dependency.state.contains(TSStateForInvalidation::EMPTY)
664 && element.first_element_child().is_some()
665 {
666 return true;
667 }
668
669 let sibling_traversal_map = self
670 .optimization_context
671 .as_ref()
672 .unwrap()
673 .sibling_traversal_map;
674 if dependency
675 .state
676 .contains(TSStateForInvalidation::NTH_EDGE_FIRST)
677 && sibling_traversal_map.prev_sibling_for(&element).is_some()
678 {
679 return true;
680 }
681
682 if dependency
683 .state
684 .contains(TSStateForInvalidation::NTH_EDGE_LAST)
685 && sibling_traversal_map.next_sibling_for(&element).is_some()
686 {
687 return true;
688 }
689 }
690 self.add_dependency(&dependency.dep, element, scope);
691 true
692 },
693 );
694
695 if let Some(v) = additional_relative_selector_invalidation_map
696 .type_to_selector
697 .get(element.local_name())
698 {
699 for dependency in v {
700 if !operation.accept(dependency, element) {
701 continue;
702 }
703 self.add_dependency(dependency, element, scope);
704 }
705 }
706
707 for dependency in &additional_relative_selector_invalidation_map.any_to_selector {
708 if !operation.accept(dependency, element) {
709 continue;
710 }
711 self.add_dependency(dependency, element, scope);
712 }
713 }
714
715 fn is_empty(&self) -> bool {
716 self.invalidations.is_empty() && self.dependencies.is_empty()
717 }
718}
719
720impl<'a, 'b, E> RelativeSelectorInvalidator<'a, 'b, E>
721where
722 E: TElement + 'a,
723{
724 #[inline(never)]
726 pub fn invalidate_relative_selectors_for_this<F>(
727 self,
728 stylist: &'a Stylist,
729 mut gather_dependencies: F,
730 ) where
731 F: FnMut(
732 &E,
733 Option<OpaqueElement>,
734 &'a CascadeData,
735 QuirksMode,
736 &mut RelativeSelectorDependencyCollector<'a, E>,
737 ),
738 {
739 let mut collector = RelativeSelectorDependencyCollector::new(self.element, None);
740 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
741 let map = data.relative_invalidation_map_attributes();
742 if !map.used {
743 return;
744 }
745 gather_dependencies(
746 &self.element,
747 scope.map(|e| e.opaque()),
748 data,
749 self.quirks_mode,
750 &mut collector,
751 );
752 });
753 if collector.is_empty() {
754 return;
755 }
756 self.invalidate_from_dependencies(collector.get());
757 }
758
759 #[inline(never)]
761 pub fn invalidate_relative_selectors_for_dom_mutation(
762 self,
763 subtree: bool,
764 stylist: &'a Stylist,
765 inherited_search_path: ElementSelectorFlags,
766 operation: DomMutationOperation,
767 ) {
768 let mut collector = RelativeSelectorDependencyCollector::new(
769 self.element,
770 if operation.is_side_effect() {
771 None
772 } else {
773 Some(OptimizationContext {
774 sibling_traversal_map: &self.sibling_traversal_map,
775 quirks_mode: self.quirks_mode,
776 operation,
777 })
778 },
779 );
780 let mut traverse_subtree = false;
781 self.element.apply_selector_flags(inherited_search_path);
782 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
783 let map_attributes = data.relative_invalidation_map_attributes();
784 if !map_attributes.used {
785 return;
786 }
787 let map = data.relative_selector_invalidation_map();
788 traverse_subtree |= map_attributes.needs_ancestors_traversal;
789 collector.collect_all_dependencies_for_element(
790 self.element,
791 scope.map(|e| e.opaque()),
792 self.quirks_mode,
793 map,
794 map_attributes,
795 operation,
796 );
797 });
798
799 if subtree && traverse_subtree {
800 for node in self.element.as_node().dom_descendants() {
801 let descendant = match node.as_element() {
802 Some(e) => e,
803 None => continue,
804 };
805 descendant.apply_selector_flags(inherited_search_path);
806 stylist.for_each_cascade_data_with_scope(descendant, |data, scope| {
807 let map_attributes = data.relative_invalidation_map_attributes();
808 if !map_attributes.used {
809 return;
810 }
811 let map = data.relative_selector_invalidation_map();
812 collector.collect_all_dependencies_for_element(
813 descendant,
814 scope.map(|e| e.opaque()),
815 self.quirks_mode,
816 map,
817 map_attributes,
818 operation,
819 );
820 });
821 }
822 }
823 if collector.is_empty() {
824 return;
825 }
826 self.invalidate_from_dependencies(collector.get());
827 }
828
829 fn invalidate_from_dependencies(&self, to_invalidate: ToInvalidate<'a, E>) {
831 for (element, dependencies) in to_invalidate.dependencies {
832 let mut selector_caches = SelectorCaches::default();
833 let mut processor = RelativeSelectorInnerInvalidationProcessor::new(
834 self.quirks_mode,
835 self.snapshot_table,
836 &dependencies,
837 &mut selector_caches,
838 &self.sibling_traversal_map,
839 );
840 TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
841 for (element, invalidation) in processor.take_invalidations() {
842 self.invalidate_upwards(element, &invalidation);
843 }
844 }
845 for invalidation in to_invalidate.invalidations {
846 self.invalidate_upwards(self.element, &invalidation);
847 }
848 }
849
850 fn invalidate_upwards(&self, element: E, invalidation: &RelativeSelectorInvalidation<'a>) {
851 match invalidation.kind {
854 RelativeDependencyInvalidationKind::Parent => {
855 element.parent_element().map(|e| {
856 if !Self::in_search_direction(
857 &e,
858 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
859 ) {
860 return;
861 }
862 self.handle_anchor(e, invalidation.dependency, invalidation.host);
863 });
864 },
865 RelativeDependencyInvalidationKind::Ancestors => {
866 let mut parent = element.parent_element();
867 while let Some(par) = parent {
868 if !Self::in_search_direction(
869 &par,
870 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
871 ) {
872 return;
873 }
874 self.handle_anchor(par, invalidation.dependency, invalidation.host);
875 parent = par.parent_element();
876 }
877 },
878 RelativeDependencyInvalidationKind::PrevSibling => {
879 self.sibling_traversal_map
880 .prev_sibling_for(&element)
881 .map(|e| {
882 if !Self::in_search_direction(
883 &e,
884 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
885 ) {
886 return;
887 }
888 self.handle_anchor(e, invalidation.dependency, invalidation.host);
889 });
890 },
891 RelativeDependencyInvalidationKind::AncestorPrevSibling => {
892 let mut parent = element.parent_element();
893 while let Some(par) = parent {
894 if !Self::in_search_direction(
895 &par,
896 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
897 ) {
898 return;
899 }
900 par.prev_sibling_element().map(|e| {
901 if !Self::in_search_direction(
902 &e,
903 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
904 ) {
905 return;
906 }
907 self.handle_anchor(e, invalidation.dependency, invalidation.host);
908 });
909 parent = par.parent_element();
910 }
911 },
912 RelativeDependencyInvalidationKind::EarlierSibling => {
913 let mut sibling = self.sibling_traversal_map.prev_sibling_for(&element);
914 while let Some(sib) = sibling {
915 if !Self::in_search_direction(
916 &sib,
917 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
918 ) {
919 return;
920 }
921 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
922 sibling = sib.prev_sibling_element();
923 }
924 },
925 RelativeDependencyInvalidationKind::AncestorEarlierSibling => {
926 let mut parent = element.parent_element();
927 while let Some(par) = parent {
928 if !Self::in_search_direction(
929 &par,
930 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
931 ) {
932 return;
933 }
934 let mut sibling = par.prev_sibling_element();
935 while let Some(sib) = sibling {
936 if !Self::in_search_direction(
937 &sib,
938 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
939 ) {
940 return;
941 }
942 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
943 sibling = sib.prev_sibling_element();
944 }
945 parent = par.parent_element();
946 }
947 },
948 }
949 }
950
951 fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
953 element
954 .relative_selector_search_direction()
955 .intersects(desired)
956 }
957
958 fn handle_anchor(
960 &self,
961 element: E,
962 outer_dependency: &Dependency,
963 host: Option<OpaqueElement>,
964 ) {
965 let is_rightmost = Self::is_subject(outer_dependency);
966 if (is_rightmost
967 && !element.has_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR))
968 || (!is_rightmost
969 && !element.has_selector_flags(
970 ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT,
971 ))
972 {
973 return;
975 }
976 let mut selector_caches = SelectorCaches::default();
977 let matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
978 MatchingMode::Normal,
979 None,
980 &mut selector_caches,
981 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
982 IncludeStartingStyle::No,
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 ) {
1021 if !Self::is_subject(&x.as_ref().slice()[0]) {
1022 return false;
1024 }
1025 }
1026 }
1027 outer_dependency
1028 .selector
1029 .is_rightmost(outer_dependency.selector_offset)
1030 }
1031}
1032
1033pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
1037 pub element: E,
1039 pub host: Option<OpaqueElement>,
1041 pub data: &'a mut ElementData,
1043 pub dependency: &'b Dependency,
1045 pub matching_context: MatchingContext<'a, E::Impl>,
1047 pub traversal_map: &'a SiblingTraversalMap<E>,
1049}
1050
1051impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'b, 'a, E>
1052 for RelativeSelectorOuterInvalidationProcessor<'a, 'b, E>
1053where
1054 E: TElement,
1055{
1056 fn invalidates_on_pseudo_element(&self) -> bool {
1057 true
1058 }
1059
1060 fn check_outer_dependency(
1061 &mut self,
1062 _dependency: &Dependency,
1063 _element: E,
1064 _: Option<OpaqueElement>,
1065 ) -> bool {
1066 true
1068 }
1069
1070 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
1071 &mut self.matching_context
1072 }
1073
1074 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1075 self.traversal_map
1076 }
1077
1078 fn collect_invalidations(
1079 &mut self,
1080 element: E,
1081 _self_invalidations: &mut InvalidationVector<'b>,
1082 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1083 sibling_invalidations: &mut InvalidationVector<'b>,
1084 ) -> bool {
1085 debug_assert_eq!(element, self.element);
1086 debug_assert!(
1087 self.matching_context.matching_for_invalidation(),
1088 "Not matching for invalidation?"
1089 );
1090
1091 let invalidated_self = {
1098 let mut invalidated = false;
1099 let mut dependencies_to_invalidate: SmallVec<[&Dependency; 1]> =
1100 smallvec![self.dependency];
1101 while let Some(d) = dependencies_to_invalidate.pop() {
1102 debug_assert!(
1103 matches!(
1104 d.invalidation_kind(),
1105 DependencyInvalidationKind::Normal(_)
1106 | DependencyInvalidationKind::Scope(_)
1107 ),
1108 "Unexpected dependency kind"
1109 );
1110 if !dependency_may_be_relevant(d, &element, false) {
1111 continue;
1112 }
1113 if !matches_selector(
1114 &d.selector,
1115 d.selector_offset,
1116 None,
1117 &element,
1118 self.matching_context(),
1119 ) {
1120 continue;
1121 }
1122
1123 let invalidation_kind = d.invalidation_kind();
1124
1125 if let DependencyInvalidationKind::Scope(scope_kind) = invalidation_kind {
1126 if d.selector.is_rightmost(d.selector_offset) {
1127 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd {
1128 let invalidations = note_scope_dependency_force_at_subject(
1129 d,
1130 self.matching_context.current_host.clone(),
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
1146 if matches!(
1147 invalidation_kind,
1148 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1149 ) {
1150 if let Some(ref deps) = d.next {
1151 dependencies_to_invalidate.push(&deps.as_ref().slice()[0]);
1153 continue;
1154 }
1155 invalidated |= true;
1156 continue;
1157 }
1158 debug_assert_ne!(d.selector_offset, 0);
1159 debug_assert_ne!(d.selector_offset, d.selector.len());
1160 let invalidation = Invalidation::new(&d, self.host, None);
1161 invalidated |= push_invalidation(
1162 invalidation,
1163 d.invalidation_kind(),
1164 descendant_invalidations,
1165 sibling_invalidations,
1166 );
1167 }
1168 invalidated
1169 };
1170
1171 if invalidated_self {
1172 self.data.hint.insert(RestyleHint::RESTYLE_SELF);
1173 }
1174 invalidated_self
1175 }
1176
1177 fn should_process_descendants(&mut self, element: E) -> bool {
1178 if element == self.element {
1179 return should_process_descendants(&self.data);
1180 }
1181
1182 match element.borrow_data() {
1183 Some(d) => should_process_descendants(&d),
1184 None => return false,
1185 }
1186 }
1187
1188 fn recursion_limit_exceeded(&mut self, _element: E) {
1189 unreachable!("Unexpected recursion limit");
1190 }
1191
1192 fn invalidated_descendants(&mut self, element: E, child: E) {
1193 invalidated_descendants(element, child)
1194 }
1195
1196 fn invalidated_self(&mut self, element: E) {
1197 debug_assert_ne!(element, self.element);
1198 invalidated_self(element);
1199 }
1200
1201 fn invalidated_sibling(&mut self, element: E, of: E) {
1202 debug_assert_ne!(element, self.element);
1203 invalidated_sibling(element, of);
1204 }
1205}
1206
1207pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1209where
1210 E: TElement + 'a,
1211{
1212 matching_context: MatchingContext<'b, E::Impl>,
1214 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1216 dependencies: &'c ElementDependencies<'a>,
1218 invalidations: InnerInvalidations<'a, E>,
1220 traversal_map: &'b SiblingTraversalMap<E>,
1222}
1223
1224impl<'a, 'b, 'c, E> RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1225where
1226 E: TElement + 'a,
1227{
1228 fn new(
1229 quirks_mode: QuirksMode,
1230 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1231 dependencies: &'c ElementDependencies<'a>,
1232 selector_caches: &'b mut SelectorCaches,
1233 traversal_map: &'b SiblingTraversalMap<E>,
1234 ) -> Self {
1235 let matching_context = MatchingContext::new_for_visited(
1236 MatchingMode::Normal,
1237 None,
1238 selector_caches,
1239 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
1240 IncludeStartingStyle::No,
1241 quirks_mode,
1242 NeedsSelectorFlags::No,
1243 MatchingForInvalidation::Yes,
1244 );
1245 Self {
1246 matching_context,
1247 snapshot_table,
1248 dependencies,
1249 invalidations: InnerInvalidations::default(),
1250 traversal_map,
1251 }
1252 }
1253
1254 fn note_dependency(
1255 &mut self,
1256 element: E,
1257 host: Option<OpaqueElement>,
1258 dependency: &'a Dependency,
1259 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1260 sibling_invalidations: &mut InvalidationVector<'a>,
1261 ) {
1262 match dependency.invalidation_kind() {
1263 DependencyInvalidationKind::FullSelector => unreachable!(),
1264 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => (),
1265 DependencyInvalidationKind::Relative(kind) => {
1266 self.found_relative_selector_invalidation(element, kind, dependency);
1267 return;
1268 },
1269 }
1270 if matches!(
1271 dependency.normal_invalidation_kind(),
1272 NormalDependencyInvalidationKind::Element
1273 ) {
1274 debug_assert!(
1276 dependency.next.is_some(),
1277 "Orphaned inner selector dependency?"
1278 );
1279 if let Some(next) = dependency.next.as_ref() {
1280 self.note_dependency(
1281 element,
1282 host,
1283 &next.as_ref().slice()[0],
1284 descendant_invalidations,
1285 sibling_invalidations,
1286 );
1287 }
1288 return;
1289 }
1290 let invalidation = Invalidation::new(&dependency, None, None);
1291 match dependency.normal_invalidation_kind() {
1292 NormalDependencyInvalidationKind::Descendants => {
1293 descendant_invalidations.dom_descendants.push(invalidation)
1295 },
1296 NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
1297 _ => (),
1302 }
1303 }
1304
1305 fn take_invalidations(self) -> InnerInvalidations<'a, E> {
1307 self.invalidations
1308 }
1309}
1310
1311impl<'a, 'b, 'c, E> InvalidationProcessor<'a, 'b, E>
1312 for RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1313where
1314 E: TElement + 'a,
1315{
1316 fn check_outer_dependency(
1317 &mut self,
1318 dependency: &Dependency,
1319 element: E,
1320 _: Option<OpaqueElement>,
1321 ) -> bool {
1322 if let Some(snapshot_table) = self.snapshot_table {
1323 let wrapper = ElementWrapper::new(element, snapshot_table);
1324 return check_dependency(
1325 dependency,
1326 &element,
1327 &wrapper,
1328 &mut self.matching_context,
1329 None,
1330 );
1331 }
1332 true
1334 }
1335
1336 fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
1337 return &mut self.matching_context;
1338 }
1339
1340 fn collect_invalidations(
1341 &mut self,
1342 element: E,
1343 _self_invalidations: &mut InvalidationVector<'a>,
1344 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1345 sibling_invalidations: &mut InvalidationVector<'a>,
1346 ) -> bool {
1347 for (scope, dependency) in self.dependencies {
1348 self.note_dependency(
1349 element,
1350 *scope,
1351 dependency,
1352 descendant_invalidations,
1353 sibling_invalidations,
1354 )
1355 }
1356 false
1357 }
1358
1359 fn should_process_descendants(&mut self, _element: E) -> bool {
1360 true
1361 }
1362
1363 fn recursion_limit_exceeded(&mut self, _element: E) {
1364 unreachable!("Unexpected recursion limit");
1365 }
1366
1367 fn invalidated_self(&mut self, _element: E) {}
1369 fn invalidated_sibling(&mut self, _sibling: E, _of: E) {}
1370 fn invalidated_descendants(&mut self, _element: E, _child: E) {}
1371
1372 fn found_relative_selector_invalidation(
1373 &mut self,
1374 element: E,
1375 kind: RelativeDependencyInvalidationKind,
1376 dep: &'a Dependency,
1377 ) {
1378 debug_assert!(dep.next.is_some(), "Orphaned inners selector?");
1379 if element.relative_selector_search_direction().is_empty() {
1380 return;
1381 }
1382 self.invalidations.push((
1383 element,
1384 RelativeSelectorInvalidation {
1385 host: self.matching_context.current_host,
1386 kind,
1387 dependency: &dep.next.as_ref().unwrap().as_ref().slice()[0],
1388 },
1389 ));
1390 }
1391
1392 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1393 &self.traversal_map
1394 }
1395}