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_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 if early_reject_by_local_name(
501 &dependency.selector,
502 dependency.selector_offset,
503 &element,
504 ) {
505 return;
506 }
507 self.insert_invalidation(element, dependency, host);
508 },
509 };
510 }
511
512 fn get(self) -> ToInvalidate<'a, E> {
514 let mut result = ToInvalidate::default();
515 for invalidation in self.invalidations {
516 match invalidation.dependency.invalidation_kind() {
517 DependencyInvalidationKind::FullSelector => unreachable!(),
518 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => {
519 unreachable!("Inner selector in invalidation?")
520 },
521 DependencyInvalidationKind::Relative(kind) => {
522 if let Some(context) = self.optimization_context.as_ref() {
523 if context.can_be_ignored(
524 invalidation.element != self.top,
525 invalidation.element,
526 invalidation.host,
527 invalidation.dependency,
528 invalidation.leftmost_collapse_offset,
529 ) {
530 continue;
531 }
532 }
533 let dependency = &invalidation.dependency.next.as_ref().unwrap().slice()[0];
534 result.invalidations.push(RelativeSelectorInvalidation {
535 kind,
536 host: invalidation.host,
537 dependency,
538 });
539 if invalidation.element != self.top
543 && matches!(
544 kind,
545 RelativeDependencyInvalidationKind::AncestorEarlierSibling
546 | RelativeDependencyInvalidationKind::AncestorPrevSibling
547 )
548 {
549 result.invalidations.push(RelativeSelectorInvalidation {
550 kind: if matches!(
551 kind,
552 RelativeDependencyInvalidationKind::AncestorPrevSibling
553 ) {
554 RelativeDependencyInvalidationKind::PrevSibling
555 } else {
556 RelativeDependencyInvalidationKind::EarlierSibling
557 },
558 host: invalidation.host,
559 dependency,
560 });
561 }
562 },
563 };
564 }
565 for (key, element_dependencies) in self.dependencies {
566 result.dependencies.push((key, element_dependencies));
568 }
569 result
570 }
571
572 fn collect_all_dependencies_for_element(
573 &mut self,
574 element: E,
575 scope: Option<OpaqueElement>,
576 quirks_mode: QuirksMode,
577 map: &'a InvalidationMap,
578 additional_relative_selector_invalidation_map: &'a AdditionalRelativeSelectorInvalidationMap,
579 operation: DomMutationOperation,
580 ) {
581 element
582 .id()
583 .map(|v| match map.id_to_selector.get(v, quirks_mode) {
584 Some(v) => {
585 for dependency in v {
586 if !operation.accept(dependency, element) {
587 continue;
588 }
589 self.add_dependency(dependency, element, scope);
590 }
591 },
592 None => (),
593 });
594 element.each_class(|v| match map.class_to_selector.get(v, quirks_mode) {
595 Some(v) => {
596 for dependency in v {
597 if !operation.accept(dependency, element) {
598 continue;
599 }
600 self.add_dependency(dependency, element, scope);
601 }
602 },
603 None => (),
604 });
605 element.each_custom_state(|v| match map.custom_state_affecting_selectors.get(v) {
606 Some(v) => {
607 for dependency in v {
608 if !operation.accept(dependency, element) {
609 continue;
610 }
611 self.add_dependency(dependency, element, scope);
612 }
613 },
614 None => (),
615 });
616 element.each_attr_name(|v| match map.other_attribute_affecting_selectors.get(v) {
617 Some(v) => {
618 for dependency in v {
619 if !operation.accept(dependency, element) {
620 continue;
621 }
622 self.add_dependency(dependency, element, scope);
623 }
624 },
625 None => (),
626 });
627 let state = element.state();
628 map.state_affecting_selectors.lookup_with_additional(
629 element,
630 quirks_mode,
631 None,
632 &[],
633 ElementState::empty(),
634 |dependency| {
635 if !dependency.state.intersects(state) {
636 return true;
637 }
638 if !operation.accept(&dependency.dep, element) {
639 return true;
640 }
641 self.add_dependency(&dependency.dep, element, scope);
642 true
643 },
644 );
645
646 additional_relative_selector_invalidation_map
647 .ts_state_to_selector
648 .lookup_with_additional(
649 element,
650 quirks_mode,
651 None,
652 &[],
653 ElementState::empty(),
654 |dependency| {
655 if !operation.accept(&dependency.dep, element) {
656 return true;
657 }
658 if dependency.state.may_be_optimized() {
661 if operation.is_side_effect() {
662 return true;
665 }
666 debug_assert!(
667 self.optimization_context.is_some(),
668 "Optimization context not available for DOM mutation?"
669 );
670 if dependency.state.contains(TSStateForInvalidation::EMPTY)
671 && element.first_element_child().is_some()
672 {
673 return true;
674 }
675
676 let sibling_traversal_map = self
677 .optimization_context
678 .as_ref()
679 .unwrap()
680 .sibling_traversal_map;
681 if dependency
682 .state
683 .contains(TSStateForInvalidation::NTH_EDGE_FIRST)
684 && sibling_traversal_map.prev_sibling_for(&element).is_some()
685 {
686 return true;
687 }
688
689 if dependency
690 .state
691 .contains(TSStateForInvalidation::NTH_EDGE_LAST)
692 && sibling_traversal_map.next_sibling_for(&element).is_some()
693 {
694 return true;
695 }
696 }
697 self.add_dependency(&dependency.dep, element, scope);
698 true
699 },
700 );
701
702 if let Some(v) = additional_relative_selector_invalidation_map
703 .type_to_selector
704 .get(element.local_name())
705 {
706 for dependency in v {
707 if !operation.accept(dependency, element) {
708 continue;
709 }
710 self.add_dependency(dependency, element, scope);
711 }
712 }
713
714 for dependency in &additional_relative_selector_invalidation_map.any_to_selector {
715 if !operation.accept(dependency, element) {
716 continue;
717 }
718 self.add_dependency(dependency, element, scope);
719 }
720 }
721
722 fn is_empty(&self) -> bool {
723 self.invalidations.is_empty() && self.dependencies.is_empty()
724 }
725}
726
727impl<'a, 'b, E> RelativeSelectorInvalidator<'a, 'b, E>
728where
729 E: TElement + 'a,
730{
731 #[inline(never)]
733 pub fn invalidate_relative_selectors_for_this<F>(
734 self,
735 stylist: &'a Stylist,
736 mut gather_dependencies: F,
737 ) where
738 F: FnMut(
739 &E,
740 Option<OpaqueElement>,
741 &'a CascadeData,
742 QuirksMode,
743 &mut RelativeSelectorDependencyCollector<'a, E>,
744 ),
745 {
746 let mut collector = RelativeSelectorDependencyCollector::new(self.element, None);
747 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
748 let map = data.relative_invalidation_map_attributes();
749 if !map.used {
750 return;
751 }
752 gather_dependencies(
753 &self.element,
754 scope.map(|e| e.opaque()),
755 data,
756 self.quirks_mode,
757 &mut collector,
758 );
759 });
760 if collector.is_empty() {
761 return;
762 }
763 self.invalidate_from_dependencies(collector.get());
764 }
765
766 #[inline(never)]
768 pub fn invalidate_relative_selectors_for_dom_mutation(
769 self,
770 subtree: bool,
771 stylist: &'a Stylist,
772 inherited_search_path: ElementSelectorFlags,
773 operation: DomMutationOperation,
774 ) {
775 let mut collector = RelativeSelectorDependencyCollector::new(
776 self.element,
777 if operation.is_side_effect() {
778 None
779 } else {
780 Some(OptimizationContext {
781 sibling_traversal_map: &self.sibling_traversal_map,
782 quirks_mode: self.quirks_mode,
783 operation,
784 })
785 },
786 );
787 let mut traverse_subtree = false;
788 self.element.apply_selector_flags(inherited_search_path);
789 stylist.for_each_cascade_data_with_scope(self.element, |data, scope| {
790 let map_attributes = data.relative_invalidation_map_attributes();
791 if !map_attributes.used {
792 return;
793 }
794 let map = data.relative_selector_invalidation_map();
795 traverse_subtree |= map_attributes.needs_ancestors_traversal;
796 collector.collect_all_dependencies_for_element(
797 self.element,
798 scope.map(|e| e.opaque()),
799 self.quirks_mode,
800 map,
801 map_attributes,
802 operation,
803 );
804 });
805
806 if subtree && traverse_subtree {
807 for node in self.element.as_node().dom_descendants() {
808 let descendant = match node.as_element() {
809 Some(e) => e,
810 None => continue,
811 };
812 descendant.apply_selector_flags(inherited_search_path);
813 stylist.for_each_cascade_data_with_scope(descendant, |data, scope| {
814 let map_attributes = data.relative_invalidation_map_attributes();
815 if !map_attributes.used {
816 return;
817 }
818 let map = data.relative_selector_invalidation_map();
819 collector.collect_all_dependencies_for_element(
820 descendant,
821 scope.map(|e| e.opaque()),
822 self.quirks_mode,
823 map,
824 map_attributes,
825 operation,
826 );
827 });
828 }
829 }
830 if collector.is_empty() {
831 return;
832 }
833 self.invalidate_from_dependencies(collector.get());
834 }
835
836 fn invalidate_from_dependencies(&self, to_invalidate: ToInvalidate<'a, E>) {
838 for (element, dependencies) in to_invalidate.dependencies {
839 let mut selector_caches = SelectorCaches::default();
840 let mut processor = RelativeSelectorInnerInvalidationProcessor::new(
841 self.quirks_mode,
842 self.snapshot_table,
843 &dependencies,
844 &mut selector_caches,
845 &self.sibling_traversal_map,
846 );
847 TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
848 for (element, invalidation) in processor.take_invalidations() {
849 self.invalidate_upwards(element, &invalidation);
850 }
851 }
852 for invalidation in to_invalidate.invalidations {
853 self.invalidate_upwards(self.element, &invalidation);
854 }
855 }
856
857 fn invalidate_upwards(&self, element: E, invalidation: &RelativeSelectorInvalidation<'a>) {
858 match invalidation.kind {
861 RelativeDependencyInvalidationKind::Parent => {
862 element.parent_element().map(|e| {
863 if !Self::in_search_direction(
864 &e,
865 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
866 ) {
867 return;
868 }
869 self.handle_anchor(e, invalidation.dependency, invalidation.host);
870 });
871 },
872 RelativeDependencyInvalidationKind::Ancestors => {
873 let mut parent = element.parent_element();
874 while let Some(par) = parent {
875 if !Self::in_search_direction(
876 &par,
877 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
878 ) {
879 return;
880 }
881 self.handle_anchor(par, invalidation.dependency, invalidation.host);
882 parent = par.parent_element();
883 }
884 },
885 RelativeDependencyInvalidationKind::PrevSibling => {
886 self.sibling_traversal_map
887 .prev_sibling_for(&element)
888 .map(|e| {
889 if !Self::in_search_direction(
890 &e,
891 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
892 ) {
893 return;
894 }
895 self.handle_anchor(e, invalidation.dependency, invalidation.host);
896 });
897 },
898 RelativeDependencyInvalidationKind::AncestorPrevSibling => {
899 let mut parent = element.parent_element();
900 while let Some(par) = parent {
901 if !Self::in_search_direction(
902 &par,
903 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
904 ) {
905 return;
906 }
907 par.prev_sibling_element().map(|e| {
908 if !Self::in_search_direction(
909 &e,
910 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
911 ) {
912 return;
913 }
914 self.handle_anchor(e, invalidation.dependency, invalidation.host);
915 });
916 parent = par.parent_element();
917 }
918 },
919 RelativeDependencyInvalidationKind::EarlierSibling => {
920 let mut sibling = self.sibling_traversal_map.prev_sibling_for(&element);
921 while let Some(sib) = sibling {
922 if !Self::in_search_direction(
923 &sib,
924 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
925 ) {
926 return;
927 }
928 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
929 sibling = sib.prev_sibling_element();
930 }
931 },
932 RelativeDependencyInvalidationKind::AncestorEarlierSibling => {
933 let mut parent = element.parent_element();
934 while let Some(par) = parent {
935 if !Self::in_search_direction(
936 &par,
937 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_ANCESTOR,
938 ) {
939 return;
940 }
941 let mut sibling = par.prev_sibling_element();
942 while let Some(sib) = sibling {
943 if !Self::in_search_direction(
944 &sib,
945 ElementSelectorFlags::RELATIVE_SELECTOR_SEARCH_DIRECTION_SIBLING,
946 ) {
947 return;
948 }
949 self.handle_anchor(sib, invalidation.dependency, invalidation.host);
950 sibling = sib.prev_sibling_element();
951 }
952 parent = par.parent_element();
953 }
954 },
955 }
956 }
957
958 fn in_search_direction(element: &E, desired: ElementSelectorFlags) -> bool {
960 element
961 .relative_selector_search_direction()
962 .intersects(desired)
963 }
964
965 fn handle_anchor(
967 &self,
968 element: E,
969 outer_dependency: &Dependency,
970 host: Option<OpaqueElement>,
971 ) {
972 let is_rightmost = Self::is_subject(outer_dependency);
973 if (is_rightmost
974 && !element.has_selector_flags(ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR))
975 || (!is_rightmost
976 && !element.has_selector_flags(
977 ElementSelectorFlags::ANCHORS_RELATIVE_SELECTOR_NON_SUBJECT,
978 ))
979 {
980 return;
982 }
983 let mut selector_caches = SelectorCaches::default();
984 let matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
985 MatchingMode::Normal,
986 None,
987 &mut selector_caches,
988 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
989 IncludeStartingStyle::No,
990 self.quirks_mode,
991 NeedsSelectorFlags::No,
992 MatchingForInvalidation::Yes,
993 );
994 let mut data = match element.mutate_data() {
995 Some(data) => data,
996 None => return,
997 };
998 let mut processor = RelativeSelectorOuterInvalidationProcessor {
999 element,
1000 host,
1001 data: data.deref_mut(),
1002 dependency: &*outer_dependency,
1003 matching_context,
1004 traversal_map: &self.sibling_traversal_map,
1005 };
1006 let result = TreeStyleInvalidator::new(element, None, &mut processor).invalidate();
1007 (self.invalidated)(element, &result);
1008 }
1009
1010 fn is_subject(outer_dependency: &Dependency) -> bool {
1012 debug_assert!(
1013 matches!(
1014 outer_dependency.invalidation_kind(),
1015 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_)
1016 ),
1017 "Outer selector of relative selector is relative?"
1018 );
1019
1020 if let Some(x) = outer_dependency.next.as_ref() {
1021 if matches!(
1025 outer_dependency.invalidation_kind(),
1026 DependencyInvalidationKind::Normal(..)
1027 ) {
1028 if !Self::is_subject(&x.as_ref().slice()[0]) {
1029 return false;
1031 }
1032 }
1033 }
1034 outer_dependency
1035 .selector
1036 .is_rightmost(outer_dependency.selector_offset)
1037 }
1038}
1039
1040pub struct RelativeSelectorOuterInvalidationProcessor<'a, 'b, E: TElement> {
1044 pub element: E,
1046 pub host: Option<OpaqueElement>,
1048 pub data: &'a mut ElementData,
1050 pub dependency: &'b Dependency,
1052 pub matching_context: MatchingContext<'a, E::Impl>,
1054 pub traversal_map: &'a SiblingTraversalMap<E>,
1056}
1057
1058impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'b, 'a, E>
1059 for RelativeSelectorOuterInvalidationProcessor<'a, 'b, E>
1060where
1061 E: TElement,
1062{
1063 fn invalidates_on_pseudo_element(&self) -> bool {
1064 true
1065 }
1066
1067 fn check_outer_dependency(
1068 &mut self,
1069 _dependency: &Dependency,
1070 _element: E,
1071 _: Option<OpaqueElement>,
1072 ) -> bool {
1073 true
1075 }
1076
1077 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
1078 &mut self.matching_context
1079 }
1080
1081 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1082 self.traversal_map
1083 }
1084
1085 fn collect_invalidations(
1086 &mut self,
1087 element: E,
1088 _self_invalidations: &mut InvalidationVector<'b>,
1089 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1090 sibling_invalidations: &mut InvalidationVector<'b>,
1091 ) -> bool {
1092 debug_assert_eq!(element, self.element);
1093 debug_assert!(
1094 self.matching_context.matching_for_invalidation(),
1095 "Not matching for invalidation?"
1096 );
1097
1098 let invalidated_self = {
1105 let mut invalidated = false;
1106 let mut dependencies_to_invalidate: SmallVec<[&Dependency; 1]> =
1107 smallvec![self.dependency];
1108 while let Some(d) = dependencies_to_invalidate.pop() {
1109 debug_assert!(
1110 matches!(
1111 d.invalidation_kind(),
1112 DependencyInvalidationKind::Normal(_)
1113 | DependencyInvalidationKind::Scope(_)
1114 ),
1115 "Unexpected dependency kind"
1116 );
1117 if !dependency_may_be_relevant(d, &element, false) {
1118 continue;
1119 }
1120 if !matches_selector(
1121 &d.selector,
1122 d.selector_offset,
1123 None,
1124 &element,
1125 self.matching_context(),
1126 ) {
1127 continue;
1128 }
1129
1130 let invalidation_kind = d.invalidation_kind();
1131
1132 if let DependencyInvalidationKind::Scope(scope_kind) = invalidation_kind {
1133 if d.selector.is_rightmost(d.selector_offset) {
1134 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd {
1135 let invalidations = note_scope_dependency_force_at_subject(
1136 d,
1137 self.matching_context.current_host.clone(),
1138 self.matching_context.scope_element,
1139 false,
1140 );
1141 descendant_invalidations
1142 .dom_descendants
1143 .extend(invalidations);
1144
1145 invalidated |= true;
1146 } else if let Some(ref next) = d.next {
1147 dependencies_to_invalidate.extend(next.as_ref().slice());
1148 }
1149 continue;
1150 }
1151 }
1152
1153 if matches!(
1154 invalidation_kind,
1155 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1156 ) {
1157 if let Some(ref deps) = d.next {
1158 dependencies_to_invalidate.push(&deps.as_ref().slice()[0]);
1160 continue;
1161 }
1162 invalidated |= true;
1163 continue;
1164 }
1165 debug_assert_ne!(d.selector_offset, 0);
1166 debug_assert_ne!(d.selector_offset, d.selector.len());
1167 let invalidation = Invalidation::new(&d, self.host, None);
1168 invalidated |= push_invalidation(
1169 invalidation,
1170 d.invalidation_kind(),
1171 descendant_invalidations,
1172 sibling_invalidations,
1173 );
1174 }
1175 invalidated
1176 };
1177
1178 if invalidated_self {
1179 self.data.hint.insert(RestyleHint::RESTYLE_SELF);
1180 }
1181 invalidated_self
1182 }
1183
1184 fn should_process_descendants(&mut self, element: E) -> bool {
1185 if element == self.element {
1186 return should_process_descendants(&self.data);
1187 }
1188
1189 match element.borrow_data() {
1190 Some(d) => should_process_descendants(&d),
1191 None => return false,
1192 }
1193 }
1194
1195 fn recursion_limit_exceeded(&mut self, _element: E) {
1196 unreachable!("Unexpected recursion limit");
1197 }
1198
1199 fn invalidated_descendants(&mut self, element: E, child: E) {
1200 invalidated_descendants(element, child)
1201 }
1202
1203 fn invalidated_self(&mut self, element: E) {
1204 debug_assert_ne!(element, self.element);
1205 invalidated_self(element);
1206 }
1207
1208 fn invalidated_sibling(&mut self, element: E, of: E) {
1209 debug_assert_ne!(element, self.element);
1210 invalidated_sibling(element, of);
1211 }
1212}
1213
1214pub struct RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1216where
1217 E: TElement + 'a,
1218{
1219 matching_context: MatchingContext<'b, E::Impl>,
1221 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1223 dependencies: &'c ElementDependencies<'a>,
1225 invalidations: InnerInvalidations<'a, E>,
1227 traversal_map: &'b SiblingTraversalMap<E>,
1229}
1230
1231impl<'a, 'b, 'c, E> RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1232where
1233 E: TElement + 'a,
1234{
1235 fn new(
1236 quirks_mode: QuirksMode,
1237 snapshot_table: Option<&'c ServoElementSnapshotTable>,
1238 dependencies: &'c ElementDependencies<'a>,
1239 selector_caches: &'b mut SelectorCaches,
1240 traversal_map: &'b SiblingTraversalMap<E>,
1241 ) -> Self {
1242 let matching_context = MatchingContext::new_for_visited(
1243 MatchingMode::Normal,
1244 None,
1245 selector_caches,
1246 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
1247 IncludeStartingStyle::No,
1248 quirks_mode,
1249 NeedsSelectorFlags::No,
1250 MatchingForInvalidation::Yes,
1251 );
1252 Self {
1253 matching_context,
1254 snapshot_table,
1255 dependencies,
1256 invalidations: InnerInvalidations::default(),
1257 traversal_map,
1258 }
1259 }
1260
1261 fn note_dependency(
1262 &mut self,
1263 element: E,
1264 host: Option<OpaqueElement>,
1265 dependency: &'a Dependency,
1266 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1267 sibling_invalidations: &mut InvalidationVector<'a>,
1268 ) {
1269 match dependency.invalidation_kind() {
1270 DependencyInvalidationKind::FullSelector => unreachable!(),
1271 DependencyInvalidationKind::Normal(_) | DependencyInvalidationKind::Scope(_) => (),
1272 DependencyInvalidationKind::Relative(kind) => {
1273 self.found_relative_selector_invalidation(element, kind, dependency);
1274 return;
1275 },
1276 }
1277 if matches!(
1278 dependency.normal_invalidation_kind(),
1279 NormalDependencyInvalidationKind::Element
1280 ) {
1281 debug_assert!(
1283 dependency.next.is_some(),
1284 "Orphaned inner selector dependency?"
1285 );
1286 if let Some(next) = dependency.next.as_ref() {
1287 self.note_dependency(
1288 element,
1289 host,
1290 &next.as_ref().slice()[0],
1291 descendant_invalidations,
1292 sibling_invalidations,
1293 );
1294 }
1295 return;
1296 }
1297 let invalidation = Invalidation::new(&dependency, None, None);
1298 match dependency.normal_invalidation_kind() {
1299 NormalDependencyInvalidationKind::Descendants => {
1300 descendant_invalidations.dom_descendants.push(invalidation)
1302 },
1303 NormalDependencyInvalidationKind::Siblings => sibling_invalidations.push(invalidation),
1304 _ => (),
1309 }
1310 }
1311
1312 fn take_invalidations(self) -> InnerInvalidations<'a, E> {
1314 self.invalidations
1315 }
1316}
1317
1318impl<'a, 'b, 'c, E> InvalidationProcessor<'a, 'b, E>
1319 for RelativeSelectorInnerInvalidationProcessor<'a, 'b, 'c, E>
1320where
1321 E: TElement + 'a,
1322{
1323 fn check_outer_dependency(
1324 &mut self,
1325 dependency: &Dependency,
1326 element: E,
1327 _: Option<OpaqueElement>,
1328 ) -> bool {
1329 if let Some(snapshot_table) = self.snapshot_table {
1330 let wrapper = ElementWrapper::new(element, snapshot_table);
1331 return check_dependency(
1332 dependency,
1333 &element,
1334 &wrapper,
1335 &mut self.matching_context,
1336 None,
1337 );
1338 }
1339 true
1341 }
1342
1343 fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl> {
1344 return &mut self.matching_context;
1345 }
1346
1347 fn collect_invalidations(
1348 &mut self,
1349 element: E,
1350 _self_invalidations: &mut InvalidationVector<'a>,
1351 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
1352 sibling_invalidations: &mut InvalidationVector<'a>,
1353 ) -> bool {
1354 for (scope, dependency) in self.dependencies {
1355 self.note_dependency(
1356 element,
1357 *scope,
1358 dependency,
1359 descendant_invalidations,
1360 sibling_invalidations,
1361 )
1362 }
1363 false
1364 }
1365
1366 fn should_process_descendants(&mut self, _element: E) -> bool {
1367 true
1368 }
1369
1370 fn recursion_limit_exceeded(&mut self, _element: E) {
1371 unreachable!("Unexpected recursion limit");
1372 }
1373
1374 fn invalidated_self(&mut self, _element: E) {}
1376 fn invalidated_sibling(&mut self, _sibling: E, _of: E) {}
1377 fn invalidated_descendants(&mut self, _element: E, _child: E) {}
1378
1379 fn found_relative_selector_invalidation(
1380 &mut self,
1381 element: E,
1382 kind: RelativeDependencyInvalidationKind,
1383 dep: &'a Dependency,
1384 ) {
1385 debug_assert!(dep.next.is_some(), "Orphaned inners selector?");
1386 if element.relative_selector_search_direction().is_empty() {
1387 return;
1388 }
1389 self.invalidations.push((
1390 element,
1391 RelativeSelectorInvalidation {
1392 host: self.matching_context.current_host,
1393 kind,
1394 dependency: &dep.next.as_ref().unwrap().as_ref().slice()[0],
1395 },
1396 ));
1397 }
1398
1399 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
1400 &self.traversal_map
1401 }
1402}