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 MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, QuirksMode,
18 SelectorCaches, VisitedHandlingMode,
19};
20use selectors::OpaqueElement;
21
22#[derive(Debug)]
25pub struct InvalidationMatchingData {
26 pub document_state: DocumentState,
28}
29
30impl Default for InvalidationMatchingData {
31 #[inline(always)]
32 fn default() -> Self {
33 Self {
34 document_state: DocumentState::empty(),
35 }
36 }
37}
38
39pub struct DocumentStateInvalidationProcessor<'a, 'b, E: TElement, I> {
42 rules: I,
43 matching_context: MatchingContext<'a, E::Impl>,
44 traversal_map: SiblingTraversalMap<E>,
45 document_states_changed: DocumentState,
46 _marker: std::marker::PhantomData<&'b ()>,
47}
48
49impl<'a, 'b, E: TElement, I> DocumentStateInvalidationProcessor<'a, 'b, E, I> {
50 #[inline]
52 pub fn new(
53 rules: I,
54 document_states_changed: DocumentState,
55 selector_caches: &'a mut SelectorCaches,
56 quirks_mode: QuirksMode,
57 ) -> Self {
58 let mut matching_context = MatchingContext::<'a, E::Impl>::new_for_visited(
59 MatchingMode::Normal,
60 None,
61 selector_caches,
62 VisitedHandlingMode::AllLinksVisitedAndUnvisited,
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, _: Option<OpaqueElement>) -> 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 None,
119 ));
120 }
121 }
122
123 false
124 }
125
126 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
127 &mut self.matching_context
128 }
129
130 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
131 &self.traversal_map
132 }
133
134 fn recursion_limit_exceeded(&mut self, _: E) {
135 unreachable!("We don't run document state invalidation with stack limits")
136 }
137
138 fn should_process_descendants(&mut self, element: E) -> bool {
139 match element.borrow_data() {
140 Some(d) => state_and_attributes::should_process_descendants(&d),
141 None => false,
142 }
143 }
144
145 fn invalidated_descendants(&mut self, element: E, child: E) {
146 state_and_attributes::invalidated_descendants(element, child)
147 }
148
149 fn invalidated_self(&mut self, element: E) {
150 state_and_attributes::invalidated_self(element);
151 }
152
153 fn invalidated_sibling(&mut self, sibling: E, of: E) {
154 state_and_attributes::invalidated_sibling(sibling, of);
155 }
156}