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};
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 IncludeStartingStyle::No,
64 quirks_mode,
65 NeedsSelectorFlags::No,
66 MatchingForInvalidation::No,
67 );
68
69 matching_context.extra_data.invalidation_data.document_state = document_states_changed;
70
71 Self {
72 rules,
73 document_states_changed,
74 matching_context,
75 traversal_map: SiblingTraversalMap::default(),
76 _marker: std::marker::PhantomData,
77 }
78 }
79}
80
81impl<'a, 'b, E, I> InvalidationProcessor<'b, 'a, E>
82 for DocumentStateInvalidationProcessor<'a, 'b, E, I>
83where
84 E: TElement,
85 I: Iterator<Item = &'b CascadeData>,
86{
87 fn check_outer_dependency(&mut self, _: &Dependency, _: E, _: Option<OpaqueElement>) -> bool {
88 debug_assert!(
89 false,
90 "how, we should only have parent-less dependencies here!"
91 );
92 true
93 }
94
95 fn collect_invalidations(
96 &mut self,
97 _element: E,
98 self_invalidations: &mut InvalidationVector<'b>,
99 _descendant_invalidations: &mut DescendantInvalidationLists<'b>,
100 _sibling_invalidations: &mut InvalidationVector<'b>,
101 ) -> bool {
102 for cascade_data in &mut self.rules {
103 let map = cascade_data.invalidation_map();
104 for dependency in &map.document_state_selectors {
105 if !dependency.state.intersects(self.document_states_changed) {
106 continue;
107 }
108
109 self_invalidations.push(Invalidation::new(
117 &dependency.dependency,
118 None,
119 None,
120 ));
121 }
122 }
123
124 false
125 }
126
127 fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
128 &mut self.matching_context
129 }
130
131 fn sibling_traversal_map(&self) -> &SiblingTraversalMap<E> {
132 &self.traversal_map
133 }
134
135 fn recursion_limit_exceeded(&mut self, _: E) {
136 unreachable!("We don't run document state invalidation with stack limits")
137 }
138
139 fn should_process_descendants(&mut self, element: E) -> bool {
140 match element.borrow_data() {
141 Some(d) => state_and_attributes::should_process_descendants(&d),
142 None => false,
143 }
144 }
145
146 fn invalidated_descendants(&mut self, element: E, child: E) {
147 state_and_attributes::invalidated_descendants(element, child)
148 }
149
150 fn invalidated_self(&mut self, element: E) {
151 state_and_attributes::invalidated_self(element);
152 }
153
154 fn invalidated_sibling(&mut self, sibling: E, of: E) {
155 state_and_attributes::invalidated_sibling(sibling, of);
156 }
157}