1use crate::bloom::StyleBloom;
10use crate::context::SharedStyleContext;
11use crate::dom::{TElement, TShadowRoot};
12use crate::properties::ComputedValues;
13use crate::sharing::{StyleSharingCandidate, StyleSharingTarget};
14use selectors::matching::SelectorCaches;
15
16pub fn parents_allow_sharing<E>(
19 target: &mut StyleSharingTarget<E>,
20 candidate: &mut StyleSharingCandidate<E>,
21) -> bool
22where
23 E: TElement,
24{
25 if target.parent_style_identity() != candidate.parent_style_identity() {
28 return false;
29 }
30
31 let parent = target.inheritance_parent().unwrap();
33 let candidate_parent = candidate.element.inheritance_parent().unwrap();
34 if parent == candidate_parent {
35 return true;
36 }
37
38 let parent_data = parent.borrow_data().unwrap();
49 let candidate_parent_data = candidate_parent.borrow_data().unwrap();
50 if !parent_data.safe_for_cousin_sharing() || !candidate_parent_data.safe_for_cousin_sharing() {
51 return false;
52 }
53
54 true
55}
56
57pub fn have_same_style_attribute<E>(
61 target: &mut StyleSharingTarget<E>,
62 candidate: &mut StyleSharingCandidate<E>,
63 shared_context: &SharedStyleContext,
64) -> bool
65where
66 E: TElement,
67{
68 match (target.style_attribute(), candidate.style_attribute()) {
69 (None, None) => true,
70 (Some(_), None) | (None, Some(_)) => false,
71 (Some(a), Some(b)) => {
72 if std::ptr::eq(&*a, &*b) {
73 return true;
74 }
75 let guard = shared_context.guards.author;
76 *a.read_with(guard) == *b.read_with(guard)
77 },
78 }
79}
80
81pub fn have_same_presentational_hints<E>(
83 target: &mut StyleSharingTarget<E>,
84 candidate: &mut StyleSharingCandidate<E>,
85) -> bool
86where
87 E: TElement,
88{
89 target.pres_hints() == candidate.pres_hints()
90}
91
92pub fn have_same_class<E>(
96 target: &mut StyleSharingTarget<E>,
97 candidate: &mut StyleSharingCandidate<E>,
98) -> bool
99where
100 E: TElement,
101{
102 target.class_list() == candidate.class_list()
103}
104
105pub fn have_same_parts<E>(
109 target: &mut StyleSharingTarget<E>,
110 candidate: &mut StyleSharingCandidate<E>,
111) -> bool
112where
113 E: TElement,
114{
115 target.part_list() == candidate.part_list()
116}
117
118#[inline]
125pub fn revalidate<E>(
126 target: &mut StyleSharingTarget<E>,
127 candidate: &mut StyleSharingCandidate<E>,
128 shared_context: &SharedStyleContext,
129 bloom: &StyleBloom<E>,
130 selector_caches: &mut SelectorCaches,
131) -> bool
132where
133 E: TElement,
134{
135 let stylist = &shared_context.stylist;
136
137 let for_element = target.revalidation_match_results(stylist, bloom, selector_caches);
138
139 let for_candidate = candidate.revalidation_match_results(stylist, bloom, selector_caches);
140
141 for_element == for_candidate
142}
143
144#[inline]
147pub fn have_same_referenced_attrs<E>(
148 target: &StyleSharingTarget<E>,
149 candidate: &StyleSharingCandidate<E>,
150) -> bool
151where
152 E: TElement,
153{
154 let borrowed_data = candidate.element.borrow_data().unwrap();
156 let styles = &borrowed_data.styles;
157
158 let check_style = |style: &ComputedValues| {
159 let Some(ref attrs) = style.attribute_references else {
160 return true;
161 };
162 attrs.iter().all(|(name, namespaces)| {
163 namespaces.iter().all(|namespace| {
164 target.get_attr(name, namespace) == candidate.get_attr(name, namespace)
165 })
166 })
167 };
168
169 if !check_style(styles.primary()) {
170 return false;
171 }
172
173 for pseudo_styles in styles.pseudos.as_array() {
174 let Some(ref styles) = pseudo_styles else {
175 continue;
176 };
177 if !check_style(styles) {
178 return false;
179 }
180 }
181 true
182}
183
184#[inline]
187pub fn revalidate_scope<E>(
188 target: &mut StyleSharingTarget<E>,
189 candidate: &mut StyleSharingCandidate<E>,
190 shared_context: &SharedStyleContext,
191 selector_caches: &mut SelectorCaches,
192) -> bool
193where
194 E: TElement,
195{
196 let stylist = &shared_context.stylist;
197 let for_element = target.scope_revalidation_results(stylist, selector_caches);
198 let for_candidate = candidate.scope_revalidation_results(stylist, selector_caches);
199
200 for_element == for_candidate
201}
202
203#[inline]
205pub fn may_match_different_id_rules<E>(
206 shared_context: &SharedStyleContext,
207 element: E,
208 candidate: E,
209) -> bool
210where
211 E: TElement,
212{
213 let element_id = element.id();
214 let candidate_id = candidate.id();
215
216 if element_id == candidate_id {
217 return false;
218 }
219
220 let stylist = &shared_context.stylist;
221
222 let may_have_rules_for_element = match element_id {
223 Some(id) => stylist.may_have_rules_for_id(id, element),
224 None => false,
225 };
226
227 if may_have_rules_for_element {
228 return true;
229 }
230
231 match candidate_id {
232 Some(id) => stylist.may_have_rules_for_id(id, candidate),
233 None => false,
234 }
235}
236
237#[inline]
239pub fn shadow_root_style_data_equals<S>(l: Option<S>, r: Option<S>) -> bool
240where
241 S: TShadowRoot,
242{
243 if l == r {
244 return true;
245 }
246 match (
247 l.and_then(|s| s.style_data()),
248 r.and_then(|s| s.style_data()),
249 ) {
250 (Some(l), Some(r)) => std::ptr::eq(l, r),
251 (None, None) => true,
252 _ => false,
253 }
254}