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