1use crate::applicable_declarations::{ApplicableDeclarationBlock, ApplicableDeclarationList};
8use crate::dom::{TElement, TNode, TShadowRoot};
9use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
10use crate::rule_tree::{CascadeLevel, CascadeOrigin, 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::new(CascadeOrigin::UA),
147 Origin::User => CascadeLevel::new(CascadeOrigin::User),
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::new(CascadeOrigin::UA));
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!(
213 declaration.level(),
214 CascadeLevel::new(CascadeOrigin::PresHints)
215 );
216 }
217 }
218 }
219
220 #[inline]
221 fn collect_rules_in_list(
222 &mut self,
223 part_rules: &[Rule],
224 cascade_level: CascadeLevel,
225 cascade_data: &CascadeData,
226 ) {
227 debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
228 SelectorMap::get_matching_rules(
229 self.element,
230 part_rules,
231 &mut self.rules,
232 &mut self.context,
233 cascade_level,
234 cascade_data,
235 &self.stylist,
236 );
237 }
238
239 #[inline]
240 fn collect_rules_in_map(
241 &mut self,
242 map: &SelectorMap<Rule>,
243 cascade_level: CascadeLevel,
244 cascade_data: &CascadeData,
245 ) {
246 debug_assert!(self.in_sort_scope, "Rules gotta be sorted");
247 map.get_all_matching_rules(
248 self.element,
249 self.rule_hash_target,
250 &mut self.rules,
251 &mut self.context,
252 cascade_level,
253 cascade_data,
254 &self.stylist,
255 );
256 }
257
258 fn collect_host_and_slotted_rules(&mut self) {
261 let mut slots = SmallVec::<[_; 3]>::new();
262 let mut current = self.rule_hash_target.assigned_slot();
263 let mut shadow_cascade_order = ShadowCascadeOrder::for_outermost_shadow_tree();
264
265 while let Some(slot) = current {
266 debug_assert!(
267 self.matches_user_and_content_rules,
268 "We should not slot NAC anywhere"
269 );
270 slots.push(slot);
271 current = slot.assigned_slot();
272 shadow_cascade_order.dec();
273 }
274
275 self.collect_host_rules(shadow_cascade_order);
276
277 for slot in slots.iter().rev() {
280 shadow_cascade_order.inc();
281
282 let shadow = slot.containing_shadow().unwrap();
283 let data = match shadow.style_data() {
284 Some(d) => d,
285 None => continue,
286 };
287 let slotted_rules = match data.slotted_rules(&self.pseudo_elements) {
288 Some(r) => r,
289 None => continue,
290 };
291
292 self.in_shadow_tree(shadow.host(), |collector| {
293 let cascade_level = CascadeLevel::author_normal(shadow_cascade_order);
294 collector.collect_rules_in_map(slotted_rules, cascade_level, data);
295 });
296 }
297 }
298
299 fn collect_rules_from_containing_shadow_tree(&mut self) {
300 if !self.matches_user_and_content_rules {
301 return;
302 }
303
304 let containing_shadow = containing_shadow_ignoring_svg_use(self.rule_hash_target);
305 let containing_shadow = match containing_shadow {
306 Some(s) => s,
307 None => return,
308 };
309
310 self.matches_document_author_rules = false;
311
312 let cascade_data = match containing_shadow.style_data() {
313 Some(c) => c,
314 None => return,
315 };
316
317 let cascade_level = CascadeLevel::same_tree_author_normal();
318 self.in_shadow_tree(containing_shadow.host(), |collector| {
319 if let Some(map) = cascade_data.normal_rules(&collector.pseudo_elements) {
320 collector.collect_rules_in_map(map, cascade_level, cascade_data);
321 }
322
323 let hash_target = collector.rule_hash_target;
325 if !hash_target.has_part_attr() {
326 return;
327 }
328
329 let part_rules = match cascade_data.part_rules(&collector.pseudo_elements) {
330 Some(p) => p,
331 None => return,
332 };
333
334 hash_target.each_part(|part| {
335 if let Some(part_rules) = part_rules.get(&part.0) {
336 collector.collect_rules_in_list(part_rules, cascade_level, cascade_data);
337 }
338 });
339 });
340 }
341
342 fn collect_host_rules(&mut self, shadow_cascade_order: ShadowCascadeOrder) {
344 let shadow = match self.rule_hash_target.shadow_root() {
345 Some(s) => s,
346 None => return,
347 };
348
349 let style_data = match shadow.style_data() {
350 Some(d) => d,
351 None => return,
352 };
353
354 let host_rules = match style_data.featureless_host_rules(&self.pseudo_elements) {
355 Some(rules) => rules,
356 None => return,
357 };
358
359 let rule_hash_target = self.rule_hash_target;
360 self.in_shadow_tree(rule_hash_target, |collector| {
361 let cascade_level = CascadeLevel::author_normal(shadow_cascade_order);
362 debug_assert!(!collector.context.featureless(), "How?");
363 collector.context.featureless = true;
364 collector.collect_rules_in_map(host_rules, cascade_level, style_data);
365 collector.context.featureless = false;
366 });
367 }
368
369 fn collect_document_author_rules(&mut self) {
370 if !self.matches_document_author_rules {
371 return;
372 }
373
374 self.collect_stylist_rules(Origin::Author);
375 }
376
377 fn collect_part_rules_from_outer_trees(&mut self) {
378 if !self.rule_hash_target.has_part_attr() {
379 return;
380 }
381
382 let mut inner_shadow = match self.rule_hash_target.containing_shadow() {
383 Some(s) => s,
384 None => return,
385 };
386
387 let mut shadow_cascade_order = ShadowCascadeOrder::for_innermost_containing_tree();
388
389 let mut parts = SmallVec::<[_; 3]>::new();
390 self.rule_hash_target.each_part(|p| parts.push(p.clone()));
391
392 loop {
393 if parts.is_empty() {
394 return;
395 }
396
397 let inner_shadow_host = inner_shadow.host();
398 let outer_shadow = inner_shadow_host.containing_shadow();
399 let cascade_data = match outer_shadow {
400 Some(shadow) => shadow.style_data(),
401 None => Some(
402 self.stylist
403 .cascade_data()
404 .borrow_for_origin(Origin::Author),
405 ),
406 };
407
408 if let Some(cascade_data) = cascade_data {
409 if let Some(part_rules) = cascade_data.part_rules(&self.pseudo_elements) {
410 let containing_host = outer_shadow.map(|s| s.host());
411 let cascade_level = CascadeLevel::author_normal(shadow_cascade_order);
412 self.in_tree(containing_host, |collector| {
413 for p in &parts {
414 if let Some(part_rules) = part_rules.get(&p.0) {
415 collector.collect_rules_in_list(
416 part_rules,
417 cascade_level,
418 cascade_data,
419 );
420 }
421 }
422 });
423 shadow_cascade_order.inc();
424 }
425 }
426
427 inner_shadow = match outer_shadow {
428 Some(s) => s,
429 None => break, };
431
432 let mut new_parts = SmallVec::new();
433 for part in &parts {
434 inner_shadow_host.each_exported_part(part, |exported_part| {
435 new_parts.push(exported_part.clone());
436 });
437 }
438 parts = new_parts;
439 }
440 }
441
442 fn collect_style_attribute(&mut self) {
443 if let Some(sa) = self.style_attribute {
444 self.rules
445 .push(ApplicableDeclarationBlock::from_declarations(
446 sa.clone_arc(),
447 CascadeLevel::same_tree_author_normal(),
448 LayerOrder::style_attribute(),
449 ));
450 }
451 }
452
453 fn collect_animation_rules(&mut self) {
454 if let Some(so) = self.smil_override {
455 self.rules
456 .push(ApplicableDeclarationBlock::from_declarations(
457 so.clone_arc(),
458 CascadeLevel::new(CascadeOrigin::SMILOverride),
459 LayerOrder::root(),
460 ));
461 }
462
463 if let Some(anim) = self.animation_declarations.animations.take() {
467 self.rules
468 .push(ApplicableDeclarationBlock::from_declarations(
469 anim,
470 CascadeLevel::new(CascadeOrigin::Animations),
471 LayerOrder::root(),
472 ));
473 }
474
475 if let Some(anim) = self.animation_declarations.transitions.take() {
478 self.rules
479 .push(ApplicableDeclarationBlock::from_declarations(
480 anim,
481 CascadeLevel::new(CascadeOrigin::Transitions),
482 LayerOrder::root(),
483 ));
484 }
485 }
486
487 pub fn collect_all(mut self) {
491 self.collect_user_agent_rules();
492 self.collect_user_rules();
493 if self.rule_inclusion == RuleInclusion::DefaultOnly {
494 return;
495 }
496 self.collect_presentational_hints();
497 if self.stylist.author_styles_enabled() == AuthorStylesEnabled::No {
500 return;
501 }
502 self.collect_host_and_slotted_rules();
503 self.collect_rules_from_containing_shadow_tree();
504 self.collect_document_author_rules();
505 self.collect_style_attribute();
506 self.collect_part_rules_from_outer_trees();
507 self.collect_animation_rules();
508 }
509}