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 {
503 match component {
504 Component::Scope => {
505 self.found_scope_in_negation = true;
506 },
507 _ => {},
508 }
509 }
510 true
511 }
512
513 fn visit_relative_selector_list(
514 &mut self,
515 _list: &[selectors::parser::RelativeSelector<Self::Impl>],
516 ) -> bool {
517 true
518 }
519
520 fn visit_selector_list(
521 &mut self,
522 list_kind: selectors::visitor::SelectorListKind,
523 list: &[selectors::parser::Selector<Self::Impl>],
524 ) -> bool {
525 for nested in list {
526 let nested_visitor = Self {
527 in_negation: list_kind.in_negation(),
528 found_scope_in_negation: false,
529 };
530
531 self.found_scope_in_negation |= nested_visitor.traverse_selector(nested);
532 }
533 true
534 }
535
536 fn visit_complex_selector(&mut self, _combinator_to_right: Option<Combinator>) -> bool {
537 true
538 }
539}
540
541pub fn any_next_has_scope_in_negation(dependency: &Dependency) -> bool {
544 let next = match dependency.next.as_ref() {
545 None => return false,
546 Some(l) => l,
547 };
548
549 next.slice().iter().any(|dep| {
550 let visitor = NegationScopeVisitor::new();
551 visitor.traverse_dependency(dep)
552 })
553}
554
555impl<'a> fmt::Debug for Invalidation<'a> {
556 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557 use cssparser::ToCss;
558
559 f.write_str("Invalidation(")?;
560 for component in self
561 .dependency
562 .selector
563 .iter_raw_parse_order_from(self.offset)
564 {
565 if matches!(*component, Component::Combinator(..)) {
566 break;
567 }
568 component.to_css(f)?;
569 }
570 f.write_char(')')
571 }
572}
573
574struct ProcessInvalidationResult {
576 invalidated_self: bool,
578 matched: bool,
581}
582
583pub struct InvalidationResult {
585 invalidated_self: bool,
587 invalidated_descendants: bool,
589 invalidated_siblings: bool,
591}
592
593impl InvalidationResult {
594 pub fn empty() -> Self {
596 Self {
597 invalidated_self: false,
598 invalidated_descendants: false,
599 invalidated_siblings: false,
600 }
601 }
602
603 pub fn has_invalidated_self(&self) -> bool {
605 self.invalidated_self
606 }
607
608 pub fn has_invalidated_descendants(&self) -> bool {
610 self.invalidated_descendants
611 }
612
613 pub fn has_invalidated_siblings(&self) -> bool {
615 self.invalidated_siblings
616 }
617}
618
619impl<'a, 'b, 'c, E, P: 'a> TreeStyleInvalidator<'a, 'b, 'c, E, P>
620where
621 'b: 'a,
622 E: TElement,
623 P: InvalidationProcessor<'b, 'c, E>,
624{
625 pub fn new(
627 element: E,
628 stack_limit_checker: Option<&'a StackLimitChecker>,
629 processor: &'a mut P,
630 ) -> Self {
631 Self {
632 element,
633 stack_limit_checker,
634 processor,
635 _marker: std::marker::PhantomData,
636 }
637 }
638
639 pub fn invalidate(mut self) -> InvalidationResult {
641 debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
642
643 let mut self_invalidations = InvalidationVector::new();
644 let mut descendant_invalidations = DescendantInvalidationLists::default();
645 let mut sibling_invalidations = InvalidationVector::new();
646
647 let mut invalidated_self = self.processor.collect_invalidations(
648 self.element,
649 &mut self_invalidations,
650 &mut descendant_invalidations,
651 &mut sibling_invalidations,
652 );
653
654 debug!("Collected invalidations (self: {}): ", invalidated_self);
655 debug!(
656 " > self: {}, {:?}",
657 self_invalidations.len(),
658 self_invalidations
659 );
660 debug!(" > descendants: {:?}", descendant_invalidations);
661 debug!(
662 " > siblings: {}, {:?}",
663 sibling_invalidations.len(),
664 sibling_invalidations
665 );
666
667 let invalidated_self_from_collection = invalidated_self;
668
669 invalidated_self |= self.process_descendant_invalidations(
670 &self_invalidations,
671 &mut descendant_invalidations,
672 &mut sibling_invalidations,
673 DescendantInvalidationKind::Dom,
674 );
675
676 if invalidated_self && !invalidated_self_from_collection {
677 self.processor.invalidated_self(self.element);
678 }
679
680 let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
681 let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
682
683 InvalidationResult {
684 invalidated_self,
685 invalidated_descendants,
686 invalidated_siblings,
687 }
688 }
689
690 fn invalidate_siblings(&mut self, sibling_invalidations: &mut InvalidationVector<'b>) -> bool {
696 if sibling_invalidations.is_empty() {
697 return false;
698 }
699
700 let mut current = self
701 .processor
702 .sibling_traversal_map()
703 .next_sibling_for(&self.element);
704 let mut any_invalidated = false;
705
706 while let Some(sibling) = current {
707 let mut sibling_invalidator =
708 TreeStyleInvalidator::new(sibling, self.stack_limit_checker, self.processor);
709
710 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
711 let invalidated_sibling = sibling_invalidator.process_sibling_invalidations(
712 &mut invalidations_for_descendants,
713 sibling_invalidations,
714 );
715
716 if invalidated_sibling {
717 sibling_invalidator
718 .processor
719 .invalidated_sibling(sibling, self.element);
720 }
721
722 any_invalidated |= invalidated_sibling;
723
724 any_invalidated |=
725 sibling_invalidator.invalidate_descendants(&invalidations_for_descendants);
726
727 if sibling_invalidations.is_empty() {
728 break;
729 }
730
731 current = self
732 .processor
733 .sibling_traversal_map()
734 .next_sibling_for(&sibling);
735 }
736
737 any_invalidated
738 }
739
740 fn invalidate_pseudo_element_or_nac(
741 &mut self,
742 child: E,
743 invalidations: &[Invalidation<'b>],
744 ) -> bool {
745 let mut sibling_invalidations = InvalidationVector::new();
746
747 let result = self.invalidate_child(
748 child,
749 invalidations,
750 &mut sibling_invalidations,
751 DescendantInvalidationKind::Dom,
752 );
753
754 result
762 }
763
764 fn invalidate_child(
767 &mut self,
768 child: E,
769 invalidations: &[Invalidation<'b>],
770 sibling_invalidations: &mut InvalidationVector<'b>,
771 descendant_invalidation_kind: DescendantInvalidationKind,
772 ) -> bool {
773 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
774
775 let mut invalidated_child = false;
776 let invalidated_descendants = {
777 let mut child_invalidator =
778 TreeStyleInvalidator::new(child, self.stack_limit_checker, self.processor);
779
780 invalidated_child |= child_invalidator.process_sibling_invalidations(
781 &mut invalidations_for_descendants,
782 sibling_invalidations,
783 );
784
785 invalidated_child |= child_invalidator.process_descendant_invalidations(
786 invalidations,
787 &mut invalidations_for_descendants,
788 sibling_invalidations,
789 descendant_invalidation_kind,
790 );
791
792 if invalidated_child {
793 child_invalidator.processor.invalidated_self(child);
794 }
795
796 child_invalidator.invalidate_descendants(&invalidations_for_descendants)
797 };
798
799 if invalidated_child || invalidated_descendants {
805 self.processor.invalidated_descendants(self.element, child);
806 }
807
808 invalidated_child || invalidated_descendants
809 }
810
811 fn invalidate_nac(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
812 let mut any_nac_root = false;
813
814 let element = self.element;
815 element.each_anonymous_content_child(|nac| {
816 any_nac_root |= self.invalidate_pseudo_element_or_nac(nac, invalidations);
817 });
818
819 any_nac_root
820 }
821
822 fn invalidate_dom_descendants_of(
825 &mut self,
826 parent: E::ConcreteNode,
827 invalidations: &[Invalidation<'b>],
828 ) -> bool {
829 let mut any_descendant = false;
830
831 let mut sibling_invalidations = InvalidationVector::new();
832 for child in parent.dom_children() {
833 let child = match child.as_element() {
834 Some(e) => e,
835 None => continue,
836 };
837
838 any_descendant |= self.invalidate_child(
839 child,
840 invalidations,
841 &mut sibling_invalidations,
842 DescendantInvalidationKind::Dom,
843 );
844 }
845
846 any_descendant
847 }
848
849 fn invalidate_parts_in_shadow_tree(
850 &mut self,
851 shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
852 invalidations: &[Invalidation<'b>],
853 ) -> bool {
854 debug_assert!(!invalidations.is_empty());
855
856 let mut any = false;
857 let mut sibling_invalidations = InvalidationVector::new();
858
859 for node in shadow.as_node().dom_descendants() {
860 let element = match node.as_element() {
861 Some(e) => e,
862 None => continue,
863 };
864
865 if element.has_part_attr() {
866 any |= self.invalidate_child(
867 element,
868 invalidations,
869 &mut sibling_invalidations,
870 DescendantInvalidationKind::Part,
871 );
872 debug_assert!(
873 sibling_invalidations.is_empty(),
874 "::part() shouldn't have sibling combinators to the right, \
875 this makes no sense! {:?}",
876 sibling_invalidations
877 );
878 }
879
880 if let Some(shadow) = element.shadow_root() {
881 if element.exports_any_part() {
882 any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
883 }
884 }
885 }
886
887 any
888 }
889
890 fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
891 if invalidations.is_empty() {
892 return false;
893 }
894
895 let shadow = match self.element.shadow_root() {
896 Some(s) => s,
897 None => return false,
898 };
899
900 self.invalidate_parts_in_shadow_tree(shadow, invalidations)
901 }
902
903 fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
904 if invalidations.is_empty() {
905 return false;
906 }
907
908 let slot = self.element;
909 self.invalidate_slotted_elements_in_slot(slot, invalidations)
910 }
911
912 fn invalidate_slotted_elements_in_slot(
913 &mut self,
914 slot: E,
915 invalidations: &[Invalidation<'b>],
916 ) -> bool {
917 let mut any = false;
918
919 let mut sibling_invalidations = InvalidationVector::new();
920 for node in slot.slotted_nodes() {
921 let element = match node.as_element() {
922 Some(e) => e,
923 None => continue,
924 };
925
926 if element.is_html_slot_element() {
927 any |= self.invalidate_slotted_elements_in_slot(element, invalidations);
928 } else {
929 any |= self.invalidate_child(
930 element,
931 invalidations,
932 &mut sibling_invalidations,
933 DescendantInvalidationKind::Slotted,
934 );
935 }
936
937 debug_assert!(
938 sibling_invalidations.is_empty(),
939 "::slotted() shouldn't have sibling combinators to the right, \
940 this makes no sense! {:?}",
941 sibling_invalidations
942 );
943 }
944
945 any
946 }
947
948 fn invalidate_non_slotted_descendants(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
949 if invalidations.is_empty() {
950 return false;
951 }
952
953 if self.processor.light_tree_only() {
954 let node = self.element.as_node();
955 return self.invalidate_dom_descendants_of(node, invalidations);
956 }
957
958 let mut any_descendant = false;
959
960 if let Some(root) = self.element.shadow_root() {
969 any_descendant |= self.invalidate_dom_descendants_of(root.as_node(), invalidations);
970 }
971
972 any_descendant |= self.invalidate_dom_descendants_of(self.element.as_node(), invalidations);
973
974 any_descendant |= self.invalidate_nac(invalidations);
975
976 any_descendant
977 }
978
979 fn invalidate_descendants(&mut self, invalidations: &DescendantInvalidationLists<'b>) -> bool {
982 if invalidations.is_empty() {
983 return false;
984 }
985
986 debug!(
987 "StyleTreeInvalidator::invalidate_descendants({:?})",
988 self.element
989 );
990 debug!(" > {:?}", invalidations);
991
992 let should_process = self.processor.should_process_descendants(self.element);
993
994 if !should_process {
995 return false;
996 }
997
998 if let Some(checker) = self.stack_limit_checker {
999 if checker.limit_exceeded() {
1000 self.processor.recursion_limit_exceeded(self.element);
1001 return true;
1002 }
1003 }
1004
1005 let mut any_descendant = false;
1006
1007 any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
1008 any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants);
1009 any_descendant |= self.invalidate_parts(&invalidations.parts);
1010
1011 any_descendant
1012 }
1013
1014 fn process_sibling_invalidations(
1026 &mut self,
1027 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1028 sibling_invalidations: &mut InvalidationVector<'b>,
1029 ) -> bool {
1030 let mut i = 0;
1031 let mut new_sibling_invalidations = InvalidationVector::new();
1032 let mut invalidated_self = false;
1033
1034 while i < sibling_invalidations.len() {
1035 let result = self.process_invalidation(
1036 &sibling_invalidations[i],
1037 descendant_invalidations,
1038 &mut new_sibling_invalidations,
1039 InvalidationKind::Sibling,
1040 );
1041
1042 invalidated_self |= result.invalidated_self;
1043 sibling_invalidations[i].matched_by_any_previous |= result.matched;
1044 if sibling_invalidations[i].effective_for_next() {
1045 i += 1;
1046 } else {
1047 sibling_invalidations.remove(i);
1048 }
1049 }
1050
1051 sibling_invalidations.extend(new_sibling_invalidations.drain(..));
1052 invalidated_self
1053 }
1054
1055 fn process_descendant_invalidations(
1061 &mut self,
1062 invalidations: &[Invalidation<'b>],
1063 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1064 sibling_invalidations: &mut InvalidationVector<'b>,
1065 descendant_invalidation_kind: DescendantInvalidationKind,
1066 ) -> bool {
1067 let mut invalidated = false;
1068
1069 for invalidation in invalidations {
1070 let result = self.process_invalidation(
1071 invalidation,
1072 descendant_invalidations,
1073 sibling_invalidations,
1074 InvalidationKind::Descendant(descendant_invalidation_kind),
1075 );
1076
1077 invalidated |= result.invalidated_self;
1078 if invalidation.effective_for_next() {
1079 let mut invalidation = invalidation.clone();
1080 invalidation.matched_by_any_previous |= result.matched;
1081 debug_assert_eq!(
1082 descendant_invalidation_kind,
1083 DescendantInvalidationKind::Dom,
1084 "Slotted or part invalidations don't propagate."
1085 );
1086 descendant_invalidations.dom_descendants.push(invalidation);
1087 }
1088 }
1089
1090 invalidated
1091 }
1092
1093 #[inline(always)]
1094 fn handle_fully_matched(
1095 &mut self,
1096 invalidation: &Invalidation<'b>,
1097 ) -> (ProcessInvalidationResult, SmallVec<[Invalidation<'b>; 1]>) {
1098 debug!(" > Invalidation matched completely");
1099 let mut to_process: SmallVec<[&Dependency; 1]> = SmallVec::from([invalidation.dependency]);
1102 let mut next_invalidations: SmallVec<[Invalidation; 1]> = SmallVec::new();
1103 let mut result = ProcessInvalidationResult {
1104 invalidated_self: false,
1105 matched: false,
1106 };
1107
1108 while !to_process.is_empty() {
1109 let mut next_dependencies: SmallVec<[&Dependency; 1]> = SmallVec::new();
1110
1111 while let Some(dependency) = to_process.pop() {
1112 if let DependencyInvalidationKind::Scope(scope_kind) =
1113 dependency.invalidation_kind()
1114 {
1115 if scope_kind == ScopeDependencyInvalidationKind::ImplicitScope {
1116 if let Some(ref deps) = dependency.next {
1117 for dep in deps.as_ref().slice() {
1118 let invalidation =
1119 Invalidation::new_always_effective_for_next_descendant(
1120 dep,
1121 invalidation.host,
1122 invalidation.scope,
1123 );
1124 next_invalidations.push(invalidation);
1125 }
1126 }
1127 continue;
1128 }
1129
1130 let force_add = any_next_has_scope_in_negation(dependency);
1131 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd || force_add {
1132 let invalidations = note_scope_dependency_force_at_subject(
1133 dependency,
1134 invalidation.host,
1135 invalidation.scope,
1136 force_add,
1137 );
1138
1139 next_invalidations.extend(invalidations);
1140
1141 continue;
1142 }
1143 }
1144
1145 match dependency.next {
1146 None => {
1147 result.invalidated_self = true;
1148 result.matched = true;
1149 },
1150 Some(ref deps) => {
1151 for n in deps.as_ref().slice() {
1152 let invalidation_kind = n.invalidation_kind();
1153 match invalidation_kind {
1154 DependencyInvalidationKind::FullSelector => unreachable!(),
1155 DependencyInvalidationKind::Normal(_) => next_dependencies.push(n),
1156 DependencyInvalidationKind::Scope(_) => {
1158 next_dependencies.push(n);
1159 },
1160 DependencyInvalidationKind::Relative(kind) => {
1161 self.processor.found_relative_selector_invalidation(
1162 self.element,
1163 kind,
1164 n,
1165 );
1166 result.matched = true;
1167 },
1168 }
1169 }
1170 },
1171 };
1172 }
1173
1174 for cur_dependency in next_dependencies.as_ref() {
1175 let scope = matches!(
1176 invalidation.dependency.invalidation_kind(),
1177 DependencyInvalidationKind::Scope(_)
1178 )
1179 .then(|| self.element.opaque());
1180 debug!(" > Checking outer dependency {:?}", cur_dependency);
1181
1182 if !self
1186 .processor
1187 .check_outer_dependency(cur_dependency, self.element, scope)
1188 {
1189 continue;
1191 }
1192
1193 let invalidation_kind = cur_dependency.invalidation_kind();
1194 if matches!(
1195 invalidation_kind,
1196 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1197 ) || (matches!(invalidation_kind, DependencyInvalidationKind::Scope(_))
1198 && cur_dependency
1199 .selector
1200 .is_rightmost(cur_dependency.selector_offset))
1201 {
1202 to_process.push(cur_dependency);
1204 continue;
1205 }
1206
1207 debug!(" > Generating invalidation");
1208 next_invalidations.push(Invalidation::new(
1209 cur_dependency,
1210 invalidation.host,
1211 scope,
1212 ));
1213 }
1214 }
1215 return (result, next_invalidations);
1216 }
1217
1218 fn process_invalidation(
1225 &mut self,
1226 invalidation: &Invalidation<'b>,
1227 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1228 sibling_invalidations: &mut InvalidationVector<'b>,
1229 invalidation_kind: InvalidationKind,
1230 ) -> ProcessInvalidationResult {
1231 debug!(
1232 "TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
1233 self.element, invalidation, invalidation_kind
1234 );
1235
1236 let matching_result = {
1237 let context = self.processor.matching_context();
1238 context.current_host = invalidation.host;
1239
1240 context.nest_for_scope_condition(invalidation.scope, |ctx| {
1241 matches_compound_selector_from(
1242 &invalidation.dependency.selector,
1243 invalidation.offset,
1244 ctx,
1245 &self.element,
1246 )
1247 })
1248 };
1249
1250 let (mut result, next_invalidations) = match matching_result {
1251 CompoundSelectorMatchingResult::NotMatched => {
1252 return ProcessInvalidationResult {
1253 invalidated_self: false,
1254 matched: false,
1255 }
1256 },
1257 CompoundSelectorMatchingResult::FullyMatched => self.handle_fully_matched(invalidation),
1258 CompoundSelectorMatchingResult::Matched {
1259 next_combinator_offset,
1260 } => (
1261 ProcessInvalidationResult {
1262 invalidated_self: false,
1263 matched: true,
1264 },
1265 smallvec![Invalidation {
1266 dependency: invalidation.dependency,
1267 host: invalidation.host,
1268 scope: invalidation.scope,
1269 offset: next_combinator_offset + 1,
1270 matched_by_any_previous: false,
1271 always_effective_for_next_descendant: invalidation
1272 .always_effective_for_next_descendant,
1273 }],
1274 ),
1275 };
1276
1277 for next_invalidation in next_invalidations {
1278 let next_invalidation_kind = if next_invalidation.always_effective_for_next_descendant {
1279 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
1280 } else {
1281 debug_assert_ne!(
1282 next_invalidation.offset, 0,
1283 "Rightmost selectors shouldn't generate more invalidations",
1284 );
1285
1286 let next_combinator = next_invalidation
1287 .dependency
1288 .selector
1289 .combinator_at_parse_order(next_invalidation.offset - 1);
1290
1291 if matches!(next_combinator, Combinator::PseudoElement)
1292 && self.processor.invalidates_on_pseudo_element()
1293 {
1294 result.invalidated_self = true;
1309
1310 if next_invalidation
1314 .dependency
1315 .selector
1316 .pseudo_element()
1317 .is_some_and(|p| p.is_lazy_painted_highlight_pseudo())
1318 {
1319 self.processor.invalidated_highlight_pseudo(self.element);
1320 }
1321 }
1322
1323 debug!(
1324 " > Invalidation matched, next: {:?}, ({:?})",
1325 next_invalidation, next_combinator
1326 );
1327
1328 next_invalidation.kind()
1329 };
1330
1331 let can_skip_pushing = next_invalidation_kind == invalidation_kind
1391 && invalidation.matched_by_any_previous
1392 && next_invalidation.effective_for_next();
1393
1394 if can_skip_pushing {
1395 debug!(
1396 " > Can avoid push, since the invalidation had \
1397 already been matched before"
1398 );
1399 } else {
1400 match next_invalidation_kind {
1401 InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
1402 descendant_invalidations
1403 .dom_descendants
1404 .push(next_invalidation);
1405 },
1406 InvalidationKind::Descendant(DescendantInvalidationKind::Part) => {
1407 descendant_invalidations.parts.push(next_invalidation);
1408 },
1409 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
1410 descendant_invalidations
1411 .slotted_descendants
1412 .push(next_invalidation);
1413 },
1414 InvalidationKind::Sibling => {
1415 sibling_invalidations.push(next_invalidation);
1416 },
1417 }
1418 }
1419 }
1420
1421 result
1422 }
1423}
1424
1425pub fn note_scope_dependency_force_at_subject<'selectors>(
1436 dependency: &'selectors Dependency,
1437 current_host: Option<OpaqueElement>,
1438 scope: Option<OpaqueElement>,
1439 traversed_non_subject: bool,
1440) -> Vec<Invalidation<'selectors>> {
1441 let mut invalidations: Vec<Invalidation> = Vec::new();
1442 if let Some(next) = dependency.next.as_ref() {
1443 for dep in next.slice() {
1444 if dep.selector.is_rightmost(dep.selector_offset) && !traversed_non_subject {
1445 continue;
1446 }
1447
1448 if dep.next.is_some()
1451 && matches!(
1452 dep.invalidation_kind(),
1453 DependencyInvalidationKind::Normal(_)
1454 )
1455 {
1456 invalidations.extend(note_scope_dependency_force_at_subject(
1457 dep,
1458 current_host,
1459 scope,
1460 true,
1463 ));
1464 } else {
1465 let invalidation = Invalidation::new_subject_invalidation(dep, current_host, scope);
1466
1467 invalidations.push(invalidation);
1468 }
1469 }
1470 }
1471 invalidations
1472}