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_descendants(&mut self, element: E, child: E);
174
175 fn found_relative_selector_invalidation(
179 &mut self,
180 _element: E,
181 _kind: RelativeDependencyInvalidationKind,
182 _relative_dependency: &'a Dependency,
183 ) {
184 debug_assert!(false, "Reached relative selector dependency");
185 }
186}
187
188#[derive(Debug, Default)]
190pub struct DescendantInvalidationLists<'a> {
191 pub dom_descendants: InvalidationVector<'a>,
196 pub slotted_descendants: InvalidationVector<'a>,
198 pub parts: InvalidationVector<'a>,
200}
201
202impl<'a> DescendantInvalidationLists<'a> {
203 fn is_empty(&self) -> bool {
204 self.dom_descendants.is_empty()
205 && self.slotted_descendants.is_empty()
206 && self.parts.is_empty()
207 }
208}
209
210pub struct TreeStyleInvalidator<'a, 'b, 'c, E, P: 'a>
213where
214 'b: 'a,
215 E: TElement,
216 P: InvalidationProcessor<'b, 'c, E>,
217{
218 element: E,
219 stack_limit_checker: Option<&'a StackLimitChecker>,
220 processor: &'a mut P,
221 _marker: std::marker::PhantomData<(&'b (), &'c ())>,
222}
223
224pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
226
227#[derive(Clone, Copy, Debug, Eq, PartialEq)]
229enum DescendantInvalidationKind {
230 Dom,
232 Slotted,
234 Part,
236}
237
238#[derive(Clone, Copy, Debug, Eq, PartialEq)]
243enum InvalidationKind {
244 Descendant(DescendantInvalidationKind),
245 Sibling,
246}
247
248pub enum InvalidationAddOverride {
250 Descendant,
252 Sibling,
254}
255
256#[derive(Clone)]
259pub struct Invalidation<'a> {
260 dependency: &'a Dependency,
265 host: Option<OpaqueElement>,
271 scope: Option<OpaqueElement>,
273 offset: usize,
280 matched_by_any_previous: bool,
287 always_effective_for_next_descendant: bool,
293}
294
295impl<'a> Invalidation<'a> {
296 pub fn new(
298 dependency: &'a Dependency,
299 host: Option<OpaqueElement>,
300 scope: Option<OpaqueElement>,
301 ) -> Self {
302 debug_assert!(
303 dependency.selector_offset == dependency.selector.len() + 1
304 || dependency.invalidation_kind()
305 != DependencyInvalidationKind::Normal(
306 NormalDependencyInvalidationKind::Element
307 ),
308 "No point to this, if the dependency matched the element we should just invalidate it"
309 );
310 Self {
311 dependency,
312 host,
313 scope,
314 offset: dependency.selector.len() + 1 - dependency.selector_offset,
316 matched_by_any_previous: false,
317 always_effective_for_next_descendant: false,
318 }
319 }
320
321 pub fn new_subject_invalidation(
327 dependency: &'a Dependency,
328 host: Option<OpaqueElement>,
329 scope: Option<OpaqueElement>,
330 ) -> Self {
331 let mut compound_offset = 0;
332 for s in dependency.selector.iter_raw_match_order() {
333 if s.is_combinator() {
334 break;
335 }
336 compound_offset += 1;
337 }
338
339 Self {
340 dependency,
341 host,
342 scope,
343 offset: dependency.selector.len() - compound_offset,
344 matched_by_any_previous: false,
345 always_effective_for_next_descendant: true,
346 }
347 }
348
349 pub fn new_always_effective_for_next_descendant(
354 dependency: &'a Dependency,
355 host: Option<OpaqueElement>,
356 scope: Option<OpaqueElement>,
357 ) -> Self {
358 if dependency.selector.is_rightmost(dependency.selector_offset) {
359 return Self::new_subject_invalidation(dependency, host, scope);
360 }
361
362 Self {
363 dependency,
364 host,
365 scope,
366 offset: dependency.selector.len() + 1 - dependency.selector_offset,
368 matched_by_any_previous: false,
369 always_effective_for_next_descendant: true,
370 }
371 }
372
373 pub fn combinator_to_right(&self) -> Combinator {
377 debug_assert_ne!(self.dependency.selector_offset, 0);
378 self.dependency
379 .selector
380 .combinator_at_match_order(self.dependency.selector.len() - self.offset)
381 }
382
383 fn effective_for_next(&self) -> bool {
386 if self.offset == 0 || self.always_effective_for_next_descendant {
387 return true;
388 }
389
390 match self
395 .dependency
396 .selector
397 .combinator_at_parse_order(self.offset - 1)
398 {
399 Combinator::Descendant | Combinator::LaterSibling | Combinator::PseudoElement => true,
400 Combinator::Part
401 | Combinator::SlotAssignment
402 | Combinator::NextSibling
403 | Combinator::Child => false,
404 }
405 }
406
407 fn kind(&self) -> InvalidationKind {
408 if self.offset == 0 {
409 return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
410 }
411
412 match self
413 .dependency
414 .selector
415 .combinator_at_parse_order(self.offset - 1)
416 {
417 Combinator::Child | Combinator::Descendant | Combinator::PseudoElement => {
418 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
419 },
420 Combinator::Part => InvalidationKind::Descendant(DescendantInvalidationKind::Part),
421 Combinator::SlotAssignment => {
422 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted)
423 },
424 Combinator::NextSibling | Combinator::LaterSibling => InvalidationKind::Sibling,
425 }
426 }
427}
428
429struct NegationScopeVisitor {
432 in_negation: bool,
434 found_scope_in_negation: bool,
436}
437
438impl NegationScopeVisitor {
439 fn new() -> Self {
441 Self {
442 in_negation: false,
443 found_scope_in_negation: false,
444 }
445 }
446
447 fn traverse_selector(
448 mut self,
449 selector: &Selector<<NegationScopeVisitor as SelectorVisitor>::Impl>,
450 ) -> bool {
451 selector.visit(&mut self);
452 self.found_scope_in_negation
453 }
454
455 fn traverse_dependency(mut self, dependency: &Dependency) -> bool {
461 if dependency.next.is_none()
462 || !matches!(
463 dependency.invalidation_kind(),
464 DependencyInvalidationKind::Normal(..)
465 )
466 {
467 dependency.selector.visit(&mut self);
468 return self.found_scope_in_negation;
469 }
470
471 let nested_visitor = Self {
472 in_negation: self.in_negation,
473 found_scope_in_negation: false,
474 };
475 dependency.selector.visit(&mut self);
476 nested_visitor.traverse_dependency(&dependency.next.as_ref().unwrap().slice()[0])
478 }
479}
480
481impl SelectorVisitor for NegationScopeVisitor {
482 type Impl = crate::selector_parser::SelectorImpl;
483
484 fn visit_attribute_selector(
485 &mut self,
486 _namespace: &selectors::attr::NamespaceConstraint<
487 &<Self::Impl as SelectorImpl>::NamespaceUrl,
488 >,
489 _local_name: &<Self::Impl as SelectorImpl>::LocalName,
490 _local_name_lower: &<Self::Impl as SelectorImpl>::LocalName,
491 ) -> bool {
492 true
493 }
494
495 fn visit_simple_selector(&mut self, component: &Component<Self::Impl>) -> bool {
496 if self.in_negation {
497 match component {
498 Component::Scope => {
499 self.found_scope_in_negation = true;
500 },
501 _ => {},
502 }
503 }
504 true
505 }
506
507 fn visit_relative_selector_list(
508 &mut self,
509 _list: &[selectors::parser::RelativeSelector<Self::Impl>],
510 ) -> bool {
511 true
512 }
513
514 fn visit_selector_list(
515 &mut self,
516 list_kind: selectors::visitor::SelectorListKind,
517 list: &[selectors::parser::Selector<Self::Impl>],
518 ) -> bool {
519 for nested in list {
520 let nested_visitor = Self {
521 in_negation: list_kind.in_negation(),
522 found_scope_in_negation: false,
523 };
524
525 self.found_scope_in_negation |= nested_visitor.traverse_selector(nested);
526 }
527 true
528 }
529
530 fn visit_complex_selector(&mut self, _combinator_to_right: Option<Combinator>) -> bool {
531 true
532 }
533}
534
535pub fn any_next_has_scope_in_negation(dependency: &Dependency) -> bool {
538 let next = match dependency.next.as_ref() {
539 None => return false,
540 Some(l) => l,
541 };
542
543 next.slice().iter().any(|dep| {
544 let visitor = NegationScopeVisitor::new();
545 visitor.traverse_dependency(dep)
546 })
547}
548
549impl<'a> fmt::Debug for Invalidation<'a> {
550 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
551 use cssparser::ToCss;
552
553 f.write_str("Invalidation(")?;
554 for component in self
555 .dependency
556 .selector
557 .iter_raw_parse_order_from(self.offset)
558 {
559 if matches!(*component, Component::Combinator(..)) {
560 break;
561 }
562 component.to_css(f)?;
563 }
564 f.write_char(')')
565 }
566}
567
568struct ProcessInvalidationResult {
570 invalidated_self: bool,
572 matched: bool,
575}
576
577pub struct InvalidationResult {
579 invalidated_self: bool,
581 invalidated_descendants: bool,
583 invalidated_siblings: bool,
585}
586
587impl InvalidationResult {
588 pub fn empty() -> Self {
590 Self {
591 invalidated_self: false,
592 invalidated_descendants: false,
593 invalidated_siblings: false,
594 }
595 }
596
597 pub fn has_invalidated_self(&self) -> bool {
599 self.invalidated_self
600 }
601
602 pub fn has_invalidated_descendants(&self) -> bool {
604 self.invalidated_descendants
605 }
606
607 pub fn has_invalidated_siblings(&self) -> bool {
609 self.invalidated_siblings
610 }
611}
612
613impl<'a, 'b, 'c, E, P: 'a> TreeStyleInvalidator<'a, 'b, 'c, E, P>
614where
615 'b: 'a,
616 E: TElement,
617 P: InvalidationProcessor<'b, 'c, E>,
618{
619 pub fn new(
621 element: E,
622 stack_limit_checker: Option<&'a StackLimitChecker>,
623 processor: &'a mut P,
624 ) -> Self {
625 Self {
626 element,
627 stack_limit_checker,
628 processor,
629 _marker: std::marker::PhantomData,
630 }
631 }
632
633 pub fn invalidate(mut self) -> InvalidationResult {
635 debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
636
637 let mut self_invalidations = InvalidationVector::new();
638 let mut descendant_invalidations = DescendantInvalidationLists::default();
639 let mut sibling_invalidations = InvalidationVector::new();
640
641 let mut invalidated_self = self.processor.collect_invalidations(
642 self.element,
643 &mut self_invalidations,
644 &mut descendant_invalidations,
645 &mut sibling_invalidations,
646 );
647
648 debug!("Collected invalidations (self: {}): ", invalidated_self);
649 debug!(
650 " > self: {}, {:?}",
651 self_invalidations.len(),
652 self_invalidations
653 );
654 debug!(" > descendants: {:?}", descendant_invalidations);
655 debug!(
656 " > siblings: {}, {:?}",
657 sibling_invalidations.len(),
658 sibling_invalidations
659 );
660
661 let invalidated_self_from_collection = invalidated_self;
662
663 invalidated_self |= self.process_descendant_invalidations(
664 &self_invalidations,
665 &mut descendant_invalidations,
666 &mut sibling_invalidations,
667 DescendantInvalidationKind::Dom,
668 );
669
670 if invalidated_self && !invalidated_self_from_collection {
671 self.processor.invalidated_self(self.element);
672 }
673
674 let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
675 let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
676
677 InvalidationResult {
678 invalidated_self,
679 invalidated_descendants,
680 invalidated_siblings,
681 }
682 }
683
684 fn invalidate_siblings(&mut self, sibling_invalidations: &mut InvalidationVector<'b>) -> bool {
690 if sibling_invalidations.is_empty() {
691 return false;
692 }
693
694 let mut current = self
695 .processor
696 .sibling_traversal_map()
697 .next_sibling_for(&self.element);
698 let mut any_invalidated = false;
699
700 while let Some(sibling) = current {
701 let mut sibling_invalidator =
702 TreeStyleInvalidator::new(sibling, self.stack_limit_checker, self.processor);
703
704 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
705 let invalidated_sibling = sibling_invalidator.process_sibling_invalidations(
706 &mut invalidations_for_descendants,
707 sibling_invalidations,
708 );
709
710 if invalidated_sibling {
711 sibling_invalidator
712 .processor
713 .invalidated_sibling(sibling, self.element);
714 }
715
716 any_invalidated |= invalidated_sibling;
717
718 any_invalidated |=
719 sibling_invalidator.invalidate_descendants(&invalidations_for_descendants);
720
721 if sibling_invalidations.is_empty() {
722 break;
723 }
724
725 current = self
726 .processor
727 .sibling_traversal_map()
728 .next_sibling_for(&sibling);
729 }
730
731 any_invalidated
732 }
733
734 fn invalidate_pseudo_element_or_nac(
735 &mut self,
736 child: E,
737 invalidations: &[Invalidation<'b>],
738 ) -> bool {
739 let mut sibling_invalidations = InvalidationVector::new();
740
741 let result = self.invalidate_child(
742 child,
743 invalidations,
744 &mut sibling_invalidations,
745 DescendantInvalidationKind::Dom,
746 );
747
748 result
756 }
757
758 fn invalidate_child(
761 &mut self,
762 child: E,
763 invalidations: &[Invalidation<'b>],
764 sibling_invalidations: &mut InvalidationVector<'b>,
765 descendant_invalidation_kind: DescendantInvalidationKind,
766 ) -> bool {
767 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
768
769 let mut invalidated_child = false;
770 let invalidated_descendants = {
771 let mut child_invalidator =
772 TreeStyleInvalidator::new(child, self.stack_limit_checker, self.processor);
773
774 invalidated_child |= child_invalidator.process_sibling_invalidations(
775 &mut invalidations_for_descendants,
776 sibling_invalidations,
777 );
778
779 invalidated_child |= child_invalidator.process_descendant_invalidations(
780 invalidations,
781 &mut invalidations_for_descendants,
782 sibling_invalidations,
783 descendant_invalidation_kind,
784 );
785
786 if invalidated_child {
787 child_invalidator.processor.invalidated_self(child);
788 }
789
790 child_invalidator.invalidate_descendants(&invalidations_for_descendants)
791 };
792
793 if invalidated_child || invalidated_descendants {
799 self.processor.invalidated_descendants(self.element, child);
800 }
801
802 invalidated_child || invalidated_descendants
803 }
804
805 fn invalidate_nac(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
806 let mut any_nac_root = false;
807
808 let element = self.element;
809 element.each_anonymous_content_child(|nac| {
810 any_nac_root |= self.invalidate_pseudo_element_or_nac(nac, invalidations);
811 });
812
813 any_nac_root
814 }
815
816 fn invalidate_dom_descendants_of(
819 &mut self,
820 parent: E::ConcreteNode,
821 invalidations: &[Invalidation<'b>],
822 ) -> bool {
823 let mut any_descendant = false;
824
825 let mut sibling_invalidations = InvalidationVector::new();
826 for child in parent.dom_children() {
827 let child = match child.as_element() {
828 Some(e) => e,
829 None => continue,
830 };
831
832 any_descendant |= self.invalidate_child(
833 child,
834 invalidations,
835 &mut sibling_invalidations,
836 DescendantInvalidationKind::Dom,
837 );
838 }
839
840 any_descendant
841 }
842
843 fn invalidate_parts_in_shadow_tree(
844 &mut self,
845 shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
846 invalidations: &[Invalidation<'b>],
847 ) -> bool {
848 debug_assert!(!invalidations.is_empty());
849
850 let mut any = false;
851 let mut sibling_invalidations = InvalidationVector::new();
852
853 for node in shadow.as_node().dom_descendants() {
854 let element = match node.as_element() {
855 Some(e) => e,
856 None => continue,
857 };
858
859 if element.has_part_attr() {
860 any |= self.invalidate_child(
861 element,
862 invalidations,
863 &mut sibling_invalidations,
864 DescendantInvalidationKind::Part,
865 );
866 debug_assert!(
867 sibling_invalidations.is_empty(),
868 "::part() shouldn't have sibling combinators to the right, \
869 this makes no sense! {:?}",
870 sibling_invalidations
871 );
872 }
873
874 if let Some(shadow) = element.shadow_root() {
875 if element.exports_any_part() {
876 any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
877 }
878 }
879 }
880
881 any
882 }
883
884 fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
885 if invalidations.is_empty() {
886 return false;
887 }
888
889 let shadow = match self.element.shadow_root() {
890 Some(s) => s,
891 None => return false,
892 };
893
894 self.invalidate_parts_in_shadow_tree(shadow, invalidations)
895 }
896
897 fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
898 if invalidations.is_empty() {
899 return false;
900 }
901
902 let slot = self.element;
903 self.invalidate_slotted_elements_in_slot(slot, invalidations)
904 }
905
906 fn invalidate_slotted_elements_in_slot(
907 &mut self,
908 slot: E,
909 invalidations: &[Invalidation<'b>],
910 ) -> bool {
911 let mut any = false;
912
913 let mut sibling_invalidations = InvalidationVector::new();
914 for node in slot.slotted_nodes() {
915 let element = match node.as_element() {
916 Some(e) => e,
917 None => continue,
918 };
919
920 if element.is_html_slot_element() {
921 any |= self.invalidate_slotted_elements_in_slot(element, invalidations);
922 } else {
923 any |= self.invalidate_child(
924 element,
925 invalidations,
926 &mut sibling_invalidations,
927 DescendantInvalidationKind::Slotted,
928 );
929 }
930
931 debug_assert!(
932 sibling_invalidations.is_empty(),
933 "::slotted() shouldn't have sibling combinators to the right, \
934 this makes no sense! {:?}",
935 sibling_invalidations
936 );
937 }
938
939 any
940 }
941
942 fn invalidate_non_slotted_descendants(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
943 if invalidations.is_empty() {
944 return false;
945 }
946
947 if self.processor.light_tree_only() {
948 let node = self.element.as_node();
949 return self.invalidate_dom_descendants_of(node, invalidations);
950 }
951
952 let mut any_descendant = false;
953
954 if let Some(root) = self.element.shadow_root() {
963 any_descendant |= self.invalidate_dom_descendants_of(root.as_node(), invalidations);
964 }
965
966 any_descendant |= self.invalidate_dom_descendants_of(self.element.as_node(), invalidations);
967
968 any_descendant |= self.invalidate_nac(invalidations);
969
970 any_descendant
971 }
972
973 fn invalidate_descendants(&mut self, invalidations: &DescendantInvalidationLists<'b>) -> bool {
976 if invalidations.is_empty() {
977 return false;
978 }
979
980 debug!(
981 "StyleTreeInvalidator::invalidate_descendants({:?})",
982 self.element
983 );
984 debug!(" > {:?}", invalidations);
985
986 let should_process = self.processor.should_process_descendants(self.element);
987
988 if !should_process {
989 return false;
990 }
991
992 if let Some(checker) = self.stack_limit_checker {
993 if checker.limit_exceeded() {
994 self.processor.recursion_limit_exceeded(self.element);
995 return true;
996 }
997 }
998
999 let mut any_descendant = false;
1000
1001 any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
1002 any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants);
1003 any_descendant |= self.invalidate_parts(&invalidations.parts);
1004
1005 any_descendant
1006 }
1007
1008 fn process_sibling_invalidations(
1020 &mut self,
1021 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1022 sibling_invalidations: &mut InvalidationVector<'b>,
1023 ) -> bool {
1024 let mut i = 0;
1025 let mut new_sibling_invalidations = InvalidationVector::new();
1026 let mut invalidated_self = false;
1027
1028 while i < sibling_invalidations.len() {
1029 let result = self.process_invalidation(
1030 &sibling_invalidations[i],
1031 descendant_invalidations,
1032 &mut new_sibling_invalidations,
1033 InvalidationKind::Sibling,
1034 );
1035
1036 invalidated_self |= result.invalidated_self;
1037 sibling_invalidations[i].matched_by_any_previous |= result.matched;
1038 if sibling_invalidations[i].effective_for_next() {
1039 i += 1;
1040 } else {
1041 sibling_invalidations.remove(i);
1042 }
1043 }
1044
1045 sibling_invalidations.extend(new_sibling_invalidations.drain(..));
1046 invalidated_self
1047 }
1048
1049 fn process_descendant_invalidations(
1055 &mut self,
1056 invalidations: &[Invalidation<'b>],
1057 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1058 sibling_invalidations: &mut InvalidationVector<'b>,
1059 descendant_invalidation_kind: DescendantInvalidationKind,
1060 ) -> bool {
1061 let mut invalidated = false;
1062
1063 for invalidation in invalidations {
1064 let result = self.process_invalidation(
1065 invalidation,
1066 descendant_invalidations,
1067 sibling_invalidations,
1068 InvalidationKind::Descendant(descendant_invalidation_kind),
1069 );
1070
1071 invalidated |= result.invalidated_self;
1072 if invalidation.effective_for_next() {
1073 let mut invalidation = invalidation.clone();
1074 invalidation.matched_by_any_previous |= result.matched;
1075 debug_assert_eq!(
1076 descendant_invalidation_kind,
1077 DescendantInvalidationKind::Dom,
1078 "Slotted or part invalidations don't propagate."
1079 );
1080 descendant_invalidations.dom_descendants.push(invalidation);
1081 }
1082 }
1083
1084 invalidated
1085 }
1086
1087 #[inline(always)]
1088 fn handle_fully_matched(
1089 &mut self,
1090 invalidation: &Invalidation<'b>,
1091 ) -> (ProcessInvalidationResult, SmallVec<[Invalidation<'b>; 1]>) {
1092 debug!(" > Invalidation matched completely");
1093 let mut to_process: SmallVec<[&Dependency; 1]> = SmallVec::from([invalidation.dependency]);
1096 let mut next_invalidations: SmallVec<[Invalidation; 1]> = SmallVec::new();
1097 let mut result = ProcessInvalidationResult {
1098 invalidated_self: false,
1099 matched: false,
1100 };
1101
1102 while !to_process.is_empty() {
1103 let mut next_dependencies: SmallVec<[&Dependency; 1]> = SmallVec::new();
1104
1105 while let Some(dependency) = to_process.pop() {
1106 if let DependencyInvalidationKind::Scope(scope_kind) =
1107 dependency.invalidation_kind()
1108 {
1109 if scope_kind == ScopeDependencyInvalidationKind::ImplicitScope {
1110 if let Some(ref deps) = dependency.next {
1111 for dep in deps.as_ref().slice() {
1112 let invalidation =
1113 Invalidation::new_always_effective_for_next_descendant(
1114 dep,
1115 invalidation.host,
1116 invalidation.scope,
1117 );
1118 next_invalidations.push(invalidation);
1119 }
1120 }
1121 continue;
1122 }
1123
1124 let force_add = any_next_has_scope_in_negation(dependency);
1125 if scope_kind == ScopeDependencyInvalidationKind::ScopeEnd || force_add {
1126 let invalidations = note_scope_dependency_force_at_subject(
1127 dependency,
1128 invalidation.host,
1129 invalidation.scope,
1130 force_add,
1131 );
1132
1133 next_invalidations.extend(invalidations);
1134
1135 continue;
1136 }
1137 }
1138
1139 match dependency.next {
1140 None => {
1141 result.invalidated_self = true;
1142 result.matched = true;
1143 },
1144 Some(ref deps) => {
1145 for n in deps.as_ref().slice() {
1146 let invalidation_kind = n.invalidation_kind();
1147 match invalidation_kind {
1148 DependencyInvalidationKind::FullSelector => unreachable!(),
1149 DependencyInvalidationKind::Normal(_) => next_dependencies.push(n),
1150 DependencyInvalidationKind::Scope(_) => {
1152 next_dependencies.push(n);
1153 },
1154 DependencyInvalidationKind::Relative(kind) => {
1155 self.processor.found_relative_selector_invalidation(
1156 self.element,
1157 kind,
1158 n,
1159 );
1160 result.matched = true;
1161 },
1162 }
1163 }
1164 },
1165 };
1166 }
1167
1168 for cur_dependency in next_dependencies.as_ref() {
1169 let scope = matches!(
1170 invalidation.dependency.invalidation_kind(),
1171 DependencyInvalidationKind::Scope(_)
1172 )
1173 .then(|| self.element.opaque());
1174 debug!(" > Checking outer dependency {:?}", cur_dependency);
1175
1176 if !self
1180 .processor
1181 .check_outer_dependency(cur_dependency, self.element, scope)
1182 {
1183 continue;
1185 }
1186
1187 let invalidation_kind = cur_dependency.invalidation_kind();
1188 if matches!(
1189 invalidation_kind,
1190 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1191 ) || (matches!(invalidation_kind, DependencyInvalidationKind::Scope(_))
1192 && cur_dependency.selector.is_rightmost(cur_dependency.selector_offset))
1193 {
1194 to_process.push(cur_dependency);
1196 continue;
1197 }
1198
1199 debug!(" > Generating invalidation");
1200 next_invalidations.push(Invalidation::new(
1201 cur_dependency,
1202 invalidation.host,
1203 scope,
1204 ));
1205 }
1206 }
1207 return (result, next_invalidations);
1208 }
1209
1210 fn process_invalidation(
1217 &mut self,
1218 invalidation: &Invalidation<'b>,
1219 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1220 sibling_invalidations: &mut InvalidationVector<'b>,
1221 invalidation_kind: InvalidationKind,
1222 ) -> ProcessInvalidationResult {
1223 debug!(
1224 "TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
1225 self.element, invalidation, invalidation_kind
1226 );
1227
1228 let matching_result = {
1229 let context = self.processor.matching_context();
1230 context.current_host = invalidation.host;
1231
1232 context.nest_for_scope_condition(invalidation.scope, |ctx| {
1233 matches_compound_selector_from(
1234 &invalidation.dependency.selector,
1235 invalidation.offset,
1236 ctx,
1237 &self.element,
1238 )
1239 })
1240 };
1241
1242 let (mut result, next_invalidations) = match matching_result {
1243 CompoundSelectorMatchingResult::NotMatched => {
1244 return ProcessInvalidationResult {
1245 invalidated_self: false,
1246 matched: false,
1247 }
1248 },
1249 CompoundSelectorMatchingResult::FullyMatched => self.handle_fully_matched(invalidation),
1250 CompoundSelectorMatchingResult::Matched {
1251 next_combinator_offset,
1252 } => (
1253 ProcessInvalidationResult {
1254 invalidated_self: false,
1255 matched: true,
1256 },
1257 smallvec![Invalidation {
1258 dependency: invalidation.dependency,
1259 host: invalidation.host,
1260 scope: invalidation.scope,
1261 offset: next_combinator_offset + 1,
1262 matched_by_any_previous: false,
1263 always_effective_for_next_descendant: invalidation
1264 .always_effective_for_next_descendant,
1265 }],
1266 ),
1267 };
1268
1269 for next_invalidation in next_invalidations {
1270 let next_invalidation_kind = if next_invalidation.always_effective_for_next_descendant {
1271 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
1272 } else {
1273 debug_assert_ne!(
1274 next_invalidation.offset, 0,
1275 "Rightmost selectors shouldn't generate more invalidations",
1276 );
1277
1278 let next_combinator = next_invalidation
1279 .dependency
1280 .selector
1281 .combinator_at_parse_order(next_invalidation.offset - 1);
1282
1283 if matches!(next_combinator, Combinator::PseudoElement)
1284 && self.processor.invalidates_on_pseudo_element()
1285 {
1286 result.invalidated_self = true;
1309 }
1310
1311 debug!(
1312 " > Invalidation matched, next: {:?}, ({:?})",
1313 next_invalidation, next_combinator
1314 );
1315
1316 next_invalidation.kind()
1317 };
1318
1319 let can_skip_pushing = next_invalidation_kind == invalidation_kind
1379 && invalidation.matched_by_any_previous
1380 && next_invalidation.effective_for_next();
1381
1382 if can_skip_pushing {
1383 debug!(
1384 " > Can avoid push, since the invalidation had \
1385 already been matched before"
1386 );
1387 } else {
1388 match next_invalidation_kind {
1389 InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
1390 descendant_invalidations
1391 .dom_descendants
1392 .push(next_invalidation);
1393 },
1394 InvalidationKind::Descendant(DescendantInvalidationKind::Part) => {
1395 descendant_invalidations.parts.push(next_invalidation);
1396 },
1397 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
1398 descendant_invalidations
1399 .slotted_descendants
1400 .push(next_invalidation);
1401 },
1402 InvalidationKind::Sibling => {
1403 sibling_invalidations.push(next_invalidation);
1404 },
1405 }
1406 }
1407 }
1408
1409 result
1410 }
1411}
1412
1413pub fn note_scope_dependency_force_at_subject<'selectors>(
1424 dependency: &'selectors Dependency,
1425 current_host: Option<OpaqueElement>,
1426 scope: Option<OpaqueElement>,
1427 traversed_non_subject: bool,
1428) -> Vec<Invalidation<'selectors>> {
1429 let mut invalidations: Vec<Invalidation> = Vec::new();
1430 if let Some(next) = dependency.next.as_ref() {
1431 for dep in next.slice() {
1432 if dep.selector.is_rightmost(dep.selector_offset) && !traversed_non_subject {
1433 continue;
1434 }
1435
1436 if dep.next.is_some()
1439 && matches!(
1440 dep.invalidation_kind(),
1441 DependencyInvalidationKind::Normal(_)
1442 )
1443 {
1444 invalidations.extend(note_scope_dependency_force_at_subject(
1445 dep,
1446 current_host,
1447 scope,
1448 true,
1451 ));
1452 } else {
1453 let invalidation = Invalidation::new_subject_invalidation(dep, current_host, scope);
1454
1455 invalidations.push(invalidation);
1456 }
1457 }
1458 }
1459 invalidations
1460}