1use crate::context::StackLimitChecker;
9use crate::dom::{TElement, TNode, TShadowRoot};
10use crate::invalidation::element::invalidation_map::{
11 Dependency, DependencyInvalidationKind, NormalDependencyInvalidationKind,
12 RelativeDependencyInvalidationKind, ScopeDependencyInvalidationKind,
13};
14use selectors::matching::matches_compound_selector_from;
15use selectors::matching::{CompoundSelectorMatchingResult, MatchingContext};
16use selectors::parser::{Combinator, Component, Selector, SelectorVisitor};
17use selectors::{OpaqueElement, SelectorImpl};
18use smallvec::{smallvec, SmallVec};
19use std::fmt;
20use std::fmt::Write;
21
22struct SiblingInfo<E>
23where
24 E: TElement,
25{
26 affected: E,
27 prev_sibling: Option<E>,
28 next_sibling: Option<E>,
29}
30
31pub struct SiblingTraversalMap<E>
41where
42 E: TElement,
43{
44 info: Option<SiblingInfo<E>>,
45}
46
47impl<E> Default for SiblingTraversalMap<E>
48where
49 E: TElement,
50{
51 fn default() -> Self {
52 Self { info: None }
53 }
54}
55
56impl<E> SiblingTraversalMap<E>
57where
58 E: TElement,
59{
60 pub fn new(affected: E, prev_sibling: Option<E>, next_sibling: Option<E>) -> Self {
62 Self {
63 info: Some(SiblingInfo {
64 affected,
65 prev_sibling,
66 next_sibling,
67 }),
68 }
69 }
70
71 pub fn next_sibling_for(&self, element: &E) -> Option<E> {
73 if let Some(ref info) = self.info {
74 if *element == info.affected {
75 return info.next_sibling;
76 }
77 }
78 element.next_sibling_element()
79 }
80
81 pub fn prev_sibling_for(&self, element: &E) -> Option<E> {
83 if let Some(ref info) = self.info {
84 if *element == info.affected {
85 return info.prev_sibling;
86 }
87 }
88 element.prev_sibling_element()
89 }
90}
91
92pub trait InvalidationProcessor<'a, 'b, E>
94where
95 E: TElement,
96{
97 fn invalidates_on_pseudo_element(&self) -> bool {
101 false
102 }
103
104 fn light_tree_only(&self) -> bool {
108 false
109 }
110
111 fn check_outer_dependency(
134 &mut self,
135 dependency: &Dependency,
136 element: E,
137 scope: Option<OpaqueElement>,
138 ) -> bool;
139
140 fn matching_context(&mut self) -> &mut MatchingContext<'b, E::Impl>;
142
143 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E>;
145
146 fn collect_invalidations(
150 &mut self,
151 element: E,
152 self_invalidations: &mut InvalidationVector<'a>,
153 descendant_invalidations: &mut DescendantInvalidationLists<'a>,
154 sibling_invalidations: &mut InvalidationVector<'a>,
155 ) -> bool;
156
157 fn should_process_descendants(&mut self, element: E) -> bool;
160
161 fn recursion_limit_exceeded(&mut self, element: E);
164
165 fn invalidated_self(&mut self, element: E);
167
168 fn invalidated_sibling(&mut self, sibling: E, of: E);
171
172 fn invalidated_highlight_pseudo(&mut self, _element: E) {}
177
178 fn invalidated_descendants(&mut self, element: E, child: E);
180
181 fn found_relative_selector_invalidation(
185 &mut self,
186 _element: E,
187 _kind: RelativeDependencyInvalidationKind,
188 _relative_dependency: &'a Dependency,
189 ) {
190 debug_assert!(false, "Reached relative selector dependency");
191 }
192}
193
194#[derive(Debug, Default)]
196pub struct DescendantInvalidationLists<'a> {
197 pub dom_descendants: InvalidationVector<'a>,
202 pub slotted_descendants: InvalidationVector<'a>,
204 pub parts: InvalidationVector<'a>,
206}
207
208impl<'a> DescendantInvalidationLists<'a> {
209 fn is_empty(&self) -> bool {
210 self.dom_descendants.is_empty()
211 && self.slotted_descendants.is_empty()
212 && self.parts.is_empty()
213 }
214}
215
216pub struct TreeStyleInvalidator<'a, 'b, 'c, E, P: 'a>
219where
220 'b: 'a,
221 E: TElement,
222 P: InvalidationProcessor<'b, 'c, E>,
223{
224 element: E,
225 stack_limit_checker: Option<&'a StackLimitChecker>,
226 processor: &'a mut P,
227 _marker: std::marker::PhantomData<(&'b (), &'c ())>,
228}
229
230pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
232
233#[derive(Clone, Copy, Debug, Eq, PartialEq)]
235enum DescendantInvalidationKind {
236 Dom,
238 Slotted,
240 Part,
242}
243
244#[derive(Clone, Copy, Debug, Eq, PartialEq)]
249enum InvalidationKind {
250 Descendant(DescendantInvalidationKind),
251 Sibling,
252}
253
254pub enum InvalidationAddOverride {
256 Descendant,
258 Sibling,
260}
261
262#[derive(Clone)]
265pub struct Invalidation<'a> {
266 dependency: &'a Dependency,
271 host: Option<OpaqueElement>,
277 scope: Option<OpaqueElement>,
279 offset: usize,
286 matched_by_any_previous: bool,
293 always_effective_for_next_descendant: bool,
299}
300
301impl<'a> Invalidation<'a> {
302 pub fn new(
304 dependency: &'a Dependency,
305 host: Option<OpaqueElement>,
306 scope: Option<OpaqueElement>,
307 ) -> Self {
308 debug_assert!(
309 dependency.selector_offset == dependency.selector.len() + 1
310 || dependency.invalidation_kind()
311 != DependencyInvalidationKind::Normal(
312 NormalDependencyInvalidationKind::Element
313 ),
314 "No point to this, if the dependency matched the element we should just invalidate it"
315 );
316 Self {
317 dependency,
318 host,
319 scope,
320 offset: dependency.selector.len() + 1 - dependency.selector_offset,
322 matched_by_any_previous: false,
323 always_effective_for_next_descendant: false,
324 }
325 }
326
327 pub fn new_subject_invalidation(
333 dependency: &'a Dependency,
334 host: Option<OpaqueElement>,
335 scope: Option<OpaqueElement>,
336 ) -> Self {
337 let mut compound_offset = 0;
338 for s in dependency.selector.iter_raw_match_order() {
339 if s.is_combinator() {
340 break;
341 }
342 compound_offset += 1;
343 }
344
345 Self {
346 dependency,
347 host,
348 scope,
349 offset: dependency.selector.len() - compound_offset,
350 matched_by_any_previous: false,
351 always_effective_for_next_descendant: true,
352 }
353 }
354
355 pub fn new_always_effective_for_next_descendant(
360 dependency: &'a Dependency,
361 host: Option<OpaqueElement>,
362 scope: Option<OpaqueElement>,
363 ) -> Self {
364 if dependency.selector.is_rightmost(dependency.selector_offset) {
365 return Self::new_subject_invalidation(dependency, host, scope);
366 }
367
368 Self {
369 dependency,
370 host,
371 scope,
372 offset: dependency.selector.len() + 1 - dependency.selector_offset,
374 matched_by_any_previous: false,
375 always_effective_for_next_descendant: true,
376 }
377 }
378
379 pub fn combinator_to_right(&self) -> Combinator {
383 debug_assert_ne!(self.dependency.selector_offset, 0);
384 self.dependency
385 .selector
386 .combinator_at_match_order(self.dependency.selector.len() - self.offset)
387 }
388
389 fn effective_for_next(&self) -> bool {
392 if self.offset == 0 || self.always_effective_for_next_descendant {
393 return true;
394 }
395
396 match self
401 .dependency
402 .selector
403 .combinator_at_parse_order(self.offset - 1)
404 {
405 Combinator::Descendant | Combinator::LaterSibling | Combinator::PseudoElement => true,
406 Combinator::Part
407 | Combinator::SlotAssignment
408 | Combinator::NextSibling
409 | Combinator::Child => false,
410 }
411 }
412
413 fn kind(&self) -> InvalidationKind {
414 if self.offset == 0 {
415 return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
416 }
417
418 match self
419 .dependency
420 .selector
421 .combinator_at_parse_order(self.offset - 1)
422 {
423 Combinator::Child | Combinator::Descendant | Combinator::PseudoElement => {
424 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
425 },
426 Combinator::Part => InvalidationKind::Descendant(DescendantInvalidationKind::Part),
427 Combinator::SlotAssignment => {
428 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted)
429 },
430 Combinator::NextSibling | Combinator::LaterSibling => InvalidationKind::Sibling,
431 }
432 }
433}
434
435struct NegationScopeVisitor {
438 in_negation: bool,
440 found_scope_in_negation: bool,
442}
443
444impl NegationScopeVisitor {
445 fn new() -> Self {
447 Self {
448 in_negation: false,
449 found_scope_in_negation: false,
450 }
451 }
452
453 fn traverse_selector(
454 mut self,
455 selector: &Selector<<NegationScopeVisitor as SelectorVisitor>::Impl>,
456 ) -> bool {
457 selector.visit(&mut self);
458 self.found_scope_in_negation
459 }
460
461 fn traverse_dependency(mut self, dependency: &Dependency) -> bool {
467 if dependency.next.is_none()
468 || !matches!(
469 dependency.invalidation_kind(),
470 DependencyInvalidationKind::Normal(..)
471 )
472 {
473 dependency.selector.visit(&mut self);
474 return self.found_scope_in_negation;
475 }
476
477 let nested_visitor = Self {
478 in_negation: self.in_negation,
479 found_scope_in_negation: false,
480 };
481 dependency.selector.visit(&mut self);
482 nested_visitor.traverse_dependency(&dependency.next.as_ref().unwrap().slice()[0])
484 }
485}
486
487impl SelectorVisitor for NegationScopeVisitor {
488 type Impl = crate::selector_parser::SelectorImpl;
489
490 fn visit_attribute_selector(
491 &mut self,
492 _namespace: &selectors::attr::NamespaceConstraint<
493 &<Self::Impl as SelectorImpl>::NamespaceUrl,
494 >,
495 _local_name: &<Self::Impl as SelectorImpl>::LocalName,
496 _local_name_lower: &<Self::Impl as SelectorImpl>::LocalName,
497 ) -> bool {
498 true
499 }
500
501 fn visit_simple_selector(&mut self, component: &Component<Self::Impl>) -> bool {
502 if self.in_negation && component == &Component::Scope {
503 self.found_scope_in_negation = true;
504 }
505 true
506 }
507
508 fn visit_relative_selector_list(
509 &mut self,
510 _list: &[selectors::parser::RelativeSelector<Self::Impl>],
511 ) -> bool {
512 true
513 }
514
515 fn visit_selector_list(
516 &mut self,
517 list_kind: selectors::visitor::SelectorListKind,
518 list: &[selectors::parser::Selector<Self::Impl>],
519 ) -> bool {
520 for nested in list {
521 let nested_visitor = Self {
522 in_negation: list_kind.in_negation(),
523 found_scope_in_negation: false,
524 };
525
526 self.found_scope_in_negation |= nested_visitor.traverse_selector(nested);
527 }
528 true
529 }
530
531 fn visit_complex_selector(&mut self, _combinator_to_right: Option<Combinator>) -> bool {
532 true
533 }
534}
535
536pub fn any_next_has_scope_in_negation(dependency: &Dependency) -> bool {
539 let next = match dependency.next.as_ref() {
540 None => return false,
541 Some(l) => l,
542 };
543
544 next.slice().iter().any(|dep| {
545 let visitor = NegationScopeVisitor::new();
546 visitor.traverse_dependency(dep)
547 })
548}
549
550impl<'a> fmt::Debug for Invalidation<'a> {
551 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
552 use cssparser::ToCss;
553
554 f.write_str("Invalidation(")?;
555 for component in self
556 .dependency
557 .selector
558 .iter_raw_parse_order_from(self.offset)
559 {
560 if matches!(*component, Component::Combinator(..)) {
561 break;
562 }
563 component.to_css(f)?;
564 }
565 f.write_char(')')
566 }
567}
568
569struct ProcessInvalidationResult {
571 invalidated_self: bool,
573 matched: bool,
576}
577
578pub struct InvalidationResult {
580 invalidated_self: bool,
582 invalidated_descendants: bool,
584 invalidated_siblings: bool,
586}
587
588impl InvalidationResult {
589 pub fn empty() -> Self {
591 Self {
592 invalidated_self: false,
593 invalidated_descendants: false,
594 invalidated_siblings: false,
595 }
596 }
597
598 pub fn has_invalidated_self(&self) -> bool {
600 self.invalidated_self
601 }
602
603 pub fn has_invalidated_descendants(&self) -> bool {
605 self.invalidated_descendants
606 }
607
608 pub fn has_invalidated_siblings(&self) -> bool {
610 self.invalidated_siblings
611 }
612}
613
614impl<'a, 'b, 'c, E, P: 'a> TreeStyleInvalidator<'a, 'b, 'c, E, P>
615where
616 'b: 'a,
617 E: TElement,
618 P: InvalidationProcessor<'b, 'c, E>,
619{
620 pub fn new(
622 element: E,
623 stack_limit_checker: Option<&'a StackLimitChecker>,
624 processor: &'a mut P,
625 ) -> Self {
626 Self {
627 element,
628 stack_limit_checker,
629 processor,
630 _marker: std::marker::PhantomData,
631 }
632 }
633
634 pub fn invalidate(mut self) -> InvalidationResult {
636 debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
637
638 let mut self_invalidations = InvalidationVector::new();
639 let mut descendant_invalidations = DescendantInvalidationLists::default();
640 let mut sibling_invalidations = InvalidationVector::new();
641
642 let mut invalidated_self = self.processor.collect_invalidations(
643 self.element,
644 &mut self_invalidations,
645 &mut descendant_invalidations,
646 &mut sibling_invalidations,
647 );
648
649 debug!("Collected invalidations (self: {}): ", invalidated_self);
650 debug!(
651 " > self: {}, {:?}",
652 self_invalidations.len(),
653 self_invalidations
654 );
655 debug!(" > descendants: {:?}", descendant_invalidations);
656 debug!(
657 " > siblings: {}, {:?}",
658 sibling_invalidations.len(),
659 sibling_invalidations
660 );
661
662 let invalidated_self_from_collection = invalidated_self;
663
664 invalidated_self |= self.process_descendant_invalidations(
665 &self_invalidations,
666 &mut descendant_invalidations,
667 &mut sibling_invalidations,
668 DescendantInvalidationKind::Dom,
669 );
670
671 if invalidated_self && !invalidated_self_from_collection {
672 self.processor.invalidated_self(self.element);
673 }
674
675 let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
676 let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
677
678 InvalidationResult {
679 invalidated_self,
680 invalidated_descendants,
681 invalidated_siblings,
682 }
683 }
684
685 fn invalidate_siblings(&mut self, sibling_invalidations: &mut InvalidationVector<'b>) -> bool {
691 if sibling_invalidations.is_empty() {
692 return false;
693 }
694
695 let mut current = self
696 .processor
697 .sibling_traversal_map()
698 .next_sibling_for(&self.element);
699 let mut any_invalidated = false;
700
701 while let Some(sibling) = current {
702 let mut sibling_invalidator =
703 TreeStyleInvalidator::new(sibling, self.stack_limit_checker, self.processor);
704
705 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
706 let invalidated_sibling = sibling_invalidator.process_sibling_invalidations(
707 &mut invalidations_for_descendants,
708 sibling_invalidations,
709 );
710
711 if invalidated_sibling {
712 sibling_invalidator
713 .processor
714 .invalidated_sibling(sibling, self.element);
715 }
716
717 any_invalidated |= invalidated_sibling;
718
719 any_invalidated |=
720 sibling_invalidator.invalidate_descendants(&invalidations_for_descendants);
721
722 if sibling_invalidations.is_empty() {
723 break;
724 }
725
726 current = self
727 .processor
728 .sibling_traversal_map()
729 .next_sibling_for(&sibling);
730 }
731
732 any_invalidated
733 }
734
735 fn invalidate_pseudo_element_or_nac(
736 &mut self,
737 child: E,
738 invalidations: &[Invalidation<'b>],
739 ) -> bool {
740 let mut sibling_invalidations = InvalidationVector::new();
741
742 self.invalidate_child(
750 child,
751 invalidations,
752 &mut sibling_invalidations,
753 DescendantInvalidationKind::Dom,
754 )
755 }
756
757 fn invalidate_child(
760 &mut self,
761 child: E,
762 invalidations: &[Invalidation<'b>],
763 sibling_invalidations: &mut InvalidationVector<'b>,
764 descendant_invalidation_kind: DescendantInvalidationKind,
765 ) -> bool {
766 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
767
768 let mut invalidated_child = false;
769 let invalidated_descendants = {
770 let mut child_invalidator =
771 TreeStyleInvalidator::new(child, self.stack_limit_checker, self.processor);
772
773 if !sibling_invalidations.is_empty() {
774 invalidated_child |= child_invalidator.process_sibling_invalidations(
775 &mut invalidations_for_descendants,
776 sibling_invalidations,
777 );
778 }
779
780 invalidated_child |= child_invalidator.process_descendant_invalidations(
781 invalidations,
782 &mut invalidations_for_descendants,
783 sibling_invalidations,
784 descendant_invalidation_kind,
785 );
786
787 if invalidated_child {
788 child_invalidator.processor.invalidated_self(child);
789 }
790
791 child_invalidator.invalidate_descendants(&invalidations_for_descendants)
792 };
793
794 if invalidated_child || invalidated_descendants {
800 self.processor.invalidated_descendants(self.element, child);
801 }
802
803 invalidated_child || invalidated_descendants
804 }
805
806 fn invalidate_nac(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
807 let mut any_nac_root = false;
808
809 let element = self.element;
810 element.each_anonymous_content_child(|nac| {
811 any_nac_root |= self.invalidate_pseudo_element_or_nac(nac, invalidations);
812 });
813
814 any_nac_root
815 }
816
817 fn invalidate_dom_descendants_of(
820 &mut self,
821 parent: E::ConcreteNode,
822 invalidations: &[Invalidation<'b>],
823 ) -> bool {
824 let mut any_descendant = false;
825
826 let mut sibling_invalidations = InvalidationVector::new();
827 for child in parent.dom_children() {
828 let child = match child.as_element() {
829 Some(e) => e,
830 None => continue,
831 };
832
833 any_descendant |= self.invalidate_child(
834 child,
835 invalidations,
836 &mut sibling_invalidations,
837 DescendantInvalidationKind::Dom,
838 );
839 }
840
841 any_descendant
842 }
843
844 fn invalidate_parts_in_shadow_tree(
845 &mut self,
846 shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
847 invalidations: &[Invalidation<'b>],
848 ) -> bool {
849 debug_assert!(!invalidations.is_empty());
850
851 let mut any = false;
852 let mut sibling_invalidations = InvalidationVector::new();
853
854 for node in shadow.as_node().dom_descendants() {
855 let element = match node.as_element() {
856 Some(e) => e,
857 None => continue,
858 };
859
860 if element.has_part_attr() {
861 any |= self.invalidate_child(
862 element,
863 invalidations,
864 &mut sibling_invalidations,
865 DescendantInvalidationKind::Part,
866 );
867 debug_assert!(
868 sibling_invalidations.is_empty(),
869 "::part() shouldn't have sibling combinators to the right, \
870 this makes no sense! {:?}",
871 sibling_invalidations
872 );
873 }
874
875 if let Some(shadow) = element.shadow_root() {
876 if element.exports_any_part() {
877 any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
878 }
879 }
880 }
881
882 any
883 }
884
885 fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
886 if invalidations.is_empty() {
887 return false;
888 }
889
890 let shadow = match self.element.shadow_root() {
891 Some(s) => s,
892 None => return false,
893 };
894
895 self.invalidate_parts_in_shadow_tree(shadow, invalidations)
896 }
897
898 fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
899 if invalidations.is_empty() {
900 return false;
901 }
902
903 let slot = self.element;
904 self.invalidate_slotted_elements_in_slot(slot, invalidations)
905 }
906
907 fn invalidate_slotted_elements_in_slot(
908 &mut self,
909 slot: E,
910 invalidations: &[Invalidation<'b>],
911 ) -> bool {
912 let mut any = false;
913
914 let mut sibling_invalidations = InvalidationVector::new();
915 for node in slot.slotted_nodes() {
916 let element = match node.as_element() {
917 Some(e) => e,
918 None => continue,
919 };
920
921 if element.is_html_slot_element() {
922 any |= self.invalidate_slotted_elements_in_slot(element, invalidations);
923 } else {
924 any |= self.invalidate_child(
925 element,
926 invalidations,
927 &mut sibling_invalidations,
928 DescendantInvalidationKind::Slotted,
929 );
930 }
931
932 debug_assert!(
933 sibling_invalidations.is_empty(),
934 "::slotted() shouldn't have sibling combinators to the right, \
935 this makes no sense! {:?}",
936 sibling_invalidations
937 );
938 }
939
940 any
941 }
942
943 fn invalidate_non_slotted_descendants(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
944 if invalidations.is_empty() {
945 return false;
946 }
947
948 if self.processor.light_tree_only() {
949 let node = self.element.as_node();
950 return self.invalidate_dom_descendants_of(node, invalidations);
951 }
952
953 let mut any_descendant = false;
954
955 if let Some(root) = self.element.shadow_root() {
964 any_descendant |= self.invalidate_dom_descendants_of(root.as_node(), invalidations);
965 }
966
967 any_descendant |= self.invalidate_dom_descendants_of(self.element.as_node(), invalidations);
968
969 any_descendant |= self.invalidate_nac(invalidations);
970
971 any_descendant
972 }
973
974 fn invalidate_descendants(&mut self, invalidations: &DescendantInvalidationLists<'b>) -> bool {
977 if invalidations.is_empty() {
978 return false;
979 }
980
981 debug!(
982 "StyleTreeInvalidator::invalidate_descendants({:?})",
983 self.element
984 );
985 debug!(" > {:?}", invalidations);
986
987 let should_process = self.processor.should_process_descendants(self.element);
988
989 if !should_process {
990 return false;
991 }
992
993 if let Some(checker) = self.stack_limit_checker {
994 if checker.limit_exceeded() {
995 self.processor.recursion_limit_exceeded(self.element);
996 return true;
997 }
998 }
999
1000 let mut any_descendant = false;
1001
1002 any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
1003 any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants);
1004 any_descendant |= self.invalidate_parts(&invalidations.parts);
1005
1006 any_descendant
1007 }
1008
1009 fn process_sibling_invalidations(
1024 &mut self,
1025 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1026 sibling_invalidations: &mut InvalidationVector<'b>,
1027 ) -> bool {
1028 let mut i = 0;
1029 let mut new_sibling_invalidations = InvalidationVector::new();
1030 let mut invalidated_self = false;
1031
1032 while i < sibling_invalidations.len() {
1033 let result = self.process_invalidation(
1034 &sibling_invalidations[i],
1035 descendant_invalidations,
1036 &mut new_sibling_invalidations,
1037 InvalidationKind::Sibling,
1038 );
1039
1040 invalidated_self |= result.invalidated_self;
1041 sibling_invalidations[i].matched_by_any_previous |= result.matched;
1042 if sibling_invalidations[i].effective_for_next() {
1043 i += 1;
1044 } else {
1045 sibling_invalidations.remove(i);
1046 }
1047 }
1048
1049 sibling_invalidations.extend(new_sibling_invalidations.drain(..));
1050 invalidated_self
1051 }
1052
1053 fn process_descendant_invalidations(
1059 &mut self,
1060 invalidations: &[Invalidation<'b>],
1061 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1062 sibling_invalidations: &mut InvalidationVector<'b>,
1063 descendant_invalidation_kind: DescendantInvalidationKind,
1064 ) -> bool {
1065 let mut invalidated = false;
1066
1067 for invalidation in invalidations {
1068 let result = self.process_invalidation(
1069 invalidation,
1070 descendant_invalidations,
1071 sibling_invalidations,
1072 InvalidationKind::Descendant(descendant_invalidation_kind),
1073 );
1074
1075 invalidated |= result.invalidated_self;
1076 if invalidation.effective_for_next() {
1077 let mut invalidation = invalidation.clone();
1078 invalidation.matched_by_any_previous |= result.matched;
1079 debug_assert_eq!(
1080 descendant_invalidation_kind,
1081 DescendantInvalidationKind::Dom,
1082 "Slotted or part invalidations don't propagate."
1083 );
1084 descendant_invalidations.dom_descendants.push(invalidation);
1085 }
1086 }
1087
1088 invalidated
1089 }
1090
1091 #[inline(always)]
1092 fn handle_fully_matched(
1093 &mut self,
1094 invalidation: &Invalidation<'b>,
1095 ) -> (ProcessInvalidationResult, SmallVec<[Invalidation<'b>; 1]>) {
1096 debug!(" > Invalidation matched completely");
1097 let mut to_process: SmallVec<[&Dependency; 1]> = SmallVec::from([invalidation.dependency]);
1100 let mut next_invalidations: SmallVec<[Invalidation; 1]> = SmallVec::new();
1101 let mut result = ProcessInvalidationResult {
1102 invalidated_self: false,
1103 matched: false,
1104 };
1105
1106 while !to_process.is_empty() {
1107 let mut next_dependencies: SmallVec<[&Dependency; 1]> = SmallVec::new();
1108
1109 while let Some(dependency) = to_process.pop() {
1110 if let DependencyInvalidationKind::Scope(scope_kind) =
1111 dependency.invalidation_kind()
1112 {
1113 if scope_kind == ScopeDependencyInvalidationKind::ImplicitScope {
1114 if let Some(ref deps) = dependency.next {
1115 for dep in deps.as_ref().slice() {
1116 let invalidation =
1117 Invalidation::new_always_effective_for_next_descendant(
1118 dep,
1119 invalidation.host,
1120 invalidation.scope,
1121 );
1122 next_invalidations.push(invalidation);
1123 }
1124 }
1125 continue;
1126 }
1127
1128 let force_add = any_next_has_scope_in_negation(dependency);
1129 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd || force_add {
1130 let invalidations = note_scope_dependency_force_at_subject(
1131 dependency,
1132 invalidation.host,
1133 invalidation.scope,
1134 force_add,
1135 );
1136
1137 next_invalidations.extend(invalidations);
1138
1139 continue;
1140 }
1141 }
1142
1143 match dependency.next {
1144 None => {
1145 result.invalidated_self = true;
1146 result.matched = true;
1147 },
1148 Some(ref deps) => {
1149 for n in deps.as_ref().slice() {
1150 let invalidation_kind = n.invalidation_kind();
1151 match invalidation_kind {
1152 DependencyInvalidationKind::FullSelector => unreachable!(),
1153 DependencyInvalidationKind::Normal(_) => next_dependencies.push(n),
1154 DependencyInvalidationKind::Scope(_) => {
1156 next_dependencies.push(n);
1157 },
1158 DependencyInvalidationKind::Relative(kind) => {
1159 self.processor.found_relative_selector_invalidation(
1160 self.element,
1161 kind,
1162 n,
1163 );
1164 result.matched = true;
1165 },
1166 }
1167 }
1168 },
1169 };
1170 }
1171
1172 for cur_dependency in next_dependencies.as_ref() {
1173 let scope = matches!(
1174 invalidation.dependency.invalidation_kind(),
1175 DependencyInvalidationKind::Scope(_)
1176 )
1177 .then(|| self.element.opaque());
1178 debug!(" > Checking outer dependency {:?}", cur_dependency);
1179
1180 if !self
1184 .processor
1185 .check_outer_dependency(cur_dependency, self.element, scope)
1186 {
1187 continue;
1189 }
1190
1191 let invalidation_kind = cur_dependency.invalidation_kind();
1192 if matches!(
1193 invalidation_kind,
1194 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1195 ) || (matches!(invalidation_kind, DependencyInvalidationKind::Scope(_))
1196 && cur_dependency
1197 .selector
1198 .is_rightmost(cur_dependency.selector_offset))
1199 {
1200 to_process.push(cur_dependency);
1202 continue;
1203 }
1204
1205 debug!(" > Generating invalidation");
1206 next_invalidations.push(Invalidation::new(
1207 cur_dependency,
1208 invalidation.host,
1209 scope,
1210 ));
1211 }
1212 }
1213 (result, next_invalidations)
1214 }
1215
1216 fn process_invalidation(
1223 &mut self,
1224 invalidation: &Invalidation<'b>,
1225 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1226 sibling_invalidations: &mut InvalidationVector<'b>,
1227 invalidation_kind: InvalidationKind,
1228 ) -> ProcessInvalidationResult {
1229 debug!(
1230 "TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
1231 self.element, invalidation, invalidation_kind
1232 );
1233
1234 let matching_result = {
1235 let context = self.processor.matching_context();
1236 context.current_host = invalidation.host;
1237
1238 context.nest_for_scope_condition(invalidation.scope, |ctx| {
1239 matches_compound_selector_from(
1240 &invalidation.dependency.selector,
1241 invalidation.offset,
1242 ctx,
1243 &self.element,
1244 )
1245 })
1246 };
1247
1248 let (mut result, next_invalidations) = match matching_result {
1249 CompoundSelectorMatchingResult::NotMatched => {
1250 return ProcessInvalidationResult {
1251 invalidated_self: false,
1252 matched: false,
1253 }
1254 },
1255 CompoundSelectorMatchingResult::FullyMatched => self.handle_fully_matched(invalidation),
1256 CompoundSelectorMatchingResult::Matched {
1257 next_combinator_offset,
1258 } => (
1259 ProcessInvalidationResult {
1260 invalidated_self: false,
1261 matched: true,
1262 },
1263 smallvec![Invalidation {
1264 dependency: invalidation.dependency,
1265 host: invalidation.host,
1266 scope: invalidation.scope,
1267 offset: next_combinator_offset + 1,
1268 matched_by_any_previous: false,
1269 always_effective_for_next_descendant: invalidation
1270 .always_effective_for_next_descendant,
1271 }],
1272 ),
1273 };
1274
1275 for next_invalidation in next_invalidations {
1276 let next_invalidation_kind = if next_invalidation.always_effective_for_next_descendant {
1277 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
1278 } else {
1279 debug_assert_ne!(
1280 next_invalidation.offset, 0,
1281 "Rightmost selectors shouldn't generate more invalidations",
1282 );
1283
1284 let next_combinator = next_invalidation
1285 .dependency
1286 .selector
1287 .combinator_at_parse_order(next_invalidation.offset - 1);
1288
1289 if matches!(next_combinator, Combinator::PseudoElement)
1290 && self.processor.invalidates_on_pseudo_element()
1291 {
1292 result.invalidated_self = true;
1307
1308 if next_invalidation
1312 .dependency
1313 .selector
1314 .pseudo_element()
1315 .is_some_and(|p| p.is_lazy_painted_highlight_pseudo())
1316 {
1317 self.processor.invalidated_highlight_pseudo(self.element);
1318 }
1319 }
1320
1321 debug!(
1322 " > Invalidation matched, next: {:?}, ({:?})",
1323 next_invalidation, next_combinator
1324 );
1325
1326 next_invalidation.kind()
1327 };
1328
1329 let can_skip_pushing = next_invalidation_kind == invalidation_kind
1389 && invalidation.matched_by_any_previous
1390 && next_invalidation.effective_for_next();
1391
1392 if can_skip_pushing {
1393 debug!(
1394 " > Can avoid push, since the invalidation had \
1395 already been matched before"
1396 );
1397 } else {
1398 match next_invalidation_kind {
1399 InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
1400 descendant_invalidations
1401 .dom_descendants
1402 .push(next_invalidation);
1403 },
1404 InvalidationKind::Descendant(DescendantInvalidationKind::Part) => {
1405 descendant_invalidations.parts.push(next_invalidation);
1406 },
1407 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
1408 descendant_invalidations
1409 .slotted_descendants
1410 .push(next_invalidation);
1411 },
1412 InvalidationKind::Sibling => {
1413 sibling_invalidations.push(next_invalidation);
1414 },
1415 }
1416 }
1417 }
1418
1419 result
1420 }
1421}
1422
1423pub fn note_scope_dependency_force_at_subject<'selectors>(
1434 dependency: &'selectors Dependency,
1435 current_host: Option<OpaqueElement>,
1436 scope: Option<OpaqueElement>,
1437 traversed_non_subject: bool,
1438) -> Vec<Invalidation<'selectors>> {
1439 let mut invalidations: Vec<Invalidation> = Vec::new();
1440 if let Some(next) = dependency.next.as_ref() {
1441 for dep in next.slice() {
1442 if dep.selector.is_rightmost(dep.selector_offset) && !traversed_non_subject {
1443 continue;
1444 }
1445
1446 if dep.next.is_some()
1449 && matches!(
1450 dep.invalidation_kind(),
1451 DependencyInvalidationKind::Normal(_)
1452 )
1453 {
1454 invalidations.extend(note_scope_dependency_force_at_subject(
1455 dep,
1456 current_host,
1457 scope,
1458 true,
1461 ));
1462 } else {
1463 let invalidation = Invalidation::new_subject_invalidation(dep, current_host, scope);
1464
1465 invalidations.push(invalidation);
1466 }
1467 }
1468 }
1469 invalidations
1470}