1use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
8use crate::dom::{TElement, TNode, TShadowRoot};
9use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
10use crate::rule_tree::{CascadeLevel, ShadowCascadeOrder};
11use crate::selector_map::SelectorMap;
12use crate::selector_parser::PseudoElement;
13use crate::shared_lock::Locked;
14use crate::stylesheets::{layer_rule::LayerOrder, Origin};
15use crate::stylist::{AuthorStylesEnabled, CascadeData, Rule, RuleInclusion, Stylist};
16use selectors::matching::MatchingContext;
17use servo_arc::ArcBorrow;
18use smallvec::SmallVec;
19
20#[inline]
38pub fn containing_shadow_ignoring_svg_use<E: TElement>(
39 element: E,
40) -> Option<<E::ConcreteNode as TNode>::ConcreteShadowRoot> {
41 let mut shadow = element.containing_shadow()?;
42 loop {
43 let host = shadow.host();
44 let host_is_svg_use_element =
45 host.is_svg_element() && host.local_name() == &**local_name!("use");
46 if !host_is_svg_use_element {
47 return Some(shadow);
48 }
49 debug_assert!(
50 shadow.style_data().is_none(),
51 "We allow no stylesheets in <svg:use> subtrees"
52 );
53 shadow = host.containing_shadow()?;
54 }
55}
56
57pub struct RuleCollector<'a, 'b: 'a, E>
63where
64 E: TElement,
65{
66 element: E,
67 rule_hash_target: E,
68 stylist: &'a Stylist,
69 pseudo_elements: SmallVec<[PseudoElement; 1]>,
70 style_attribute: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>,
71 smil_override: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>,
72 animation_declarations: AnimationDeclarations,
73 rule_inclusion: RuleInclusion,
74 rules: &'a mut ApplicableDeclarationList,
75 context: &'a mut MatchingContext<'b, E::Impl>,
76 matches_user_and_content_rules: bool,
77 matches_document_author_rules: bool,
78 in_sort_scope: bool,
79}
80
81impl<'a, 'b: 'a, E> RuleCollector<'a, 'b, E>
82where
83 E: TElement,
84{
85 pub fn new(
87 stylist: &'a Stylist,
88 element: E,
89 pseudo_elements: SmallVec<[PseudoElement; 1]>,
90 style_attribute: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>,
91 smil_override: Option<ArcBorrow<'a, Locked<PropertyDeclarationBlock>>>,
92 animation_declarations: AnimationDeclarations,
93 rule_inclusion: RuleInclusion,
94 rules: &'a mut ApplicableDeclarationList,
95 context: &'a mut MatchingContext<'b, E::Impl>,
96 ) -> Self {
97 let rule_hash_target = element.rule_hash_target();
98 let matches_user_and_content_rules = rule_hash_target.matches_user_and_content_rules();
99
100 debug_assert!(pseudo_elements.iter().all(|p| !p.is_precomputed()));
101
102 Self {
103 element,
104 rule_hash_target,
105 stylist,
106 pseudo_elements,
107 style_attribute,
108 smil_override,
109 animation_declarations,
110 rule_inclusion,
111 context,
112 rules,
113 matches_user_and_content_rules,
114 matches_document_author_rules: matches_user_and_content_rules,
115 in_sort_scope: false,
116 }
117 }
118
119 #[inline]
125 fn in_tree(&mut self, host: Option<E>, f: impl FnOnce(&mut Self)) {
126 debug_assert!(!self.in_sort_scope, "Nested sorting makes no sense");
127 let start = self.rules.len();
128 self.in_sort_scope = true;
129 let old_host = self.context.current_host.take();
130 self.context.current_host = host.map(|e| e.opaque());
131 f(self);
132 if start != self.rules.len() {
133 self.rules[start..].sort_unstable_by_key(|block| block.sort_key());
134 }
135 self.context.current_host = old_host;
136 self.in_sort_scope = false;
137 }
138
139 #[inline]
140 fn in_shadow_tree(&mut self, host: E, f: impl FnOnce(&mut Self)) {
141 self.in_tree(Some(host), f);
142 }
143
144 fn collect_stylist_rules(&mut self, origin: Origin) {
145 let cascade_level = match origin {
146 Origin::UserAgent => CascadeLevel::UANormal,
147 Origin::User => CascadeLevel::UserNormal,
148 Origin::Author => CascadeLevel::same_tree_author_normal(),
149 };
150
151 let cascade_data = self.stylist.cascade_data().borrow_for_origin(origin);
152 let map = match cascade_data.normal_rules(&self.pseudo_elements) {
153 Some(m) => m,
154 None => return,
155 };
156
157 self.in_tree(None, |collector| {
158 collector.collect_rules_in_map(map, cascade_level, cascade_data);
159 });
160 }
161
162 fn collect_user_agent_rules(&mut self) {
163 self.collect_stylist_rules(Origin::UserAgent);
164 #[cfg(feature = "gecko")]
165 self.collect_view_transition_dynamic_rules();
166 }
167
168 #[cfg(feature = "gecko")]
169 fn collect_view_transition_dynamic_rules(&mut self) {
170 if !self
171 .pseudo_elements
172 .first()
173 .is_some_and(|p| p.is_named_view_transition())
174 {
175 return;
176 }
177 let len_before_vt_rules = self.rules.len();
178 self.element
179 .synthesize_view_transition_dynamic_rules(self.rules);
180 if cfg!(debug_assertions) && self.rules.len() != len_before_vt_rules {
181 for declaration in &self.rules[len_before_vt_rules..] {
182 assert_eq!(declaration.level(), CascadeLevel::UANormal);
183 }
184 }
185 }
186
187 fn collect_user_rules(&mut self) {
188 if !self.matches_user_and_content_rules {
189 return;
190 }
191
192 self.collect_stylist_rules(Origin::User);
193 }
194
195 fn collect_presentational_hints(&mut self) {
200 if !self.pseudo_elements.is_empty() {
201 return;
202 }
203
204 let length_before_preshints = self.rules.len();
205 self.element
206 .synthesize_presentational_hints_for_legacy_attributes(
207 self.context.visited_handling(),
208 self.rules,
209 );
210 if cfg!(debug_assertions) && self.rules.len() != length_before_preshints {
211 for declaration in &self.rules[length_before_preshints..] {
212 assert_eq!(declaration.level(), CascadeLevel::PresHints);
213 }
214 }
215 }
216
217 #[inline]
218 fn collect_rules_in_list(
219 &mut self,
220 part_rules: &[Rule],
221 cascade_level: CascadeLevel,
222 cascade_data: &CascadeData,
223 ) {
224 debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
225 SelectorMap::get_matching_rules(
226 self.element,
227 part_rules,
228 &mut self.rules,
229 &mut self.context,
230 cascade_level,
231 cascade_data,
232 &self.stylist,
233 );
234 }
235
236 #[inline]
237 fn collect_rules_in_map(
238 &mut self,
239 map: &SelectorMap<Rule>,
240 cascade_level: CascadeLevel,
241 cascade_data: &CascadeData,
242 ) {
243 debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
244 map.get_all_matching_rules(
245 self.element,
246 self.rule_hash_target,
247 &mut self.rules,
248 &mut self.context,
249 cascade_level,
250 cascade_data,
251 &self.stylist,
252 );
253 }
254
255 fn collect_host_and_slotted_rules(&mut self) {
258 let mut slots = SmallVec::<[_; 3]>::new();
259 let mut current = self.rule_hash_target.assigned_slot();
260 let mut shadow_cascade_order = ShadowCascadeOrder::for_outermost_shadow_tree();
261
262 while let Some(slot) = current {
263 debug_assert!(
264 self.matches_user_and_content_rules,
265 "We should not slot NAC anywhere"
266 );
267 slots.push(slot);
268 current = slot.assigned_slot();
269 shadow_cascade_order.dec();
270 }
271
272 self.collect_host_rules(shadow_cascade_order);
273
274 for slot in slots.iter().rev() {
277 shadow_cascade_order.inc();
278
279 let shadow = slot.containing_shadow().unwrap();
280 let data = match shadow.style_data() {
281 Some(d) => d,
282 None => continue,
283 };
284 let slotted_rules = match data.slotted_rules(&self.pseudo_elements) {
285 Some(r) => r,
286 None => continue,
287 };
288
289 self.in_shadow_tree(shadow.host(), |collector| {
290 let cascade_level = CascadeLevel::AuthorNormal {
291 shadow_cascade_order,
292 };
293 collector.collect_rules_in_map(slotted_rules, cascade_level, data);
294 });
295 }
296 }
297
298 fn collect_rules_from_containing_shadow_tree(&mut self) {
299 if !self.matches_user_and_content_rules {
300 return;
301 }
302
303 let containing_shadow = containing_shadow_ignoring_svg_use(self.rule_hash_target);
304 let containing_shadow = match containing_shadow {
305 Some(s) => s,
306 None => return,
307 };
308
309 self.matches_document_author_rules = false;
310
311 let cascade_data = match containing_shadow.style_data() {
312 Some(c) => c,
313 None => return,
314 };
315
316 let cascade_level = CascadeLevel::same_tree_author_normal();
317 self.in_shadow_tree(containing_shadow.host(), |collector| {
318 if let Some(map) = cascade_data.normal_rules(&collector.pseudo_elements) {
319 collector.collect_rules_in_map(map, cascade_level, cascade_data);
320 }
321
322 let hash_target = collector.rule_hash_target;
324 if !hash_target.has_part_attr() {
325 return;
326 }
327
328 let part_rules = match cascade_data.part_rules(&collector.pseudo_elements) {
329 Some(p) => p,
330 None => return,
331 };
332
333 hash_target.each_part(|part| {
334 if let Some(part_rules) = part_rules.get(&part.0) {
335 collector.collect_rules_in_list(part_rules, cascade_level, cascade_data);
336 }
337 });
338 });
339 }
340
341 fn collect_host_rules(&mut self, shadow_cascade_order: ShadowCascadeOrder) {
343 let shadow = match self.rule_hash_target.shadow_root() {
344 Some(s) => s,
345 None => return,
346 };
347
348 let style_data = match shadow.style_data() {
349 Some(d) => d,
350 None => return,
351 };
352
353 let host_rules = match style_data.featureless_host_rules(&self.pseudo_elements) {
354 Some(rules) => rules,
355 None => return,
356 };
357
358 let rule_hash_target = self.rule_hash_target;
359 self.in_shadow_tree(rule_hash_target, |collector| {
360 let cascade_level = CascadeLevel::AuthorNormal {
361 shadow_cascade_order,
362 };
363 debug_assert!(!collector.context.featureless(), "How?");
364 collector.context.featureless = true;
365 collector.collect_rules_in_map(host_rules, cascade_level, style_data);
366 collector.context.featureless = false;
367 });
368 }
369
370 fn collect_document_author_rules(&mut self) {
371 if !self.matches_document_author_rules {
372 return;
373 }
374
375 self.collect_stylist_rules(Origin::Author);
376 }
377
378 fn collect_part_rules_from_outer_trees(&mut self) {
379 if !self.rule_hash_target.has_part_attr() {
380 return;
381 }
382
383 let mut inner_shadow = match self.rule_hash_target.containing_shadow() {
384 Some(s) => s,
385 None => return,
386 };
387
388 let mut shadow_cascade_order = ShadowCascadeOrder::for_innermost_containing_tree();
389
390 let mut parts = SmallVec::<[_; 3]>::new();
391 self.rule_hash_target.each_part(|p| parts.push(p.clone()));
392
393 loop {
394 if parts.is_empty() {
395 return;
396 }
397
398 let inner_shadow_host = inner_shadow.host();
399 let outer_shadow = inner_shadow_host.containing_shadow();
400 let cascade_data = match outer_shadow {
401 Some(shadow) => shadow.style_data(),
402 None => Some(
403 self.stylist
404 .cascade_data()
405 .borrow_for_origin(Origin::Author),
406 ),
407 };
408
409 if let Some(cascade_data) = cascade_data {
410 if let Some(part_rules) = cascade_data.part_rules(&self.pseudo_elements) {
411 let containing_host = outer_shadow.map(|s| s.host());
412 let cascade_level = CascadeLevel::AuthorNormal {
413 shadow_cascade_order,
414 };
415 self.in_tree(containing_host, |collector| {
416 for p in &parts {
417 if let Some(part_rules) = part_rules.get(&p.0) {
418 collector.collect_rules_in_list(
419 part_rules,
420 cascade_level,
421 cascade_data,
422 );
423 }
424 }
425 });
426 shadow_cascade_order.inc();
427 }
428 }
429
430 inner_shadow = match outer_shadow {
431 Some(s) => s,
432 None => break, };
434
435 let mut new_parts = SmallVec::new();
436 for part in &parts {
437 inner_shadow_host.each_exported_part(part, |exported_part| {
438 new_parts.push(exported_part.clone());
439 });
440 }
441 parts = new_parts;
442 }
443 }
444
445 fn collect_style_attribute(&mut self) {
446 if let Some(sa) = self.style_attribute {
447 self.rules
448 .push(ApplicableDeclarationBlock::from_declarations(
449 sa.clone_arc(),
450 CascadeLevel::same_tree_author_normal(),
451 LayerOrder::style_attribute(),
452 ));
453 }
454 }
455
456 fn collect_animation_rules(&mut self) {
457 if let Some(so) = self.smil_override {
458 self.rules
459 .push(ApplicableDeclarationBlock::from_declarations(
460 so.clone_arc(),
461 CascadeLevel::SMILOverride,
462 LayerOrder::root(),
463 ));
464 }
465
466 if let Some(anim) = self.animation_declarations.animations.take() {
470 self.rules
471 .push(ApplicableDeclarationBlock::from_declarations(
472 anim,
473 CascadeLevel::Animations,
474 LayerOrder::root(),
475 ));
476 }
477
478 if let Some(anim) = self.animation_declarations.transitions.take() {
481 self.rules
482 .push(ApplicableDeclarationBlock::from_declarations(
483 anim,
484 CascadeLevel::Transitions,
485 LayerOrder::root(),
486 ));
487 }
488 }
489
490 pub fn collect_all(mut self) {
494 self.collect_user_agent_rules();
495 self.collect_user_rules();
496 if self.rule_inclusion == RuleInclusion::DefaultOnly {
497 return;
498 }
499 self.collect_presentational_hints();
500 if self.stylist.author_styles_enabled() == AuthorStylesEnabled::No {
503 return;
504 }
505 self.collect_host_and_slotted_rules();
506 self.collect_rules_from_containing_shadow_tree();
507 self.collect_document_author_rules();
508 self.collect_style_attribute();
509 self.collect_part_rules_from_outer_trees();
510 self.collect_animation_rules();
511 }
512}