style/invalidation/element/
document_state.rs1use crate::dom::TElement;
8use crate::invalidation::element::invalidation_map::Dependency;
9use crate::invalidation::element::invalidator::{
10 DescendantInvalidationLists, InvalidationVector, SiblingTraversalMap,
11};
12use crate::invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
13use crate::invalidation::element::state_and_attributes;
14use crate::stylist::CascadeData;
15use dom::DocumentState;
16use selectors::matching::{
17 IncludeStartingStyle, MatchingContext, MatchingForInvalidation, MatchingMode,
18 NeedsSelectorFlags, QuirksMode, SelectorCaches, VisitedHandlingMode,
19};
20
21#[derive(Debug)]
24pub struct InvalidationMatchingData {
25 pub document_state: DocumentState,
27}
28
29impl Default for InvalidationMatchingData {
30 #[inline(always)]
31 fn default() -> Self {
32 Self {
33 document_state: DocumentState::empty(),
34 }
35 }
36}
37
38pub struct DocumentStateInvalidationProcessor<'a, 'b, E: TElement, I> {
41 rules: I,
42 matching_context: MatchingContext<'a, E::Impl>,
43 traversal_map: SiblingTraversalMap<E>,
44 document_states_changed: DocumentState,
45 _marker: std::marker::PhantomData<&'b ()>,
46}
47
48impl<'a, 'b, E: TElement, I> DocumentStateInvalidationProcessor<'a, 'b, E, I> {
49 #[inline]
51 pub fn new(
52 rules: I,
53 document_states_changed: DocumentState,
54 selector_caches: &'a mut SelectorCaches,
55 quirks_mode: QuirksMode,
56 ) -> Self {
57 let mut matching_context = MatchingContext::<'a, E::Impl>::new_for_visited(
58 MatchingMode::Normal,
59 None,
60 selector_caches,
61 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
62 IncludeStartingStyle::No,
63 quirks_mode,
64 NeedsSelectorFlags::No,
65 MatchingForInvalidation::No,
66 );
67
68 matching_context.extra_data.invalidation_data.document_state = document_states_changed;
69
70 Self {
71 rules,
72 document_states_changed,
73 matching_context,
74 traversal_map: SiblingTraversalMap::default(),
75 _marker: std::marker::PhantomData,
76 }
77 }
78}
79
80impl<'a, 'b, E, I> InvalidationProcessor<'b, 'a, E>
81 for DocumentStateInvalidationProcessor<'a, 'b, E, I>
82where
83 E: TElement,
84 I: Iterator<Item = &'b CascadeData>,
85{
86 fn check_outer_dependency(&mut self, _: &Dependency, _: E) -> bool {
87 debug_assert!(
88 false,
89 "how, we should only have parent-less dependencies here!"
90 );
91 true
92 }
93
94 fn collect_invalidations(
95 &mut self,
96 _element: E,
97 self_invalidations: &mut InvalidationVector<'b>,
98 _descendant_invalidations: &mut DescendantInvalidationLists<'b>,
99 _sibling_invalidations: &mut InvalidationVector<'b>,
100 ) -> bool {
101 for cascade_data in &mut self.rules {
102 let map = cascade_data.invalidation_map();
103 for dependency in &map.document_state_selectors {
104 if !dependency.state.intersects(self.document_states_changed) {
105 continue;
106 }
107
108 self_invalidations.push(Invalidation::new(
116 &dependency.dependency,
117 None,
118 ));
119 }
120 }
121
122 false
123 }
124
125 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
126 &mut self.matching_context
127 }
128
129 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
130 &self.traversal_map
131 }
132
133 fn recursion_limit_exceeded(&mut self, _: E) {
134 unreachable!("We don't run document state invalidation with stack limits")
135 }
136
137 fn should_process_descendants(&mut self, element: E) -> bool {
138 match element.borrow_data() {
139 Some(d) => state_and_attributes::should_process_descendants(&d),
140 None => false,
141 }
142 }
143
144 fn invalidated_descendants(&mut self, element: E, child: E) {
145 state_and_attributes::invalidated_descendants(element, child)
146 }
147
148 fn invalidated_self(&mut self, element: E) {
149 state_and_attributes::invalidated_self(element);
150 }
151
152 fn invalidated_sibling(&mut self, sibling: E, of: E) {
153 state_and_attributes::invalidated_sibling(sibling, of);
154 }
155}