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};
17use selectors::OpaqueElement;
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}
288
289impl<'a> Invalidation<'a> {
290 pub fn new(
292 dependency: &'a Dependency,
293 host: Option<OpaqueElement>,
294 scope: Option<OpaqueElement>,
295 ) -> Self {
296 debug_assert!(
297 dependency.selector_offset == dependency.selector.len() + 1
298 || dependency.invalidation_kind()
299 != DependencyInvalidationKind::Normal(
300 NormalDependencyInvalidationKind::Element
301 ),
302 "No point to this, if the dependency matched the element we should just invalidate it"
303 );
304 Self {
305 dependency,
306 host,
307 scope,
308 offset: dependency.selector.len() + 1 - dependency.selector_offset,
310 matched_by_any_previous: false,
311 }
312 }
313
314 pub fn new_subject_invalidation(
320 dependency: &'a Dependency,
321 host: Option<OpaqueElement>,
322 scope: Option<OpaqueElement>,
323 ) -> Self {
324 let mut compound_offset = 0;
325 for s in dependency.selector.iter_raw_match_order() {
326 if s.is_combinator() {
327 break;
328 }
329 compound_offset += 1;
330 }
331
332 Self {
333 dependency,
334 host,
335 scope,
336 offset: dependency.selector.len() - compound_offset,
337 matched_by_any_previous: false,
338 }
339 }
340
341 fn effective_for_next(&self) -> bool {
344 if self.offset == 0 {
345 return true;
346 }
347
348 match self
353 .dependency
354 .selector
355 .combinator_at_parse_order(self.offset - 1)
356 {
357 Combinator::Descendant | Combinator::LaterSibling | Combinator::PseudoElement => true,
358 Combinator::Part
359 | Combinator::SlotAssignment
360 | Combinator::NextSibling
361 | Combinator::Child => false,
362 }
363 }
364
365 fn kind(&self) -> InvalidationKind {
366 if self.offset == 0 {
367 return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
368 }
369
370 match self
371 .dependency
372 .selector
373 .combinator_at_parse_order(self.offset - 1)
374 {
375 Combinator::Child | Combinator::Descendant | Combinator::PseudoElement => {
376 InvalidationKind::Descendant(DescendantInvalidationKind::Dom)
377 },
378 Combinator::Part => InvalidationKind::Descendant(DescendantInvalidationKind::Part),
379 Combinator::SlotAssignment => {
380 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted)
381 },
382 Combinator::NextSibling | Combinator::LaterSibling => InvalidationKind::Sibling,
383 }
384 }
385}
386
387impl<'a> fmt::Debug for Invalidation<'a> {
388 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
389 use cssparser::ToCss;
390
391 f.write_str("Invalidation(")?;
392 for component in self
393 .dependency
394 .selector
395 .iter_raw_parse_order_from(self.offset)
396 {
397 if matches!(*component, Component::Combinator(..)) {
398 break;
399 }
400 component.to_css(f)?;
401 }
402 f.write_char(')')
403 }
404}
405
406struct ProcessInvalidationResult {
408 invalidated_self: bool,
410 matched: bool,
413}
414
415pub struct InvalidationResult {
417 invalidated_self: bool,
419 invalidated_descendants: bool,
421 invalidated_siblings: bool,
423}
424
425impl InvalidationResult {
426 pub fn empty() -> Self {
428 Self {
429 invalidated_self: false,
430 invalidated_descendants: false,
431 invalidated_siblings: false,
432 }
433 }
434
435 pub fn has_invalidated_self(&self) -> bool {
437 self.invalidated_self
438 }
439
440 pub fn has_invalidated_descendants(&self) -> bool {
442 self.invalidated_descendants
443 }
444
445 pub fn has_invalidated_siblings(&self) -> bool {
447 self.invalidated_siblings
448 }
449}
450
451impl<'a, 'b, 'c, E, P: 'a> TreeStyleInvalidator<'a, 'b, 'c, E, P>
452where
453 'b: 'a,
454 E: TElement,
455 P: InvalidationProcessor<'b, 'c, E>,
456{
457 pub fn new(
459 element: E,
460 stack_limit_checker: Option<&'a StackLimitChecker>,
461 processor: &'a mut P,
462 ) -> Self {
463 Self {
464 element,
465 stack_limit_checker,
466 processor,
467 _marker: std::marker::PhantomData,
468 }
469 }
470
471 pub fn invalidate(mut self) -> InvalidationResult {
473 debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
474
475 let mut self_invalidations = InvalidationVector::new();
476 let mut descendant_invalidations = DescendantInvalidationLists::default();
477 let mut sibling_invalidations = InvalidationVector::new();
478
479 let mut invalidated_self = self.processor.collect_invalidations(
480 self.element,
481 &mut self_invalidations,
482 &mut descendant_invalidations,
483 &mut sibling_invalidations,
484 );
485
486 debug!("Collected invalidations (self: {}): ", invalidated_self);
487 debug!(
488 " > self: {}, {:?}",
489 self_invalidations.len(),
490 self_invalidations
491 );
492 debug!(" > descendants: {:?}", descendant_invalidations);
493 debug!(
494 " > siblings: {}, {:?}",
495 sibling_invalidations.len(),
496 sibling_invalidations
497 );
498
499 let invalidated_self_from_collection = invalidated_self;
500
501 invalidated_self |= self.process_descendant_invalidations(
502 &self_invalidations,
503 &mut descendant_invalidations,
504 &mut sibling_invalidations,
505 DescendantInvalidationKind::Dom,
506 );
507
508 if invalidated_self && !invalidated_self_from_collection {
509 self.processor.invalidated_self(self.element);
510 }
511
512 let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
513 let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
514
515 InvalidationResult {
516 invalidated_self,
517 invalidated_descendants,
518 invalidated_siblings,
519 }
520 }
521
522 fn invalidate_siblings(&mut self, sibling_invalidations: &mut InvalidationVector<'b>) -> bool {
528 if sibling_invalidations.is_empty() {
529 return false;
530 }
531
532 let mut current = self
533 .processor
534 .sibling_traversal_map()
535 .next_sibling_for(&self.element);
536 let mut any_invalidated = false;
537
538 while let Some(sibling) = current {
539 let mut sibling_invalidator =
540 TreeStyleInvalidator::new(sibling, self.stack_limit_checker, self.processor);
541
542 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
543 let invalidated_sibling = sibling_invalidator.process_sibling_invalidations(
544 &mut invalidations_for_descendants,
545 sibling_invalidations,
546 );
547
548 if invalidated_sibling {
549 sibling_invalidator
550 .processor
551 .invalidated_sibling(sibling, self.element);
552 }
553
554 any_invalidated |= invalidated_sibling;
555
556 any_invalidated |=
557 sibling_invalidator.invalidate_descendants(&invalidations_for_descendants);
558
559 if sibling_invalidations.is_empty() {
560 break;
561 }
562
563 current = self
564 .processor
565 .sibling_traversal_map()
566 .next_sibling_for(&sibling);
567 }
568
569 any_invalidated
570 }
571
572 fn invalidate_pseudo_element_or_nac(
573 &mut self,
574 child: E,
575 invalidations: &[Invalidation<'b>],
576 ) -> bool {
577 let mut sibling_invalidations = InvalidationVector::new();
578
579 let result = self.invalidate_child(
580 child,
581 invalidations,
582 &mut sibling_invalidations,
583 DescendantInvalidationKind::Dom,
584 );
585
586 result
594 }
595
596 fn invalidate_child(
599 &mut self,
600 child: E,
601 invalidations: &[Invalidation<'b>],
602 sibling_invalidations: &mut InvalidationVector<'b>,
603 descendant_invalidation_kind: DescendantInvalidationKind,
604 ) -> bool {
605 let mut invalidations_for_descendants = DescendantInvalidationLists::default();
606
607 let mut invalidated_child = false;
608 let invalidated_descendants = {
609 let mut child_invalidator =
610 TreeStyleInvalidator::new(child, self.stack_limit_checker, self.processor);
611
612 invalidated_child |= child_invalidator.process_sibling_invalidations(
613 &mut invalidations_for_descendants,
614 sibling_invalidations,
615 );
616
617 invalidated_child |= child_invalidator.process_descendant_invalidations(
618 invalidations,
619 &mut invalidations_for_descendants,
620 sibling_invalidations,
621 descendant_invalidation_kind,
622 );
623
624 if invalidated_child {
625 child_invalidator.processor.invalidated_self(child);
626 }
627
628 child_invalidator.invalidate_descendants(&invalidations_for_descendants)
629 };
630
631 if invalidated_child || invalidated_descendants {
637 self.processor.invalidated_descendants(self.element, child);
638 }
639
640 invalidated_child || invalidated_descendants
641 }
642
643 fn invalidate_nac(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
644 let mut any_nac_root = false;
645
646 let element = self.element;
647 element.each_anonymous_content_child(|nac| {
648 any_nac_root |= self.invalidate_pseudo_element_or_nac(nac, invalidations);
649 });
650
651 any_nac_root
652 }
653
654 fn invalidate_dom_descendants_of(
657 &mut self,
658 parent: E::ConcreteNode,
659 invalidations: &[Invalidation<'b>],
660 ) -> bool {
661 let mut any_descendant = false;
662
663 let mut sibling_invalidations = InvalidationVector::new();
664 for child in parent.dom_children() {
665 let child = match child.as_element() {
666 Some(e) => e,
667 None => continue,
668 };
669
670 any_descendant |= self.invalidate_child(
671 child,
672 invalidations,
673 &mut sibling_invalidations,
674 DescendantInvalidationKind::Dom,
675 );
676 }
677
678 any_descendant
679 }
680
681 fn invalidate_parts_in_shadow_tree(
682 &mut self,
683 shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
684 invalidations: &[Invalidation<'b>],
685 ) -> bool {
686 debug_assert!(!invalidations.is_empty());
687
688 let mut any = false;
689 let mut sibling_invalidations = InvalidationVector::new();
690
691 for node in shadow.as_node().dom_descendants() {
692 let element = match node.as_element() {
693 Some(e) => e,
694 None => continue,
695 };
696
697 if element.has_part_attr() {
698 any |= self.invalidate_child(
699 element,
700 invalidations,
701 &mut sibling_invalidations,
702 DescendantInvalidationKind::Part,
703 );
704 debug_assert!(
705 sibling_invalidations.is_empty(),
706 "::part() shouldn't have sibling combinators to the right, \
707 this makes no sense! {:?}",
708 sibling_invalidations
709 );
710 }
711
712 if let Some(shadow) = element.shadow_root() {
713 if element.exports_any_part() {
714 any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
715 }
716 }
717 }
718
719 any
720 }
721
722 fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
723 if invalidations.is_empty() {
724 return false;
725 }
726
727 let shadow = match self.element.shadow_root() {
728 Some(s) => s,
729 None => return false,
730 };
731
732 self.invalidate_parts_in_shadow_tree(shadow, invalidations)
733 }
734
735 fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
736 if invalidations.is_empty() {
737 return false;
738 }
739
740 let slot = self.element;
741 self.invalidate_slotted_elements_in_slot(slot, invalidations)
742 }
743
744 fn invalidate_slotted_elements_in_slot(
745 &mut self,
746 slot: E,
747 invalidations: &[Invalidation<'b>],
748 ) -> bool {
749 let mut any = false;
750
751 let mut sibling_invalidations = InvalidationVector::new();
752 for node in slot.slotted_nodes() {
753 let element = match node.as_element() {
754 Some(e) => e,
755 None => continue,
756 };
757
758 if element.is_html_slot_element() {
759 any |= self.invalidate_slotted_elements_in_slot(element, invalidations);
760 } else {
761 any |= self.invalidate_child(
762 element,
763 invalidations,
764 &mut sibling_invalidations,
765 DescendantInvalidationKind::Slotted,
766 );
767 }
768
769 debug_assert!(
770 sibling_invalidations.is_empty(),
771 "::slotted() shouldn't have sibling combinators to the right, \
772 this makes no sense! {:?}",
773 sibling_invalidations
774 );
775 }
776
777 any
778 }
779
780 fn invalidate_non_slotted_descendants(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
781 if invalidations.is_empty() {
782 return false;
783 }
784
785 if self.processor.light_tree_only() {
786 let node = self.element.as_node();
787 return self.invalidate_dom_descendants_of(node, invalidations);
788 }
789
790 let mut any_descendant = false;
791
792 if let Some(root) = self.element.shadow_root() {
801 any_descendant |= self.invalidate_dom_descendants_of(root.as_node(), invalidations);
802 }
803
804 any_descendant |= self.invalidate_dom_descendants_of(self.element.as_node(), invalidations);
805
806 any_descendant |= self.invalidate_nac(invalidations);
807
808 any_descendant
809 }
810
811 fn invalidate_descendants(&mut self, invalidations: &DescendantInvalidationLists<'b>) -> bool {
814 if invalidations.is_empty() {
815 return false;
816 }
817
818 debug!(
819 "StyleTreeInvalidator::invalidate_descendants({:?})",
820 self.element
821 );
822 debug!(" > {:?}", invalidations);
823
824 let should_process = self.processor.should_process_descendants(self.element);
825
826 if !should_process {
827 return false;
828 }
829
830 if let Some(checker) = self.stack_limit_checker {
831 if checker.limit_exceeded() {
832 self.processor.recursion_limit_exceeded(self.element);
833 return true;
834 }
835 }
836
837 let mut any_descendant = false;
838
839 any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
840 any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants);
841 any_descendant |= self.invalidate_parts(&invalidations.parts);
842
843 any_descendant
844 }
845
846 fn process_sibling_invalidations(
858 &mut self,
859 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
860 sibling_invalidations: &mut InvalidationVector<'b>,
861 ) -> bool {
862 let mut i = 0;
863 let mut new_sibling_invalidations = InvalidationVector::new();
864 let mut invalidated_self = false;
865
866 while i < sibling_invalidations.len() {
867 let result = self.process_invalidation(
868 &sibling_invalidations[i],
869 descendant_invalidations,
870 &mut new_sibling_invalidations,
871 InvalidationKind::Sibling,
872 );
873
874 invalidated_self |= result.invalidated_self;
875 sibling_invalidations[i].matched_by_any_previous |= result.matched;
876 if sibling_invalidations[i].effective_for_next() {
877 i += 1;
878 } else {
879 sibling_invalidations.remove(i);
880 }
881 }
882
883 sibling_invalidations.extend(new_sibling_invalidations.drain(..));
884 invalidated_self
885 }
886
887 fn process_descendant_invalidations(
893 &mut self,
894 invalidations: &[Invalidation<'b>],
895 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
896 sibling_invalidations: &mut InvalidationVector<'b>,
897 descendant_invalidation_kind: DescendantInvalidationKind,
898 ) -> bool {
899 let mut invalidated = false;
900
901 for invalidation in invalidations {
902 let result = self.process_invalidation(
903 invalidation,
904 descendant_invalidations,
905 sibling_invalidations,
906 InvalidationKind::Descendant(descendant_invalidation_kind),
907 );
908
909 invalidated |= result.invalidated_self;
910 if invalidation.effective_for_next() {
911 let mut invalidation = invalidation.clone();
912 invalidation.matched_by_any_previous |= result.matched;
913 debug_assert_eq!(
914 descendant_invalidation_kind,
915 DescendantInvalidationKind::Dom,
916 "Slotted or part invalidations don't propagate."
917 );
918 descendant_invalidations.dom_descendants.push(invalidation);
919 }
920 }
921
922 invalidated
923 }
924
925 #[inline(always)]
926 fn handle_fully_matched(
927 &mut self,
928 invalidation: &Invalidation<'b>,
929 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
930 sibling_invalidations: &mut InvalidationVector<'b>,
931 ) -> (ProcessInvalidationResult, SmallVec<[Invalidation<'b>; 1]>) {
932 debug!(" > Invalidation matched completely");
933 let mut to_process: SmallVec<[&Dependency; 1]> = SmallVec::from([invalidation.dependency]);
936 let mut next_invalidations: SmallVec<[Invalidation; 1]> = SmallVec::new();
937 let mut result = ProcessInvalidationResult {
938 invalidated_self: false,
939 matched: false,
940 };
941
942 while !to_process.is_empty() {
943 let mut next_dependencies: SmallVec<[&Dependency; 1]> = SmallVec::new();
944
945 while let Some(dependency) = to_process.pop() {
946 if dependency.invalidation_kind()
947 == DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ScopeEnd)
948 {
949 let invalidations =
950 note_scope_dependency_force_at_subject(dependency, invalidation.host);
951 for (invalidation, override_type) in invalidations {
952 match override_type {
953 InvalidationAddOverride::Descendant => {
954 descendant_invalidations.dom_descendants.push(invalidation)
955 },
956 InvalidationAddOverride::Sibling => {
957 sibling_invalidations.push(invalidation)
958 },
959 }
960 }
961 continue;
962 }
963 match dependency.next {
964 None => {
965 result.invalidated_self = true;
966 result.matched = true;
967 },
968 Some(ref deps) => {
969 for n in deps.as_ref().slice() {
970 let invalidation_kind = n.invalidation_kind();
971 match invalidation_kind {
972 DependencyInvalidationKind::FullSelector => unreachable!(),
973 DependencyInvalidationKind::Normal(_) => next_dependencies.push(n),
974 DependencyInvalidationKind::Scope(_) => {
976 next_dependencies.push(n);
977 },
978 DependencyInvalidationKind::Relative(kind) => {
979 self.processor.found_relative_selector_invalidation(
980 self.element,
981 kind,
982 n,
983 );
984 result.matched = true;
985 },
986 }
987 }
988 },
989 };
990 }
991
992 for cur_dependency in next_dependencies.as_ref() {
993 let scope = matches!(
994 invalidation.dependency.invalidation_kind(),
995 DependencyInvalidationKind::Scope(_)
996 )
997 .then(|| self.element.opaque());
998 debug!(" > Checking outer dependency {:?}", cur_dependency);
999
1000 if !self
1004 .processor
1005 .check_outer_dependency(cur_dependency, self.element, scope)
1006 {
1007 continue;
1009 }
1010
1011 let invalidation_kind = cur_dependency.invalidation_kind();
1012 if matches!(
1013 invalidation_kind,
1014 DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element)
1015 ) || (matches!(invalidation_kind, DependencyInvalidationKind::Scope(_))
1016 && cur_dependency.selector_offset == 0)
1017 {
1018 to_process.push(cur_dependency);
1020 continue;
1021 }
1022
1023 debug!(" > Generating invalidation");
1024 next_invalidations.push(Invalidation::new(
1025 cur_dependency,
1026 invalidation.host,
1027 scope,
1028 ));
1029 }
1030 }
1031 return (result, next_invalidations);
1032 }
1033
1034 fn process_invalidation(
1041 &mut self,
1042 invalidation: &Invalidation<'b>,
1043 descendant_invalidations: &mut DescendantInvalidationLists<'b>,
1044 sibling_invalidations: &mut InvalidationVector<'b>,
1045 invalidation_kind: InvalidationKind,
1046 ) -> ProcessInvalidationResult {
1047 debug!(
1048 "TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
1049 self.element, invalidation, invalidation_kind
1050 );
1051
1052 let matching_result = {
1053 let context = self.processor.matching_context();
1054 context.current_host = invalidation.host;
1055
1056 context.nest_for_scope_condition(invalidation.scope, |ctx| {
1057 matches_compound_selector_from(
1058 &invalidation.dependency.selector,
1059 invalidation.offset,
1060 ctx,
1061 &self.element,
1062 )
1063 })
1064 };
1065
1066 let (result, next_invalidations) = match matching_result {
1067 CompoundSelectorMatchingResult::NotMatched => {
1068 return ProcessInvalidationResult {
1069 invalidated_self: false,
1070 matched: false,
1071 }
1072 },
1073 CompoundSelectorMatchingResult::FullyMatched => self.handle_fully_matched(
1074 invalidation,
1075 descendant_invalidations,
1076 sibling_invalidations,
1077 ),
1078 CompoundSelectorMatchingResult::Matched {
1079 next_combinator_offset,
1080 } => (
1081 ProcessInvalidationResult {
1082 invalidated_self: false,
1083 matched: true,
1084 },
1085 smallvec![Invalidation {
1086 dependency: invalidation.dependency,
1087 host: invalidation.host,
1088 scope: invalidation.scope,
1089 offset: next_combinator_offset + 1,
1090 matched_by_any_previous: false,
1091 }],
1092 ),
1093 };
1094
1095 let mut invalidated_self = result.invalidated_self;
1096 for next_invalidation in next_invalidations {
1097 debug_assert_ne!(
1098 next_invalidation.offset, 0,
1099 "Rightmost selectors shouldn't generate more invalidations",
1100 );
1101
1102 let next_combinator = next_invalidation
1103 .dependency
1104 .selector
1105 .combinator_at_parse_order(next_invalidation.offset - 1);
1106
1107 if matches!(next_combinator, Combinator::PseudoElement)
1108 && self.processor.invalidates_on_pseudo_element()
1109 {
1110 invalidated_self = true;
1133 }
1134
1135 debug!(
1136 " > Invalidation matched, next: {:?}, ({:?})",
1137 next_invalidation, next_combinator
1138 );
1139
1140 let next_invalidation_kind = next_invalidation.kind();
1141
1142 let can_skip_pushing = next_invalidation_kind == invalidation_kind
1202 && invalidation.matched_by_any_previous
1203 && next_invalidation.effective_for_next();
1204
1205 if can_skip_pushing {
1206 debug!(
1207 " > Can avoid push, since the invalidation had \
1208 already been matched before"
1209 );
1210 } else {
1211 match next_invalidation_kind {
1212 InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
1213 descendant_invalidations
1214 .dom_descendants
1215 .push(next_invalidation);
1216 },
1217 InvalidationKind::Descendant(DescendantInvalidationKind::Part) => {
1218 descendant_invalidations.parts.push(next_invalidation);
1219 },
1220 InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
1221 descendant_invalidations
1222 .slotted_descendants
1223 .push(next_invalidation);
1224 },
1225 InvalidationKind::Sibling => {
1226 sibling_invalidations.push(next_invalidation);
1227 },
1228 }
1229 }
1230 }
1231
1232 ProcessInvalidationResult {
1233 invalidated_self,
1234 matched: true,
1235 }
1236 }
1237}
1238
1239pub fn note_scope_dependency_force_at_subject<'selectors>(
1250 dependency: &'selectors Dependency,
1251 current_host: Option<OpaqueElement>,
1252) -> Vec<(Invalidation<'selectors>, InvalidationAddOverride)> {
1253 let mut invalidations_and_override_types: Vec<(Invalidation, InvalidationAddOverride)> =
1254 Vec::new();
1255 if let Some(next) = dependency.next.as_ref() {
1256 for dep in next.slice() {
1257 if dep.selector_offset == 0 {
1258 continue;
1259 }
1260
1261 let invalidation = Invalidation::new_subject_invalidation(dep, current_host, None);
1262
1263 let combinator = dep
1264 .selector
1265 .combinator_at_match_order(dep.selector_offset - 1);
1266
1267 let invalidation_override = match combinator.is_sibling() {
1268 true => InvalidationAddOverride::Sibling,
1269 false => InvalidationAddOverride::Descendant,
1270 };
1271
1272 invalidations_and_override_types.push((invalidation, invalidation_override));
1273 invalidations_and_override_types
1274 .extend(note_scope_dependency_force_at_subject(dep, current_host));
1275 }
1276 }
1277 invalidations_and_override_types
1278}