1use crate::AllocErr;
8use crate::context::QuirksMode;
9use crate::derives::*;
10use crate::selector_map::{
11 MaybeCaseInsensitiveHashMap, PrecomputedHashMap, SelectorMap, SelectorMapEntry,
12};
13use crate::selector_parser::{NonTSPseudoClass, SelectorImpl};
14use crate::values::AtomIdent;
15use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded};
16use dom::{DocumentState, ElementState};
17use selectors::attr::NamespaceConstraint;
18use selectors::parser::{
19 Combinator, Component, RelativeSelector, RelativeSelectorCombinatorCount,
20 RelativeSelectorMatchHint,
21};
22use selectors::parser::{Selector, SelectorIter};
23use selectors::visitor::{SelectorListKind, SelectorVisitor};
24use servo_arc::ThinArc;
25use smallvec::SmallVec;
26
27#[derive(Clone, Debug, MallocSizeOf)]
46pub struct Dependency {
47 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
49 pub selector: Selector<SelectorImpl>,
50
51 pub selector_offset: usize,
53
54 #[ignore_malloc_size_of = "Arc"]
73 pub next: Option<ThinArc<(), Dependency>>,
74
75 kind: DependencyInvalidationKind,
77}
78
79impl SelectorMapEntry for Dependency {
80 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
81 self.selector.iter_from(self.selector_offset)
82 }
83}
84
85#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
87pub enum NormalDependencyInvalidationKind {
88 Element,
90 ElementAndDescendants,
95 Descendants,
97 Siblings,
100 SlottedElements,
102 Parts,
104}
105
106#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
110pub enum RelativeDependencyInvalidationKind {
111 Ancestors,
113 Parent,
115 PrevSibling,
117 AncestorPrevSibling,
119 EarlierSibling,
121 AncestorEarlierSibling,
123}
124
125#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
127pub enum ScopeDependencyInvalidationKind {
128 ExplicitScope,
130 ImplicitScope,
132 ScopeEnd,
134}
135
136#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
138pub enum DependencyInvalidationKind {
139 FullSelector,
142 Normal(NormalDependencyInvalidationKind),
144 Relative(RelativeDependencyInvalidationKind),
146 Scope(ScopeDependencyInvalidationKind),
148}
149
150#[derive(Clone, Copy, Debug, MallocSizeOf)]
152pub enum GeneratedInvalidation<'a> {
153 Normal,
155 Scope(Option<&'a ThinArc<(), Dependency>>),
157}
158
159#[inline(always)]
161fn get_non_relative_invalidation_kind(
162 selector: &Selector<SelectorImpl>,
163 selector_offset: usize,
164 scope_kind: Option<ScopeDependencyInvalidationKind>,
165) -> DependencyInvalidationKind {
166 if let Some(kind) = scope_kind {
167 return DependencyInvalidationKind::Scope(kind);
168 }
169 if selector_offset == 0 {
170 return DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element);
171 }
172 let combinator = selector.combinator_at_match_order(selector_offset - 1);
173 DependencyInvalidationKind::Normal(match combinator {
174 Combinator::Child | Combinator::Descendant => NormalDependencyInvalidationKind::Descendants,
175 Combinator::LaterSibling | Combinator::NextSibling => {
176 NormalDependencyInvalidationKind::Siblings
177 },
178 Combinator::PseudoElement => NormalDependencyInvalidationKind::ElementAndDescendants,
179 Combinator::SlotAssignment => NormalDependencyInvalidationKind::SlottedElements,
180 Combinator::Part => NormalDependencyInvalidationKind::Parts,
181 })
182}
183
184impl Dependency {
185 pub fn new(
187 selector: Selector<SelectorImpl>,
188 selector_offset: usize,
189 next: Option<ThinArc<(), Dependency>>,
190 kind: DependencyInvalidationKind,
191 ) -> Self {
192 Self {
193 selector,
194 selector_offset,
195 next,
196 kind,
197 }
198 }
199 pub fn for_full_selector_invalidation(selector: Selector<SelectorImpl>) -> Self {
208 Self {
209 selector_offset: selector.len() + 1,
210 selector,
211 next: None,
212 kind: DependencyInvalidationKind::FullSelector,
213 }
214 }
215
216 pub fn normal_invalidation_kind(&self) -> NormalDependencyInvalidationKind {
219 if let DependencyInvalidationKind::Normal(kind) = self.kind {
220 return kind;
221 }
222 unreachable!("Querying normal invalidation kind on non-normal dependency.");
223 }
224
225 #[inline(always)]
228 pub fn relative_invalidation_kind(&self) -> RelativeDependencyInvalidationKind {
229 if let DependencyInvalidationKind::Relative(kind) = self.kind {
230 return kind;
231 }
232 unreachable!("Querying relative invalidation kind on non-relative dependency.");
233 }
234
235 pub fn invalidation_kind(&self) -> DependencyInvalidationKind {
237 self.kind
238 }
239
240 pub fn right_combinator_is_next_sibling(&self) -> bool {
245 if self.selector_offset == 0 {
246 return false;
247 }
248 matches!(
249 self.selector
250 .combinator_at_match_order(self.selector_offset - 1),
251 Combinator::NextSibling
252 )
253 }
254
255 pub fn dependency_is_relative_with_single_next_sibling(&self) -> bool {
260 match self.invalidation_kind() {
261 DependencyInvalidationKind::Relative(kind) => {
262 kind == RelativeDependencyInvalidationKind::PrevSibling
263 },
264 _ => false,
265 }
266 }
267}
268
269#[derive(Clone, Debug, MallocSizeOf)]
272pub struct StateDependency {
273 pub dep: Dependency,
275 pub state: ElementState,
277}
278
279impl SelectorMapEntry for StateDependency {
280 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
281 self.dep.selector()
282 }
283}
284
285#[derive(Clone, Debug, MallocSizeOf)]
287pub struct DocumentStateDependency {
288 #[cfg_attr(
291 feature = "gecko",
292 ignore_malloc_size_of = "CssRules have primary refs, we measure there"
293 )]
294 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
295 pub dependency: Dependency,
296 pub state: DocumentState,
298}
299
300pub type IdOrClassDependencyMap = MaybeCaseInsensitiveHashMap<Atom, SmallVec<[Dependency; 1]>>;
302pub type StateDependencyMap = SelectorMap<StateDependency>;
304pub type LocalNameDependencyMap = PrecomputedHashMap<LocalName, SmallVec<[Dependency; 1]>>;
306pub type CustomStateDependencyMap = PrecomputedHashMap<AtomIdent, SmallVec<[Dependency; 1]>>;
308
309#[derive(Clone, Debug, MallocSizeOf)]
318pub struct InvalidationMap {
319 pub class_to_selector: IdOrClassDependencyMap,
322 pub id_to_selector: IdOrClassDependencyMap,
325 pub state_affecting_selectors: StateDependencyMap,
327 pub document_state_selectors: Vec<DocumentStateDependency>,
329 pub other_attribute_affecting_selectors: LocalNameDependencyMap,
331 pub custom_state_affecting_selectors: CustomStateDependencyMap,
333}
334
335#[derive(Clone, Copy, Debug, MallocSizeOf)]
341pub struct TSStateForInvalidation(u8);
342
343bitflags! {
344 impl TSStateForInvalidation : u8 {
345 const EMPTY = 1 << 0;
348 const NTH = 1 << 1;
350 const NTH_EDGE_FIRST = 1 << 2;
353 const NTH_EDGE_LAST = 1 << 3;
356 }
357}
358
359impl TSStateForInvalidation {
360 pub fn may_be_optimized(&self) -> bool {
363 (Self::EMPTY | Self::NTH_EDGE_FIRST | Self::NTH_EDGE_LAST).contains(*self)
364 }
365}
366
367#[derive(Clone, Debug, MallocSizeOf)]
369pub struct TSStateDependency {
370 pub dep: Dependency,
372 pub state: TSStateForInvalidation,
374}
375
376impl SelectorMapEntry for TSStateDependency {
377 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
378 self.dep.selector()
379 }
380}
381
382pub type TSStateDependencyMap = SelectorMap<TSStateDependency>;
384pub type AnyDependencyMap = SmallVec<[Dependency; 1]>;
386
387#[derive(Clone, Debug, MallocSizeOf)]
391pub struct AdditionalRelativeSelectorInvalidationMap {
392 pub ts_state_to_selector: TSStateDependencyMap,
394 pub type_to_selector: LocalNameDependencyMap,
396 pub any_to_selector: AnyDependencyMap,
398 pub used: bool,
400 pub needs_ancestors_traversal: bool,
402}
403
404impl Default for AdditionalRelativeSelectorInvalidationMap {
405 fn default() -> Self {
406 Self::new()
407 }
408}
409
410impl AdditionalRelativeSelectorInvalidationMap {
411 pub fn new() -> Self {
413 Self {
414 ts_state_to_selector: TSStateDependencyMap::default(),
415 type_to_selector: LocalNameDependencyMap::default(),
416 any_to_selector: SmallVec::default(),
417 used: false,
418 needs_ancestors_traversal: false,
419 }
420 }
421
422 pub fn clear(&mut self) {
424 self.ts_state_to_selector.clear();
425 self.type_to_selector.clear();
426 self.any_to_selector.clear();
427 }
428
429 pub fn shrink_if_needed(&mut self) {
431 self.ts_state_to_selector.shrink_if_needed();
432 self.type_to_selector.shrink_if_needed();
433 }
434}
435
436impl Default for InvalidationMap {
437 fn default() -> Self {
438 Self::new()
439 }
440}
441
442impl InvalidationMap {
443 pub fn new() -> Self {
445 Self {
446 class_to_selector: IdOrClassDependencyMap::new(),
447 id_to_selector: IdOrClassDependencyMap::new(),
448 state_affecting_selectors: StateDependencyMap::new(),
449 document_state_selectors: Vec::new(),
450 other_attribute_affecting_selectors: LocalNameDependencyMap::default(),
451 custom_state_affecting_selectors: CustomStateDependencyMap::default(),
452 }
453 }
454
455 pub fn len(&self) -> usize {
457 self.state_affecting_selectors.len()
458 + self.document_state_selectors.len()
459 + self
460 .other_attribute_affecting_selectors
461 .iter()
462 .fold(0, |accum, (_, v)| accum + v.len())
463 + self
464 .id_to_selector
465 .iter()
466 .fold(0, |accum, (_, v)| accum + v.len())
467 + self
468 .class_to_selector
469 .iter()
470 .fold(0, |accum, (_, v)| accum + v.len())
471 + self
472 .custom_state_affecting_selectors
473 .iter()
474 .fold(0, |accum, (_, v)| accum + v.len())
475 }
476
477 pub fn clear(&mut self) {
479 self.class_to_selector.clear();
480 self.id_to_selector.clear();
481 self.state_affecting_selectors.clear();
482 self.document_state_selectors.clear();
483 self.other_attribute_affecting_selectors.clear();
484 self.custom_state_affecting_selectors.clear();
485 }
486
487 pub fn shrink_if_needed(&mut self) {
489 self.class_to_selector.shrink_if_needed();
490 self.id_to_selector.shrink_if_needed();
491 self.state_affecting_selectors.shrink_if_needed();
492 self.other_attribute_affecting_selectors.shrink_if_needed();
493 self.custom_state_affecting_selectors.shrink_if_needed();
494 }
495}
496
497pub fn note_selector_for_invalidation(
499 selector: &Selector<SelectorImpl>,
500 quirks_mode: QuirksMode,
501 map: &mut InvalidationMap,
502 relative_selector_invalidation_map: &mut InvalidationMap,
503 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
504 inner_scope_dependencies: Option<&ThinArc<(), Dependency>>,
505 scope_kind: Option<ScopeDependencyInvalidationKind>,
506) -> Result<Option<Vec<Dependency>>, AllocErr> {
507 let next_dependency = Dependency::for_full_selector_invalidation(selector.clone());
508 let mut document_state = DocumentState::empty();
509 let mut scope_dependencies = ScopeSelectorCollectorState {
510 inner_dependencies: &inner_scope_dependencies.cloned(),
511 this_dependencies: None,
512 scope_kind,
513 };
514
515 {
516 let mut next_stack = NextSelectors::new();
517 let mut alloc_error = None;
518 let mut collector = SelectorDependencyCollector {
519 map,
520 relative_selector_invalidation_map,
521 additional_relative_selector_invalidation_map,
522 document_state: &mut document_state,
523 selector,
524 next_selectors: &mut next_stack,
525 quirks_mode,
526 compound_state: PerCompoundState::new(0),
527 relative_inner_collector: None,
528 scope_dependencies: &mut scope_dependencies,
529 alloc_error: &mut alloc_error,
530 };
531
532 let visit_result = collector.visit_whole_selector();
533
534 debug_assert_eq!(!visit_result, alloc_error.is_some());
535 if let Some(alloc_error) = alloc_error {
536 return Err(alloc_error);
537 }
538 }
539
540 if !document_state.is_empty() {
541 let dep = DocumentStateDependency {
542 state: document_state,
543 dependency: next_dependency,
544 };
545 map.document_state_selectors.try_reserve(1)?;
546 map.document_state_selectors.push(dep);
547 }
548 Ok(scope_dependencies.this_dependencies)
549}
550
551struct PerCompoundState {
552 offset: usize,
554
555 element_state: ElementState,
557}
558
559impl PerCompoundState {
560 fn new(offset: usize) -> Self {
561 Self {
562 offset,
563 element_state: ElementState::empty(),
564 }
565 }
566}
567
568struct NextDependencyEntry {
569 selector: Selector<SelectorImpl>,
570 offset: usize,
571 cached_dependency: Option<ThinArc<(), Dependency>>,
572}
573
574struct RelativeSelectorInnerCollectorState<'a> {
575 next_dependency: &'a ThinArc<(), Dependency>,
576 relative_compound_state: RelativeSelectorCompoundStateAttributes,
577}
578struct ScopeSelectorCollectorState<'a> {
579 inner_dependencies: &'a Option<ThinArc<(), Dependency>>,
581 this_dependencies: Option<Vec<Dependency>>,
583 scope_kind: Option<ScopeDependencyInvalidationKind>,
585}
586
587trait Collector {
588 fn dependency(&mut self) -> Dependency;
589 fn id_map(&mut self) -> &mut IdOrClassDependencyMap;
590 fn class_map(&mut self) -> &mut IdOrClassDependencyMap;
591 fn state_map(&mut self) -> &mut StateDependencyMap;
592 fn attribute_map(&mut self) -> &mut LocalNameDependencyMap;
593 fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap;
594 fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>>;
595 fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>>;
596 fn update_states(&mut self, element_state: ElementState, document_state: DocumentState);
597
598 fn type_map(&mut self) -> &mut LocalNameDependencyMap {
605 unreachable!();
606 }
607
608 fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
612 unreachable!();
613 }
614
615 fn any_vec(&mut self) -> &mut AnyDependencyMap {
617 unreachable!();
618 }
619}
620
621fn on_attribute<C: Collector>(
622 local_name: &LocalName,
623 local_name_lower: &LocalName,
624 collector: &mut C,
625) -> Result<(), AllocErr> {
626 add_attr_dependency(local_name, collector)?;
627 if local_name != local_name_lower {
628 add_attr_dependency(local_name_lower, collector)?;
629 }
630 Ok(())
631}
632
633fn on_id_or_class<C: Collector>(
634 s: &Component<SelectorImpl>,
635 quirks_mode: QuirksMode,
636 collector: &mut C,
637) -> Result<(), AllocErr> {
638 let dependency = collector.dependency();
639
640 let (atom, map) = match *s {
641 Component::ID(ref atom) => (atom, collector.id_map()),
642 Component::Class(ref atom) => (atom, collector.class_map()),
643 _ => unreachable!(),
644 };
645 let vec = map.try_get_or_insert_with(&atom.0, quirks_mode, SmallVec::new)?;
646 vec.try_reserve(1)?;
647 vec.push(dependency);
648 Ok(())
649}
650
651fn on_scope<C: Collector>(collector: &mut C) -> Result<(), AllocErr> {
652 let new_dependency = collector.dependency();
653 let this_scope_dependencies = collector.this_scope_dependencies();
654
655 this_scope_dependencies
656 .get_or_insert(Vec::new())
657 .push(new_dependency);
658
659 Ok(())
660}
661
662fn add_attr_dependency<C: Collector>(name: &LocalName, collector: &mut C) -> Result<(), AllocErr> {
663 let dependency = collector.dependency();
664 let map = collector.attribute_map();
665 add_local_name(name, dependency, map)
666}
667
668fn add_custom_state_dependency<C: Collector>(
669 name: &AtomIdent,
670 collector: &mut C,
671) -> Result<(), AllocErr> {
672 let dependency = collector.dependency();
673 let map = collector.custom_state_map();
674 map.try_reserve(1)?;
675 let vec = map.entry_ref(name).or_default();
676 vec.try_reserve(1)?;
677 vec.push(dependency);
678 Ok(())
679}
680
681fn add_local_name(
682 name: &LocalName,
683 dependency: Dependency,
684 map: &mut LocalNameDependencyMap,
685) -> Result<(), AllocErr> {
686 map.try_reserve(1)?;
687 let vec = map.entry_ref(name).or_default();
688 vec.try_reserve(1)?;
689 vec.push(dependency);
690 Ok(())
691}
692
693fn on_pseudo_class<C: Collector>(pc: &NonTSPseudoClass, collector: &mut C) -> Result<(), AllocErr> {
694 collector.update_states(pc.state_flag(), pc.document_state_flag());
695
696 let attr_name = match *pc {
697 #[cfg(feature = "gecko")]
698 NonTSPseudoClass::MozTableBorderNonzero => local_name!("border"),
699 #[cfg(feature = "gecko")]
700 NonTSPseudoClass::MozSelectListBox => {
701 add_attr_dependency(&local_name!("multiple"), collector)?;
703 return add_attr_dependency(&local_name!("size"), collector);
704 },
705 NonTSPseudoClass::Lang(..) => local_name!("lang"),
706 NonTSPseudoClass::CustomState(ref name) => {
707 return add_custom_state_dependency(&name.0, collector);
708 },
709 _ => return Ok(()),
710 };
711
712 add_attr_dependency(&attr_name, collector)
713}
714
715fn add_pseudo_class_dependency<C: Collector>(
716 element_state: ElementState,
717 quirks_mode: QuirksMode,
718 collector: &mut C,
719) -> Result<(), AllocErr> {
720 if element_state.is_empty() {
721 return Ok(());
722 }
723 let dependency = collector.dependency();
724 collector.state_map().insert(
725 StateDependency {
726 dep: dependency,
727 state: element_state,
728 },
729 quirks_mode,
730 )
731}
732
733fn visit_all_in_iter_compound<T: SelectorVisitor<Impl = SelectorImpl>>(
740 visitor: &mut T,
741 iter: &mut SelectorIter<'_, SelectorImpl>,
742) -> (bool, usize) {
743 let mut index = 0;
744 for ss in iter {
745 if !ss.visit(visitor) {
746 return (false, index);
747 }
748 index += 1;
749 }
750 (true, index)
751}
752
753type NextSelectors = SmallVec<[NextDependencyEntry; 5]>;
754
755struct SelectorDependencyCollector<'a, 'b, 'c> {
757 map: &'a mut InvalidationMap,
758 relative_selector_invalidation_map: &'a mut InvalidationMap,
759 additional_relative_selector_invalidation_map:
760 &'a mut AdditionalRelativeSelectorInvalidationMap,
761
762 document_state: &'a mut DocumentState,
767
768 selector: &'a Selector<SelectorImpl>,
770
771 next_selectors: &'a mut NextSelectors,
777
778 quirks_mode: QuirksMode,
780
781 compound_state: PerCompoundState,
783
784 relative_inner_collector: Option<RelativeSelectorInnerCollectorState<'b>>,
787
788 scope_dependencies: &'a mut ScopeSelectorCollectorState<'c>,
789
790 alloc_error: &'a mut Option<AllocErr>,
792}
793
794fn next_dependency(
795 next_selector: &mut NextSelectors,
796 next_outer_dependency: Option<&ThinArc<(), Dependency>>,
797 next_scope_dependencies: Option<&ThinArc<(), Dependency>>,
798 scope_kind: Option<ScopeDependencyInvalidationKind>,
799) -> Option<ThinArc<(), Dependency>> {
800 if next_selector.is_empty() {
801 return match next_outer_dependency {
802 Some(..) => next_outer_dependency.cloned(),
803 None => next_scope_dependencies.cloned(),
804 };
805 }
806
807 fn dependencies_from(
808 entries: &mut [NextDependencyEntry],
809 next_outer_dependency: &Option<&ThinArc<(), Dependency>>,
810 next_scope_dependencies: &Option<&ThinArc<(), Dependency>>,
811 scope_kind: Option<ScopeDependencyInvalidationKind>,
812 ) -> Option<ThinArc<(), Dependency>> {
813 if entries.is_empty() {
814 return next_scope_dependencies.cloned();
815 }
816
817 let last_index = entries.len() - 1;
818 let (previous, last) = entries.split_at_mut(last_index);
819 let last = &mut last[0];
820 let selector = &last.selector;
821 let selector_offset = last.offset;
822
823 let dependency = Dependency {
824 selector: selector.clone(),
825 selector_offset,
826 next: dependencies_from(
827 previous,
828 next_outer_dependency,
829 next_scope_dependencies,
830 scope_kind,
831 ),
832 kind: get_non_relative_invalidation_kind(
833 selector,
834 selector_offset,
835 next_scope_dependencies
836 .is_some()
837 .then_some(scope_kind)
838 .flatten(),
839 ),
840 };
841
842 Some(
843 last.cached_dependency
844 .get_or_insert_with(|| ThinArc::from_header_and_iter((), [dependency].into_iter()))
845 .clone(),
846 )
847 }
848
849 dependencies_from(
850 next_selector,
851 &next_outer_dependency,
852 &next_scope_dependencies,
853 scope_kind,
854 )
855}
856
857impl<'a, 'b, 'c> Collector for SelectorDependencyCollector<'a, 'b, 'c> {
858 fn dependency(&mut self) -> Dependency {
859 let optional_dependency = self
860 .relative_inner_collector
861 .as_ref()
862 .map(|collector| collector.next_dependency);
863
864 let offset = self.compound_state.offset;
865
866 let scope_dependencies = self.inner_scope_dependencies();
867
868 let next = next_dependency(
869 self.next_selectors,
870 optional_dependency,
871 scope_dependencies.as_ref(),
872 self.scope_dependencies.scope_kind,
873 );
874
875 Dependency {
876 selector: self.selector.clone(),
877 selector_offset: offset,
878 next,
879 kind: get_non_relative_invalidation_kind(
880 self.selector,
881 offset,
882 scope_dependencies
883 .is_some()
884 .then_some(self.scope_dependencies.scope_kind)
885 .flatten(),
886 ),
887 }
888 }
889
890 fn id_map(&mut self) -> &mut IdOrClassDependencyMap {
891 if self.relative_inner_collector.is_none() {
892 &mut self.map.id_to_selector
893 } else {
894 &mut self.relative_selector_invalidation_map.id_to_selector
895 }
896 }
897
898 fn class_map(&mut self) -> &mut IdOrClassDependencyMap {
899 if self.relative_inner_collector.is_none() {
900 &mut self.map.class_to_selector
901 } else {
902 &mut self.relative_selector_invalidation_map.class_to_selector
903 }
904 }
905
906 fn state_map(&mut self) -> &mut StateDependencyMap {
907 if self.relative_inner_collector.is_none() {
908 &mut self.map.state_affecting_selectors
909 } else {
910 &mut self
911 .relative_selector_invalidation_map
912 .state_affecting_selectors
913 }
914 }
915
916 fn attribute_map(&mut self) -> &mut LocalNameDependencyMap {
917 if self.relative_inner_collector.is_none() {
918 &mut self.map.other_attribute_affecting_selectors
919 } else {
920 &mut self
921 .relative_selector_invalidation_map
922 .other_attribute_affecting_selectors
923 }
924 }
925
926 fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>> {
927 self.scope_dependencies.inner_dependencies.clone()
928 }
929
930 fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>> {
931 &mut self.scope_dependencies.this_dependencies
932 }
933
934 fn update_states(&mut self, element_state: ElementState, document_state: DocumentState) {
935 self.compound_state.element_state |= element_state;
936 *self.document_state |= document_state;
937 }
938
939 fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap {
940 if self.relative_inner_collector.is_none() {
941 &mut self.map.custom_state_affecting_selectors
942 } else {
943 &mut self
944 .relative_selector_invalidation_map
945 .custom_state_affecting_selectors
946 }
947 }
948
949 fn type_map(&mut self) -> &mut LocalNameDependencyMap {
950 debug_assert!(
951 self.relative_inner_collector.is_some(),
952 "Asking for relative selector invalidation outside of relative selector"
953 );
954 &mut self
955 .additional_relative_selector_invalidation_map
956 .type_to_selector
957 }
958
959 fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
960 debug_assert!(
961 self.relative_inner_collector.is_some(),
962 "Asking for relative selector invalidation outside of relative selector"
963 );
964 &mut self
965 .additional_relative_selector_invalidation_map
966 .ts_state_to_selector
967 }
968
969 fn any_vec(&mut self) -> &mut AnyDependencyMap {
970 debug_assert!(
971 self.relative_inner_collector.is_some(),
972 "Asking for relative selector invalidation outside of relative selector"
973 );
974 &mut self
975 .additional_relative_selector_invalidation_map
976 .any_to_selector
977 }
978}
979
980impl<'a, 'b, 'c> SelectorDependencyCollector<'a, 'b, 'c> {
981 fn visit_whole_selector(&mut self) -> bool {
982 let iter = self.selector.iter();
983 self.visit_whole_selector_from(iter, 0)
984 }
985
986 fn visit_whole_selector_from(
987 &mut self,
988 mut iter: SelectorIter<SelectorImpl>,
989 mut index: usize,
990 ) -> bool {
991 loop {
992 self.compound_state = PerCompoundState::new(index);
994 if let Some(state) = self.relative_inner_collector.as_mut() {
995 state.relative_compound_state = RelativeSelectorCompoundStateAttributes::new();
996 }
997
998 let (keep_traversing, index_offset) = visit_all_in_iter_compound(self, &mut iter);
1000
1001 if !keep_traversing {
1002 return false;
1003 }
1004
1005 index += index_offset;
1006
1007 if let Err(err) = add_pseudo_class_dependency(
1008 self.compound_state.element_state,
1009 self.quirks_mode,
1010 self,
1011 ) {
1012 *self.alloc_error = Some(err);
1013 return false;
1014 }
1015
1016 if let Some(state) = self
1017 .relative_inner_collector
1018 .as_ref()
1019 .map(|state| state.relative_compound_state)
1020 {
1021 if let Err(err) =
1022 add_ts_pseudo_class_dependency(state.ts_state, self.quirks_mode, self)
1023 {
1024 *self.alloc_error = Some(err);
1025 return false;
1026 }
1027
1028 if !state.added_entry {
1029 if let Err(err) =
1031 add_non_unique_info(self.selector, self.compound_state.offset, self)
1032 {
1033 *self.alloc_error = Some(err);
1034 return false;
1035 }
1036 }
1037 }
1038
1039 let combinator = iter.next_sequence();
1040 if combinator.is_none() {
1041 return true;
1042 }
1043 index += 1; }
1045 }
1046}
1047
1048impl<'a, 'b, 'c> SelectorVisitor for SelectorDependencyCollector<'a, 'b, 'c> {
1049 type Impl = SelectorImpl;
1050
1051 fn visit_selector_list(
1052 &mut self,
1053 _list_kind: SelectorListKind,
1054 list: &[Selector<SelectorImpl>],
1055 ) -> bool {
1056 let next_relative_dependency = self
1057 .relative_inner_collector
1058 .is_some()
1059 .then(|| ThinArc::from_header_and_iter((), std::iter::once(self.dependency())));
1060 for selector in list {
1061 let mut iter = selector.iter();
1067 let saved_added_entry = self
1068 .relative_inner_collector
1069 .as_ref()
1070 .map(|state| state.relative_compound_state.added_entry);
1071
1072 let (keep_traversing, mut index) = visit_all_in_iter_compound(self, &mut iter);
1073
1074 if !keep_traversing {
1075 return false;
1076 }
1077
1078 if let Some(state) = self.relative_inner_collector.as_mut() {
1079 state.relative_compound_state.added_entry = saved_added_entry.unwrap_or_default();
1080 }
1081 let combinator = iter.next_sequence();
1082 if combinator.is_none() {
1083 continue;
1084 }
1085
1086 index += 1; let offset = self.compound_state.offset;
1089
1090 if self.relative_inner_collector.is_none() {
1091 self.next_selectors.push(NextDependencyEntry {
1092 selector: self.selector.clone(),
1093 offset,
1094 cached_dependency: None,
1095 });
1096 }
1097 debug_assert!(
1098 next_relative_dependency.is_some() == self.relative_inner_collector.is_some(),
1099 "Next relative dependency and relative inner collector must be Some/None at the same time!"
1100 );
1101 let mut nested = SelectorDependencyCollector {
1102 map: &mut *self.map,
1103 relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1104 additional_relative_selector_invalidation_map: &mut *self
1105 .additional_relative_selector_invalidation_map,
1106 document_state: &mut *self.document_state,
1107 selector,
1108 next_selectors: &mut *self.next_selectors,
1109 quirks_mode: self.quirks_mode,
1110 compound_state: PerCompoundState::new(index),
1111 relative_inner_collector: next_relative_dependency.as_ref().map(
1112 |next_dependency| RelativeSelectorInnerCollectorState {
1113 next_dependency,
1114 relative_compound_state: RelativeSelectorCompoundStateAttributes::new(),
1115 },
1116 ),
1117 scope_dependencies: self.scope_dependencies,
1118 alloc_error: &mut *self.alloc_error,
1119 };
1120 if !nested.visit_whole_selector_from(iter, index) {
1121 return false;
1122 }
1123 self.next_selectors.pop();
1124 }
1125 true
1126 }
1127
1128 fn visit_relative_selector_list(
1129 &mut self,
1130 list: &[selectors::parser::RelativeSelector<Self::Impl>],
1131 ) -> bool {
1132 if self.relative_inner_collector.is_some() {
1134 return true;
1135 }
1136
1137 self.additional_relative_selector_invalidation_map.used = true;
1138 for relative_selector in list {
1139 self.next_selectors.push(NextDependencyEntry {
1142 selector: self.selector.clone(),
1143 offset: self.compound_state.offset,
1144 cached_dependency: None,
1145 });
1146 let mut nested = RelativeSelectorDependencyCollector {
1147 map: &mut *self.map,
1148 relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1149 additional_relative_selector_invalidation_map: &mut *self
1150 .additional_relative_selector_invalidation_map,
1151 document_state: &mut *self.document_state,
1152 selector: relative_selector,
1153 combinator_count: RelativeSelectorCombinatorCount::new(relative_selector),
1154 next_selectors: &mut *self.next_selectors,
1155 quirks_mode: self.quirks_mode,
1156 compound_state: PerCompoundState::new(0),
1157 compound_state_attributes: RelativeSelectorCompoundStateAttributes::new(),
1158 scope_dependencies: self.scope_dependencies,
1159 alloc_error: &mut *self.alloc_error,
1160 };
1161 if !nested.visit_whole_selector() {
1162 return false;
1163 }
1164 self.next_selectors.pop();
1165 }
1166 true
1167 }
1168
1169 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
1170 match on_simple_selector(s, self.quirks_mode, self) {
1171 Ok(result) => {
1172 if let ComponentVisitResult::Handled(state) = result
1173 && let Some(inner_collector_state) = self.relative_inner_collector.as_mut()
1174 {
1175 inner_collector_state.relative_compound_state.added_entry = true;
1176 inner_collector_state
1177 .relative_compound_state
1178 .ts_state
1179 .insert(state);
1180 }
1181 true
1182 },
1183 Err(err) => {
1184 *self.alloc_error = Some(err);
1185 false
1186 },
1187 }
1188 }
1189
1190 fn visit_attribute_selector(
1191 &mut self,
1192 _: &NamespaceConstraint<&Namespace>,
1193 local_name: &LocalName,
1194 local_name_lower: &LocalName,
1195 ) -> bool {
1196 if let Some(state) = self.relative_inner_collector.as_mut() {
1197 state.relative_compound_state.added_entry = true;
1198 }
1199 if let Err(err) = on_attribute(local_name, local_name_lower, self) {
1200 *self.alloc_error = Some(err);
1201 return false;
1202 }
1203 true
1204 }
1205}
1206
1207#[derive(Clone, Copy)]
1208struct RelativeSelectorCompoundStateAttributes {
1209 ts_state: TSStateForInvalidation,
1210 added_entry: bool,
1211}
1212
1213impl RelativeSelectorCompoundStateAttributes {
1214 fn new() -> Self {
1215 Self {
1216 ts_state: TSStateForInvalidation::empty(),
1217 added_entry: false,
1218 }
1219 }
1220}
1221
1222struct RelativeSelectorDependencyCollector<'a, 'b> {
1224 map: &'a mut InvalidationMap,
1225 relative_selector_invalidation_map: &'a mut InvalidationMap,
1226 additional_relative_selector_invalidation_map:
1227 &'a mut AdditionalRelativeSelectorInvalidationMap,
1228
1229 document_state: &'a mut DocumentState,
1234
1235 selector: &'a RelativeSelector<SelectorImpl>,
1237 combinator_count: RelativeSelectorCombinatorCount,
1239
1240 next_selectors: &'a mut NextSelectors,
1246
1247 quirks_mode: QuirksMode,
1249
1250 compound_state: PerCompoundState,
1252
1253 compound_state_attributes: RelativeSelectorCompoundStateAttributes,
1255
1256 scope_dependencies: &'a mut ScopeSelectorCollectorState<'b>,
1257
1258 alloc_error: &'a mut Option<AllocErr>,
1260}
1261
1262fn add_non_unique_info<C: Collector>(
1263 selector: &Selector<SelectorImpl>,
1264 offset: usize,
1265 collector: &mut C,
1266) -> Result<(), AllocErr> {
1267 for ss in selector.iter_from(offset) {
1269 if let Component::LocalName(name) = ss {
1270 let dependency = collector.dependency();
1271 add_local_name(&name.name, dependency, collector.type_map())?;
1272 if name.name != name.lower_name {
1273 let dependency = collector.dependency();
1274 add_local_name(&name.lower_name, dependency, collector.type_map())?;
1275 }
1276 return Ok(());
1277 };
1278 }
1279 collector.any_vec().try_reserve(1)?;
1281 let dependency = collector.dependency();
1282 collector.any_vec().push(dependency);
1283 Ok(())
1284}
1285
1286fn add_ts_pseudo_class_dependency<C: Collector>(
1287 state: TSStateForInvalidation,
1288 quirks_mode: QuirksMode,
1289 collector: &mut C,
1290) -> Result<(), AllocErr> {
1291 if state.is_empty() {
1292 return Ok(());
1293 }
1294 let dependency = collector.dependency();
1295 collector.ts_state_map().insert(
1296 TSStateDependency {
1297 dep: dependency,
1298 state,
1299 },
1300 quirks_mode,
1301 )
1302}
1303
1304impl<'a, 'b> RelativeSelectorDependencyCollector<'a, 'b> {
1305 fn visit_whole_selector(&mut self) -> bool {
1306 let mut iter = self.selector.selector.iter_skip_relative_selector_anchor();
1307 let mut index = 0;
1308
1309 self.additional_relative_selector_invalidation_map
1310 .needs_ancestors_traversal |= match self.selector.match_hint {
1311 RelativeSelectorMatchHint::InNextSiblingSubtree
1312 | RelativeSelectorMatchHint::InSiblingSubtree
1313 | RelativeSelectorMatchHint::InSubtree => true,
1314 _ => false,
1315 };
1316 loop {
1317 self.compound_state = PerCompoundState::new(index);
1319
1320 let (keep_traversing, index_offset) = visit_all_in_iter_compound(self, &mut iter);
1321
1322 if !keep_traversing {
1323 return false;
1324 }
1325
1326 index += index_offset;
1327
1328 if let Err(err) = add_pseudo_class_dependency(
1329 self.compound_state.element_state,
1330 self.quirks_mode,
1331 self,
1332 ) {
1333 *self.alloc_error = Some(err);
1334 return false;
1335 }
1336
1337 if let Err(err) = add_ts_pseudo_class_dependency(
1338 self.compound_state_attributes.ts_state,
1339 self.quirks_mode,
1340 self,
1341 ) {
1342 *self.alloc_error = Some(err);
1343 return false;
1344 }
1345
1346 if !self.compound_state_attributes.added_entry {
1347 if let Err(err) =
1349 add_non_unique_info(&self.selector.selector, self.compound_state.offset, self)
1350 {
1351 *self.alloc_error = Some(err);
1352 return false;
1353 }
1354 }
1355
1356 let combinator = iter.next_sequence();
1357 if let Some(c) = combinator {
1358 match c {
1359 Combinator::Child | Combinator::Descendant => {
1360 self.combinator_count.child_or_descendants -= 1
1361 },
1362 Combinator::NextSibling | Combinator::LaterSibling => {
1363 self.combinator_count.adjacent_or_next_siblings -= 1
1364 },
1365 Combinator::Part | Combinator::PseudoElement | Combinator::SlotAssignment => (),
1366 }
1367 } else {
1368 return true;
1369 }
1370 index += 1; }
1372 }
1373}
1374
1375impl<'a, 'b> Collector for RelativeSelectorDependencyCollector<'a, 'b> {
1376 fn dependency(&mut self) -> Dependency {
1377 let scope_dependencies = self.inner_scope_dependencies();
1378 let scope_kind = self.scope_dependencies.scope_kind;
1379
1380 let next = next_dependency(
1381 self.next_selectors,
1382 None,
1383 scope_dependencies.as_ref(),
1384 scope_kind,
1385 );
1386 debug_assert!(
1387 next.as_ref().is_some_and(|d| !matches!(
1388 d.slice()[0].kind,
1389 DependencyInvalidationKind::Relative(_)
1390 )),
1391 "Duplicate relative dependency?"
1392 );
1393 debug_assert!(
1394 next.as_ref().is_some_and(|d| !d.slice().is_empty()),
1395 "Empty dependency?"
1396 );
1397
1398 Dependency {
1399 selector: self.selector.selector.clone(),
1400 selector_offset: self.compound_state.offset,
1401 kind: DependencyInvalidationKind::Relative(
1402 match self.combinator_count.get_match_hint() {
1403 RelativeSelectorMatchHint::InChild => {
1404 RelativeDependencyInvalidationKind::Parent
1405 },
1406 RelativeSelectorMatchHint::InSubtree => {
1407 RelativeDependencyInvalidationKind::Ancestors
1408 },
1409 RelativeSelectorMatchHint::InNextSibling => {
1410 RelativeDependencyInvalidationKind::PrevSibling
1411 },
1412 RelativeSelectorMatchHint::InSibling => {
1413 RelativeDependencyInvalidationKind::EarlierSibling
1414 },
1415 RelativeSelectorMatchHint::InNextSiblingSubtree => {
1416 RelativeDependencyInvalidationKind::AncestorPrevSibling
1417 },
1418 RelativeSelectorMatchHint::InSiblingSubtree => {
1419 RelativeDependencyInvalidationKind::AncestorEarlierSibling
1420 },
1421 },
1422 ),
1423 next,
1424 }
1425 }
1426
1427 fn id_map(&mut self) -> &mut IdOrClassDependencyMap {
1428 &mut self.relative_selector_invalidation_map.id_to_selector
1429 }
1430
1431 fn class_map(&mut self) -> &mut IdOrClassDependencyMap {
1432 &mut self.relative_selector_invalidation_map.class_to_selector
1433 }
1434
1435 fn state_map(&mut self) -> &mut StateDependencyMap {
1436 &mut self
1437 .relative_selector_invalidation_map
1438 .state_affecting_selectors
1439 }
1440
1441 fn attribute_map(&mut self) -> &mut LocalNameDependencyMap {
1442 &mut self
1443 .relative_selector_invalidation_map
1444 .other_attribute_affecting_selectors
1445 }
1446
1447 fn custom_state_map(&mut self) -> &mut CustomStateDependencyMap {
1448 &mut self
1449 .relative_selector_invalidation_map
1450 .custom_state_affecting_selectors
1451 }
1452
1453 fn inner_scope_dependencies(&self) -> Option<ThinArc<(), Dependency>> {
1454 self.scope_dependencies.inner_dependencies.clone()
1455 }
1456
1457 fn this_scope_dependencies(&mut self) -> &mut Option<Vec<Dependency>> {
1458 &mut self.scope_dependencies.this_dependencies
1459 }
1460
1461 fn update_states(&mut self, element_state: ElementState, document_state: DocumentState) {
1462 self.compound_state.element_state |= element_state;
1463 *self.document_state |= document_state;
1464 }
1465
1466 fn type_map(&mut self) -> &mut LocalNameDependencyMap {
1467 &mut self
1468 .additional_relative_selector_invalidation_map
1469 .type_to_selector
1470 }
1471
1472 fn ts_state_map(&mut self) -> &mut TSStateDependencyMap {
1473 &mut self
1474 .additional_relative_selector_invalidation_map
1475 .ts_state_to_selector
1476 }
1477
1478 fn any_vec(&mut self) -> &mut AnyDependencyMap {
1479 &mut self
1480 .additional_relative_selector_invalidation_map
1481 .any_to_selector
1482 }
1483}
1484
1485enum ComponentVisitResult {
1486 IsIrrelevant,
1488 Handled(TSStateForInvalidation),
1491}
1492
1493#[inline(always)]
1494fn on_simple_selector<C: Collector>(
1495 s: &Component<SelectorImpl>,
1496 quirks_mode: QuirksMode,
1497 collector: &mut C,
1498) -> Result<ComponentVisitResult, AllocErr> {
1499 match *s {
1500 Component::ID(..) | Component::Class(..) => {
1501 on_id_or_class(s, quirks_mode, collector)?;
1502 Ok(ComponentVisitResult::Handled(
1503 TSStateForInvalidation::empty(),
1504 ))
1505 },
1506 Component::ImplicitScope | Component::Scope => {
1507 on_scope(collector)?;
1508 Ok(ComponentVisitResult::Handled(
1509 TSStateForInvalidation::empty(),
1510 ))
1511 },
1512 Component::NonTSPseudoClass(ref pc) => {
1513 on_pseudo_class(pc, collector)?;
1514 Ok(ComponentVisitResult::Handled(
1515 TSStateForInvalidation::empty(),
1516 ))
1517 },
1518 Component::Empty => Ok(ComponentVisitResult::Handled(TSStateForInvalidation::EMPTY)),
1519 Component::Nth(data) => {
1520 let kind = if data.is_simple_edge() {
1521 if data.ty.is_from_end() {
1522 TSStateForInvalidation::NTH_EDGE_LAST
1523 } else {
1524 TSStateForInvalidation::NTH_EDGE_FIRST
1525 }
1526 } else {
1527 TSStateForInvalidation::NTH
1528 };
1529 Ok(ComponentVisitResult::Handled(kind))
1530 },
1531 Component::RelativeSelectorAnchor => unreachable!("Should not visit this far"),
1532 _ => Ok(ComponentVisitResult::IsIrrelevant),
1533 }
1534}
1535
1536impl<'a, 'b> SelectorVisitor for RelativeSelectorDependencyCollector<'a, 'b> {
1537 type Impl = SelectorImpl;
1538
1539 fn visit_selector_list(
1540 &mut self,
1541 _list_kind: SelectorListKind,
1542 list: &[Selector<SelectorImpl>],
1543 ) -> bool {
1544 let mut next_stack = NextSelectors::new();
1545 let next_dependency = ThinArc::from_header_and_iter((), [self.dependency()].into_iter());
1546 for selector in list {
1547 let mut iter = selector.iter();
1548 let saved_added_entry = self.compound_state_attributes.added_entry;
1549
1550 let (keep_traversing, mut index) = visit_all_in_iter_compound(self, &mut iter);
1551
1552 if !keep_traversing {
1553 return false;
1554 }
1555
1556 let combinator = iter.next_sequence();
1557
1558 self.compound_state_attributes.added_entry = saved_added_entry;
1563 if combinator.is_none() {
1564 continue;
1565 }
1566
1567 index += 1; let mut nested = SelectorDependencyCollector {
1570 map: &mut *self.map,
1571 relative_selector_invalidation_map: &mut *self.relative_selector_invalidation_map,
1572 additional_relative_selector_invalidation_map: self
1573 .additional_relative_selector_invalidation_map,
1574 document_state: &mut *self.document_state,
1575 selector,
1576 next_selectors: &mut next_stack,
1577 quirks_mode: self.quirks_mode,
1578 compound_state: PerCompoundState::new(index),
1579 relative_inner_collector: Some(RelativeSelectorInnerCollectorState {
1580 next_dependency: &next_dependency,
1581 relative_compound_state: RelativeSelectorCompoundStateAttributes::new(),
1582 }),
1583 scope_dependencies: self.scope_dependencies,
1584 alloc_error: &mut *self.alloc_error,
1585 };
1586 if !nested.visit_whole_selector_from(iter, index) {
1587 return false;
1588 }
1589 }
1590 true
1591 }
1592
1593 fn visit_relative_selector_list(
1594 &mut self,
1595 _list: &[selectors::parser::RelativeSelector<Self::Impl>],
1596 ) -> bool {
1597 true
1599 }
1600
1601 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
1602 match on_simple_selector(s, self.quirks_mode, self) {
1603 Ok(result) => {
1604 if let ComponentVisitResult::Handled(state) = result {
1605 self.compound_state_attributes.added_entry = true;
1606 self.compound_state_attributes.ts_state.insert(state);
1607 }
1608 true
1609 },
1610 Err(err) => {
1611 *self.alloc_error = Some(err);
1612 false
1613 },
1614 }
1615 }
1616
1617 fn visit_attribute_selector(
1618 &mut self,
1619 _: &NamespaceConstraint<&Namespace>,
1620 local_name: &LocalName,
1621 local_name_lower: &LocalName,
1622 ) -> bool {
1623 self.compound_state_attributes.added_entry = true;
1624 if let Err(err) = on_attribute(local_name, local_name_lower, self) {
1625 *self.alloc_error = Some(err);
1626 return false;
1627 }
1628 true
1629 }
1630}