1use crate::applicable_declarations::{
8 ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
9};
10use crate::computed_value_flags::ComputedValueFlags;
11use crate::context::{CascadeInputs, QuirksMode};
12use crate::custom_properties::ComputedCustomProperties;
13use crate::custom_properties::{parse_name, SpecifiedValue};
14use crate::derives::*;
15use crate::device::Device;
16use crate::dom::TElement;
17#[cfg(feature = "gecko")]
18use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
19use crate::invalidation::element::invalidation_map::{
20 note_selector_for_invalidation, AdditionalRelativeSelectorInvalidationMap, Dependency,
21 DependencyInvalidationKind, InvalidationMap, ScopeDependencyInvalidationKind,
22};
23use crate::invalidation::media_queries::{
24 EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
25};
26use crate::invalidation::stylesheets::{RuleChangeKind, StylesheetInvalidationSet};
27#[cfg(feature = "gecko")]
28use crate::properties::StyleBuilder;
29use crate::properties::{
30 self, AnimationDeclarations, CascadeMode, ComputedValues, FirstLineReparenting,
31 PropertyDeclarationBlock,
32};
33use crate::properties_and_values::registry::{
34 PropertyRegistration, PropertyRegistrationData, ScriptRegistry as CustomPropertyScriptRegistry,
35};
36use crate::properties_and_values::rule::{Inherits, PropertyRegistrationError, PropertyRuleName};
37use crate::properties_and_values::syntax::Descriptor;
38use crate::rule_cache::{RuleCache, RuleCacheConditions};
39use crate::rule_collector::RuleCollector;
40use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
41use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
42use crate::selector_parser::{NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl};
43use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
44use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
45use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
46use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
47use crate::stylesheets::container_rule::ContainerCondition;
48use crate::stylesheets::import_rule::ImportLayer;
49use crate::stylesheets::keyframes_rule::KeyframesAnimation;
50use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
51use crate::stylesheets::scope_rule::{
52 collect_scope_roots, element_is_outside_of_scope, scope_selector_list_is_trivial,
53 ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget,
54};
55use crate::stylesheets::UrlExtraData;
56use crate::stylesheets::{
57 CounterStyleRule, CssRule, CssRuleRef, EffectiveRulesIterator, FontFaceRule,
58 FontFeatureValuesRule, FontPaletteValuesRule, Origin, OriginSet, PagePseudoClassFlags,
59 PageRule, PerOrigin, PerOriginIter, PositionTryRule, StylesheetContents, StylesheetInDocument,
60};
61use crate::stylesheets::{CustomMediaEvaluator, CustomMediaMap};
62#[cfg(feature = "gecko")]
63use crate::values::specified::position::PositionTryFallbacksItem;
64use crate::values::specified::position::PositionTryFallbacksTryTactic;
65use crate::values::{computed, AtomIdent, Parser, SourceLocation};
66use crate::AllocErr;
67use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
68use cssparser::ParserInput;
69use dom::{DocumentState, ElementState};
70#[cfg(feature = "gecko")]
71use malloc_size_of::MallocUnconditionalShallowSizeOf;
72use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
73use rustc_hash::FxHashMap;
74use selectors::attr::{CaseSensitivity, NamespaceConstraint};
75use selectors::bloom::BloomFilter;
76use selectors::matching::{
77 matches_selector, selector_may_match, MatchingContext, MatchingMode, NeedsSelectorFlags,
78 SelectorCaches,
79};
80use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
81use selectors::parser::{
82 AncestorHashes, Combinator, Component, MatchesFeaturelessHost, Selector, SelectorIter,
83 SelectorList,
84};
85use selectors::visitor::{SelectorListKind, SelectorVisitor};
86use servo_arc::{Arc, ArcBorrow, ThinArc};
87use smallvec::SmallVec;
88use std::cmp::Ordering;
89use std::hash::{Hash, Hasher};
90use std::mem;
91use std::sync::{LazyLock, Mutex};
92
93#[cfg(feature = "servo")]
95pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
96
97#[cfg(feature = "gecko")]
99pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
100
101#[derive(Debug, Clone)]
102struct StylesheetContentsPtr(Arc<StylesheetContents>);
103
104impl PartialEq for StylesheetContentsPtr {
105 #[inline]
106 fn eq(&self, other: &Self) -> bool {
107 Arc::ptr_eq(&self.0, &other.0)
108 }
109}
110
111impl Eq for StylesheetContentsPtr {}
112
113impl Hash for StylesheetContentsPtr {
114 fn hash<H: Hasher>(&self, state: &mut H) {
115 let contents: &StylesheetContents = &*self.0;
116 (contents as *const StylesheetContents).hash(state)
117 }
118}
119
120type StyleSheetContentList = Vec<StylesheetContentsPtr>;
121
122#[derive(Default, Debug, MallocSizeOf)]
124pub struct CascadeDataDifference {
125 pub changed_position_try_names: PrecomputedHashSet<Atom>,
127}
128
129impl CascadeDataDifference {
130 pub fn merge_with(&mut self, other: Self) {
132 self.changed_position_try_names
133 .extend(other.changed_position_try_names.into_iter())
134 }
135
136 pub fn is_empty(&self) -> bool {
138 self.changed_position_try_names.is_empty()
139 }
140
141 fn update(&mut self, old_data: &PositionTryMap, new_data: &PositionTryMap) {
142 let mut any_different_key = false;
143 let different_len = old_data.len() != new_data.len();
144 for (name, rules) in old_data.iter() {
145 let changed = match new_data.get(name) {
146 Some(new_rule) => !Arc::ptr_eq(&rules.last().unwrap().0, new_rule),
147 None => {
148 any_different_key = true;
149 true
150 },
151 };
152 if changed {
153 self.changed_position_try_names.insert(name.clone());
154 }
155 }
156
157 if any_different_key || different_len {
158 for name in new_data.keys() {
159 if !old_data.contains_key(name) {
161 self.changed_position_try_names.insert(name.clone());
162 }
163 }
164 }
165 }
166}
167
168#[derive(Debug, Hash, Default, PartialEq, Eq)]
170struct CascadeDataCacheKey {
171 media_query_results: Vec<MediaListKey>,
172 contents: StyleSheetContentList,
173}
174
175unsafe impl Send for CascadeDataCacheKey {}
176unsafe impl Sync for CascadeDataCacheKey {}
177
178trait CascadeDataCacheEntry: Sized {
179 fn rebuild<S>(
182 device: &Device,
183 quirks_mode: QuirksMode,
184 collection: SheetCollectionFlusher<S>,
185 guard: &SharedRwLockReadGuard,
186 old_entry: &Self,
187 difference: &mut CascadeDataDifference,
188 ) -> Result<Arc<Self>, AllocErr>
189 where
190 S: StylesheetInDocument + PartialEq + 'static;
191 #[cfg(feature = "gecko")]
193 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
194}
195
196struct CascadeDataCache<Entry> {
197 entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
198}
199
200impl<Entry> CascadeDataCache<Entry>
201where
202 Entry: CascadeDataCacheEntry,
203{
204 fn new() -> Self {
205 Self {
206 entries: Default::default(),
207 }
208 }
209
210 fn len(&self) -> usize {
211 self.entries.len()
212 }
213
214 fn lookup<'a, S>(
219 &'a mut self,
220 device: &Device,
221 quirks_mode: QuirksMode,
222 collection: SheetCollectionFlusher<S>,
223 guard: &SharedRwLockReadGuard,
224 old_entry: &Entry,
225 difference: &mut CascadeDataDifference,
226 ) -> Result<Option<Arc<Entry>>, AllocErr>
227 where
228 S: StylesheetInDocument + PartialEq + 'static,
229 {
230 use std::collections::hash_map::Entry as HashMapEntry;
231 debug!("StyleSheetCache::lookup({})", self.len());
232
233 if !collection.dirty() {
234 return Ok(None);
235 }
236
237 let mut key = CascadeDataCacheKey::default();
238 let mut custom_media_map = CustomMediaMap::default();
239 for sheet in collection.sheets() {
240 CascadeData::collect_applicable_media_query_results_into(
241 device,
242 sheet,
243 guard,
244 &mut key.media_query_results,
245 &mut key.contents,
246 &mut custom_media_map,
247 )
248 }
249
250 let new_entry;
251 match self.entries.entry(key) {
252 HashMapEntry::Vacant(e) => {
253 debug!("> Picking the slow path (not in the cache)");
254 new_entry = Entry::rebuild(
255 device,
256 quirks_mode,
257 collection,
258 guard,
259 old_entry,
260 difference,
261 )?;
262 e.insert(new_entry.clone());
263 },
264 HashMapEntry::Occupied(mut e) => {
265 if !std::ptr::eq(&**e.get(), old_entry) {
269 if log_enabled!(log::Level::Debug) {
270 debug!("cache hit for:");
271 for sheet in collection.sheets() {
272 debug!(" > {:?}", sheet);
273 }
274 }
275 collection.each(|_, _, _| true);
278 return Ok(Some(e.get().clone()));
279 }
280
281 debug!("> Picking the slow path due to same entry as old");
282 new_entry = Entry::rebuild(
283 device,
284 quirks_mode,
285 collection,
286 guard,
287 old_entry,
288 difference,
289 )?;
290 e.insert(new_entry.clone());
291 },
292 }
293
294 Ok(Some(new_entry))
295 }
296
297 fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
305 let mut unused = SmallVec::new();
306 self.entries.retain(|_key, value| {
307 if !value.is_unique() {
311 return true;
312 }
313 unused.push(value.clone());
314 false
315 });
316 unused
317 }
318
319 fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
320 mem::take(&mut self.entries)
321 }
322
323 #[cfg(feature = "gecko")]
324 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
325 sizes.mOther += self.entries.shallow_size_of(ops);
326 for (_key, arc) in self.entries.iter() {
327 sizes.mOther += arc.unconditional_shallow_size_of(ops);
330 arc.add_size_of(ops, sizes);
331 }
332 }
333}
334
335#[cfg(feature = "gecko")]
337pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
338 UA_CASCADE_DATA_CACHE
339 .lock()
340 .unwrap()
341 .add_size_of(ops, sizes);
342}
343
344static UA_CASCADE_DATA_CACHE: LazyLock<Mutex<UserAgentCascadeDataCache>> =
346 LazyLock::new(|| Mutex::new(UserAgentCascadeDataCache::new()));
347
348impl CascadeDataCacheEntry for UserAgentCascadeData {
349 fn rebuild<S>(
350 device: &Device,
351 quirks_mode: QuirksMode,
352 collection: SheetCollectionFlusher<S>,
353 guard: &SharedRwLockReadGuard,
354 old: &Self,
355 difference: &mut CascadeDataDifference,
356 ) -> Result<Arc<Self>, AllocErr>
357 where
358 S: StylesheetInDocument + PartialEq + 'static,
359 {
360 let mut new_data = servo_arc::UniqueArc::new(Self {
363 cascade_data: CascadeData::new(),
364 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
365 });
366
367 for (index, sheet) in collection.sheets().enumerate() {
368 let new_data = &mut *new_data;
369 new_data.cascade_data.add_stylesheet(
370 device,
371 quirks_mode,
372 sheet,
373 index,
374 guard,
375 SheetRebuildKind::Full,
376 Some(&mut new_data.precomputed_pseudo_element_decls),
377 None,
378 )?;
379 }
380
381 new_data.cascade_data.did_finish_rebuild();
382 difference.update(
383 &old.cascade_data.extra_data.position_try_rules,
384 &new_data.cascade_data.extra_data.position_try_rules,
385 );
386
387 Ok(new_data.shareable())
388 }
389
390 #[cfg(feature = "gecko")]
391 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
392 self.cascade_data.add_size_of(ops, sizes);
393 sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
394 }
395}
396
397type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
398
399type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
400
401#[derive(Default)]
402struct UserAgentCascadeData {
403 cascade_data: CascadeData,
404
405 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
412}
413
414static EMPTY_UA_CASCADE_DATA: LazyLock<Arc<UserAgentCascadeData>> = LazyLock::new(|| {
416 let arc = Arc::new(UserAgentCascadeData::default());
417 arc.mark_as_intentionally_leaked();
418 arc
419});
420
421#[derive(MallocSizeOf)]
424pub struct DocumentCascadeData {
425 #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
426 user_agent: Arc<UserAgentCascadeData>,
427 user: CascadeData,
428 author: CascadeData,
429 per_origin: PerOrigin<()>,
430}
431
432impl Default for DocumentCascadeData {
433 fn default() -> Self {
434 Self {
435 user_agent: EMPTY_UA_CASCADE_DATA.clone(),
436 user: Default::default(),
437 author: Default::default(),
438 per_origin: Default::default(),
439 }
440 }
441}
442
443pub struct DocumentCascadeDataIter<'a> {
445 iter: PerOriginIter<'a, ()>,
446 cascade_data: &'a DocumentCascadeData,
447}
448
449impl<'a> Iterator for DocumentCascadeDataIter<'a> {
450 type Item = (&'a CascadeData, Origin);
451
452 fn next(&mut self) -> Option<Self::Item> {
453 let (_, origin) = self.iter.next()?;
454 Some((self.cascade_data.borrow_for_origin(origin), origin))
455 }
456}
457
458impl DocumentCascadeData {
459 #[inline]
461 pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
462 match origin {
463 Origin::UserAgent => &self.user_agent.cascade_data,
464 Origin::Author => &self.author,
465 Origin::User => &self.user,
466 }
467 }
468
469 fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
470 DocumentCascadeDataIter {
471 iter: self.per_origin.iter_origins(),
472 cascade_data: self,
473 }
474 }
475
476 fn iter_origins_rev(&self) -> DocumentCascadeDataIter<'_> {
477 DocumentCascadeDataIter {
478 iter: self.per_origin.iter_origins_rev(),
479 cascade_data: self,
480 }
481 }
482
483 fn custom_media_for_sheet(
484 &self,
485 s: &StylistSheet,
486 guard: &SharedRwLockReadGuard,
487 ) -> &CustomMediaMap {
488 let origin = s.contents(guard).origin;
489 &self.borrow_for_origin(origin).custom_media
490 }
491
492 fn rebuild<'a, S>(
496 &mut self,
497 device: &Device,
498 quirks_mode: QuirksMode,
499 mut flusher: DocumentStylesheetFlusher<'a, S>,
500 guards: &StylesheetGuards,
501 difference: &mut CascadeDataDifference,
502 ) -> Result<(), AllocErr>
503 where
504 S: StylesheetInDocument + PartialEq + 'static,
505 {
506 {
508 let origin_flusher = flusher.flush_origin(Origin::UserAgent);
509 if origin_flusher.dirty() {
512 let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
513 let new_data = ua_cache.lookup(
514 device,
515 quirks_mode,
516 origin_flusher,
517 guards.ua_or_user,
518 &self.user_agent,
519 difference,
520 )?;
521 if let Some(new_data) = new_data {
522 self.user_agent = new_data;
523 }
524 let _unused_entries = ua_cache.take_unused();
525 std::mem::drop(ua_cache);
527 }
528 }
529
530 self.user.rebuild(
532 device,
533 quirks_mode,
534 flusher.flush_origin(Origin::User),
535 guards.ua_or_user,
536 difference,
537 )?;
538
539 self.author.rebuild(
541 device,
542 quirks_mode,
543 flusher.flush_origin(Origin::Author),
544 guards.author,
545 difference,
546 )?;
547
548 Ok(())
549 }
550
551 #[cfg(feature = "gecko")]
553 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
554 self.user.add_size_of(ops, sizes);
555 self.author.add_size_of(ops, sizes);
556 }
557}
558
559#[allow(missing_docs)]
563#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
564pub enum AuthorStylesEnabled {
565 Yes,
566 No,
567}
568
569#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
572#[derive(Deref, DerefMut)]
573struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
574unsafe impl Sync for StylistStylesheetSet {}
576
577impl StylistStylesheetSet {
578 fn new() -> Self {
579 StylistStylesheetSet(DocumentStylesheetSet::new())
580 }
581}
582
583#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
591pub struct Stylist {
592 device: Device,
605
606 stylesheets: StylistStylesheetSet,
608
609 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "XXX: how to handle this?")]
611 author_data_cache: CascadeDataCache<CascadeData>,
612
613 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
615 quirks_mode: QuirksMode,
616
617 cascade_data: DocumentCascadeData,
621
622 author_styles_enabled: AuthorStylesEnabled,
624
625 rule_tree: RuleTree,
627
628 script_custom_properties: CustomPropertyScriptRegistry,
631
632 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
634 initial_values_for_custom_properties: ComputedCustomProperties,
635
636 initial_values_for_custom_properties_flags: ComputedValueFlags,
638
639 num_rebuilds: usize,
641}
642
643#[derive(Clone, Copy, PartialEq)]
645pub enum RuleInclusion {
646 All,
649 DefaultOnly,
652}
653
654#[cfg(feature = "gecko")]
655impl From<StyleRuleInclusion> for RuleInclusion {
656 fn from(value: StyleRuleInclusion) -> Self {
657 match value {
658 StyleRuleInclusion::All => RuleInclusion::All,
659 StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
660 }
661 }
662}
663
664#[derive(Clone, Copy, Eq, PartialEq)]
669enum ScopeMatchesShadowHost {
670 NotApplicable,
671 No,
672 Yes,
673}
674
675impl Default for ScopeMatchesShadowHost {
676 fn default() -> Self {
677 Self::NotApplicable
678 }
679}
680
681impl ScopeMatchesShadowHost {
682 fn nest_for_scope(&mut self, matches_shadow_host: bool) {
683 match *self {
684 Self::NotApplicable => {
685 *self = if matches_shadow_host {
687 Self::Yes
688 } else {
689 Self::No
690 };
691 },
692 Self::Yes if !matches_shadow_host => {
693 *self = Self::No;
695 },
696 _ => (),
697 }
698 }
699}
700
701#[derive(Copy, Clone)]
708enum NestedDeclarationsContext {
709 Style,
710 Scope,
711}
712
713struct ContainingScopeRuleState {
715 id: ScopeConditionId,
716 inner_dependencies: Vec<Dependency>,
717 matches_shadow_host: ScopeMatchesShadowHost,
718}
719
720impl Default for ContainingScopeRuleState {
721 fn default() -> Self {
722 Self {
723 id: ScopeConditionId::none(),
724 inner_dependencies: Vec::new(),
725 matches_shadow_host: Default::default(),
726 }
727 }
728}
729
730impl ContainingScopeRuleState {
731 fn save(&self) -> SavedContainingScopeRuleState {
732 SavedContainingScopeRuleState {
733 id: self.id,
734 matches_shadow_host: self.matches_shadow_host,
735 inner_dependencies_len: self.inner_dependencies.len(),
736 }
737 }
738
739 fn restore(
740 &mut self,
741 saved: &SavedContainingScopeRuleState,
742 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
743 debug_assert!(self.inner_dependencies.len() >= saved.inner_dependencies_len);
744
745 if self.id == saved.id {
746 return None;
747 }
748
749 let scope_id = self.id;
750 let inner_deps = self
751 .inner_dependencies
752 .drain(saved.inner_dependencies_len..)
753 .collect();
754
755 self.id = saved.id;
756 self.matches_shadow_host = saved.matches_shadow_host;
757
758 Some((inner_deps, scope_id))
759 }
760}
761
762struct SavedContainingScopeRuleState {
763 id: ScopeConditionId,
764 matches_shadow_host: ScopeMatchesShadowHost,
765 inner_dependencies_len: usize,
766}
767
768struct ContainingRuleState {
771 layer_name: LayerName,
772 layer_id: LayerId,
773 container_condition_id: ContainerConditionId,
774 in_starting_style: bool,
775 containing_scope_rule_state: ContainingScopeRuleState,
776 ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
777 nested_declarations_context: NestedDeclarationsContext,
778}
779
780impl Default for ContainingRuleState {
781 fn default() -> Self {
782 Self {
783 layer_name: LayerName::new_empty(),
784 layer_id: LayerId::root(),
785 container_condition_id: ContainerConditionId::none(),
786 in_starting_style: false,
787 ancestor_selector_lists: Default::default(),
788 containing_scope_rule_state: Default::default(),
789 nested_declarations_context: NestedDeclarationsContext::Style,
790 }
791 }
792}
793
794struct SavedContainingRuleState {
795 ancestor_selector_lists_len: usize,
796 layer_name_len: usize,
797 layer_id: LayerId,
798 container_condition_id: ContainerConditionId,
799 in_starting_style: bool,
800 saved_containing_scope_rule_state: SavedContainingScopeRuleState,
801 nested_declarations_context: NestedDeclarationsContext,
802}
803
804impl ContainingRuleState {
805 fn save(&self) -> SavedContainingRuleState {
806 SavedContainingRuleState {
807 ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
808 layer_name_len: self.layer_name.0.len(),
809 layer_id: self.layer_id,
810 container_condition_id: self.container_condition_id,
811 in_starting_style: self.in_starting_style,
812 saved_containing_scope_rule_state: self.containing_scope_rule_state.save(),
813 nested_declarations_context: self.nested_declarations_context,
814 }
815 }
816
817 fn restore(
818 &mut self,
819 saved: &SavedContainingRuleState,
820 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
821 debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
822 debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
823
824 self.ancestor_selector_lists
825 .truncate(saved.ancestor_selector_lists_len);
826 self.layer_name.0.truncate(saved.layer_name_len);
827 self.layer_id = saved.layer_id;
828 self.container_condition_id = saved.container_condition_id;
829 self.in_starting_style = saved.in_starting_style;
830 self.nested_declarations_context = saved.nested_declarations_context;
831
832 self.containing_scope_rule_state
833 .restore(&saved.saved_containing_scope_rule_state)
834 }
835
836 fn scope_is_effective(&self) -> bool {
837 self.containing_scope_rule_state.id != ScopeConditionId::none()
838 }
839}
840
841type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
842
843impl Stylist {
844 #[inline]
848 pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
849 Self {
850 device,
851 quirks_mode,
852 stylesheets: StylistStylesheetSet::new(),
853 author_data_cache: CascadeDataCache::new(),
854 cascade_data: Default::default(),
855 author_styles_enabled: AuthorStylesEnabled::Yes,
856 rule_tree: RuleTree::new(),
857 script_custom_properties: Default::default(),
858 initial_values_for_custom_properties: Default::default(),
859 initial_values_for_custom_properties_flags: Default::default(),
860 num_rebuilds: 0,
861 }
862 }
863
864 #[inline]
866 pub fn cascade_data(&self) -> &DocumentCascadeData {
867 &self.cascade_data
868 }
869
870 #[inline]
872 pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
873 self.author_styles_enabled
874 }
875
876 #[inline]
878 pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
879 self.cascade_data.iter_origins()
880 }
881
882 pub fn remove_unique_author_data_cache_entries(&mut self) {
885 self.author_data_cache.take_unused();
886 }
887
888 pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyRegistrationData {
891 if let Some(registration) = self.custom_property_script_registry().get(name) {
892 return ®istration.data;
893 }
894 for (data, _) in self.iter_origins() {
895 if let Some(registration) = data.custom_property_registrations.get(name) {
896 return ®istration.data;
897 }
898 }
899 PropertyRegistrationData::unregistered()
900 }
901
902 pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
904 &self.initial_values_for_custom_properties
905 }
906
907 pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
909 self.initial_values_for_custom_properties_flags
910 }
911
912 pub fn rebuild_initial_values_for_custom_properties(&mut self) {
915 let mut initial_values = ComputedCustomProperties::default();
916 let initial_values_flags;
917 {
918 let mut seen_names = PrecomputedHashSet::default();
919 let mut rule_cache_conditions = RuleCacheConditions::default();
920 let context = computed::Context::new_for_initial_at_property_value(
921 self,
922 &mut rule_cache_conditions,
923 );
924
925 for (k, v) in self.custom_property_script_registry().properties().iter() {
926 seen_names.insert(k.clone());
927 let Ok(value) = v.compute_initial_value(&context) else {
928 continue;
929 };
930 let map = if v.inherits() {
931 &mut initial_values.inherited
932 } else {
933 &mut initial_values.non_inherited
934 };
935 map.insert(k, value);
936 }
937 for (data, _) in self.iter_origins() {
938 for (k, v) in data.custom_property_registrations.iter() {
939 if seen_names.insert(k.clone()) {
940 let last_value = &v.last().unwrap().0;
941 let Ok(value) = last_value.compute_initial_value(&context) else {
942 continue;
943 };
944 let map = if last_value.inherits() {
945 &mut initial_values.inherited
946 } else {
947 &mut initial_values.non_inherited
948 };
949 map.insert(k, value);
950 }
951 }
952 }
953 initial_values_flags = context.builder.flags();
954 }
955 self.initial_values_for_custom_properties_flags = initial_values_flags;
956 self.initial_values_for_custom_properties = initial_values;
957 }
958
959 pub fn rebuild_author_data<S>(
961 &mut self,
962 old_data: &CascadeData,
963 collection: SheetCollectionFlusher<S>,
964 guard: &SharedRwLockReadGuard,
965 difference: &mut CascadeDataDifference,
966 ) -> Result<Option<Arc<CascadeData>>, AllocErr>
967 where
968 S: StylesheetInDocument + PartialEq + 'static,
969 {
970 self.author_data_cache.lookup(
971 &self.device,
972 self.quirks_mode,
973 collection,
974 guard,
975 old_data,
976 difference,
977 )
978 }
979
980 #[inline]
982 pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
983 ExtraStyleDataIterator(self.cascade_data.iter_origins())
984 }
985
986 #[inline]
988 pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
989 ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
990 }
991
992 pub fn num_selectors(&self) -> usize {
994 self.cascade_data
995 .iter_origins()
996 .map(|(d, _)| d.num_selectors)
997 .sum()
998 }
999
1000 pub fn num_declarations(&self) -> usize {
1002 self.cascade_data
1003 .iter_origins()
1004 .map(|(d, _)| d.num_declarations)
1005 .sum()
1006 }
1007
1008 pub fn num_rebuilds(&self) -> usize {
1010 self.num_rebuilds
1011 }
1012
1013 pub fn num_revalidation_selectors(&self) -> usize {
1015 self.cascade_data
1016 .iter_origins()
1017 .map(|(data, _)| data.selectors_for_cache_revalidation.len())
1018 .sum()
1019 }
1020
1021 pub fn num_invalidations(&self) -> usize {
1023 self.cascade_data
1024 .iter_origins()
1025 .map(|(data, _)| {
1026 data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
1027 })
1028 .sum()
1029 }
1030
1031 pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
1034 self.cascade_data
1035 .iter_origins()
1036 .any(|(d, _)| d.document_state_dependencies.intersects(state))
1037 }
1038
1039 pub fn flush(&mut self, guards: &StylesheetGuards) -> StylesheetInvalidationSet {
1042 if !self.stylesheets.has_changed() {
1043 return Default::default();
1044 }
1045
1046 self.num_rebuilds += 1;
1047
1048 let (flusher, mut invalidations) = self.stylesheets.flush();
1049
1050 self.cascade_data
1051 .rebuild(
1052 &self.device,
1053 self.quirks_mode,
1054 flusher,
1055 guards,
1056 &mut invalidations.cascade_data_difference,
1057 )
1058 .unwrap_or_else(|_| {
1059 warn!("OOM in Stylist::flush");
1060 });
1061
1062 self.rebuild_initial_values_for_custom_properties();
1063 invalidations
1064 }
1065
1066 pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
1072 self.stylesheets.force_dirty(origins)
1073 }
1074
1075 pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
1077 self.author_styles_enabled = enabled;
1078 }
1079
1080 pub fn stylesheets_have_changed(&self) -> bool {
1082 self.stylesheets.has_changed()
1083 }
1084
1085 pub fn insert_stylesheet_before(
1087 &mut self,
1088 sheet: StylistSheet,
1089 before_sheet: StylistSheet,
1090 guard: &SharedRwLockReadGuard,
1091 ) {
1092 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1093 self.stylesheets.insert_stylesheet_before(
1094 Some(&self.device),
1095 custom_media,
1096 sheet,
1097 before_sheet,
1098 guard,
1099 )
1100 }
1101
1102 pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1104 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1105 self.stylesheets
1106 .append_stylesheet(Some(&self.device), custom_media, sheet, guard)
1107 }
1108
1109 pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1111 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1112 self.stylesheets
1113 .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
1114 }
1115
1116 pub fn rule_changed(
1118 &mut self,
1119 sheet: &StylistSheet,
1120 rule: &CssRule,
1121 guard: &SharedRwLockReadGuard,
1122 change_kind: RuleChangeKind,
1123 ancestors: &[CssRuleRef],
1124 ) {
1125 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1126 self.stylesheets.rule_changed(
1127 Some(&self.device),
1128 custom_media,
1129 sheet,
1130 rule,
1131 guard,
1132 change_kind,
1133 ancestors,
1134 )
1135 }
1136
1137 #[inline]
1139 pub fn sheet_count(&self, origin: Origin) -> usize {
1140 self.stylesheets.sheet_count(origin)
1141 }
1142
1143 #[inline]
1145 pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
1146 self.stylesheets.get(origin, index)
1147 }
1148
1149 pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
1152 where
1153 E: TElement,
1154 F: FnMut(&CascadeData) -> bool,
1155 {
1156 if f(&self.cascade_data.user_agent.cascade_data) {
1157 return true;
1158 }
1159
1160 let mut maybe = false;
1161
1162 let doc_author_rules_apply =
1163 element.each_applicable_non_document_style_rule_data(|data, _| {
1164 maybe = maybe || f(&*data);
1165 });
1166
1167 if maybe || f(&self.cascade_data.user) {
1168 return true;
1169 }
1170
1171 doc_author_rules_apply && f(&self.cascade_data.author)
1172 }
1173
1174 pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1176 where
1177 E: TElement + 'a,
1178 F: FnMut(&'a CascadeData, Option<E>),
1179 {
1180 f(&self.cascade_data.user_agent.cascade_data, None);
1181 element.each_applicable_non_document_style_rule_data(|data, scope| {
1182 f(data, Some(scope));
1183 });
1184 f(&self.cascade_data.user, None);
1185 f(&self.cascade_data.author, None);
1186 }
1187
1188 pub fn precomputed_values_for_pseudo<E>(
1191 &self,
1192 guards: &StylesheetGuards,
1193 pseudo: &PseudoElement,
1194 parent: Option<&ComputedValues>,
1195 ) -> Arc<ComputedValues>
1196 where
1197 E: TElement,
1198 {
1199 debug_assert!(pseudo.is_precomputed());
1200
1201 let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1202
1203 self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1204 }
1205
1206 pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1212 &self,
1213 guards: &StylesheetGuards,
1214 pseudo: &PseudoElement,
1215 parent: Option<&ComputedValues>,
1216 rules: StrongRuleNode,
1217 ) -> Arc<ComputedValues>
1218 where
1219 E: TElement,
1220 {
1221 self.compute_pseudo_element_style_with_inputs::<E>(
1222 CascadeInputs {
1223 rules: Some(rules),
1224 visited_rules: None,
1225 flags: Default::default(),
1226 },
1227 pseudo,
1228 guards,
1229 parent,
1230 None,
1231 )
1232 }
1233
1234 pub fn rule_node_for_precomputed_pseudo(
1240 &self,
1241 guards: &StylesheetGuards,
1242 pseudo: &PseudoElement,
1243 mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1244 ) -> StrongRuleNode {
1245 let mut declarations_with_extra;
1246 let declarations = match self
1247 .cascade_data
1248 .user_agent
1249 .precomputed_pseudo_element_decls
1250 .get(pseudo)
1251 {
1252 Some(declarations) => {
1253 if !extra_declarations.is_empty() {
1254 declarations_with_extra = declarations.clone();
1255 declarations_with_extra.append(&mut extra_declarations);
1256 &*declarations_with_extra
1257 } else {
1258 &**declarations
1259 }
1260 },
1261 None => &[],
1262 };
1263
1264 self.rule_tree.insert_ordered_rules_with_important(
1265 declarations.into_iter().map(|a| a.clone().for_rule_tree()),
1266 guards,
1267 )
1268 }
1269
1270 #[cfg(feature = "servo")]
1275 pub fn style_for_anonymous<E>(
1276 &self,
1277 guards: &StylesheetGuards,
1278 pseudo: &PseudoElement,
1279 parent_style: &ComputedValues,
1280 ) -> Arc<ComputedValues>
1281 where
1282 E: TElement,
1283 {
1284 self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1285 }
1286
1287 pub fn lazily_compute_pseudo_element_style<E>(
1295 &self,
1296 guards: &StylesheetGuards,
1297 element: E,
1298 pseudo: &PseudoElement,
1299 rule_inclusion: RuleInclusion,
1300 originating_element_style: &ComputedValues,
1301 is_probe: bool,
1302 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1303 ) -> Option<Arc<ComputedValues>>
1304 where
1305 E: TElement,
1306 {
1307 let cascade_inputs = self.lazy_pseudo_rules(
1308 guards,
1309 element,
1310 originating_element_style,
1311 pseudo,
1312 is_probe,
1313 rule_inclusion,
1314 matching_fn,
1315 )?;
1316
1317 Some(self.compute_pseudo_element_style_with_inputs(
1318 cascade_inputs,
1319 pseudo,
1320 guards,
1321 Some(originating_element_style),
1322 Some(element),
1323 ))
1324 }
1325
1326 pub fn compute_pseudo_element_style_with_inputs<E>(
1331 &self,
1332 inputs: CascadeInputs,
1333 pseudo: &PseudoElement,
1334 guards: &StylesheetGuards,
1335 parent_style: Option<&ComputedValues>,
1336 element: Option<E>,
1337 ) -> Arc<ComputedValues>
1338 where
1339 E: TElement,
1340 {
1341 self.cascade_style_and_visited(
1354 element,
1355 Some(pseudo),
1356 inputs,
1357 guards,
1358 parent_style,
1359 parent_style,
1360 FirstLineReparenting::No,
1361 &PositionTryFallbacksTryTactic::default(),
1362 None,
1363 &mut RuleCacheConditions::default(),
1364 )
1365 }
1366
1367 #[cfg(feature = "gecko")]
1369 pub fn resolve_position_try<E>(
1370 &self,
1371 style: &ComputedValues,
1372 guards: &StylesheetGuards,
1373 element: E,
1374 fallback_item: &PositionTryFallbacksItem,
1375 ) -> Option<Arc<ComputedValues>>
1376 where
1377 E: TElement,
1378 {
1379 let name_and_try_tactic = match *fallback_item {
1380 PositionTryFallbacksItem::PositionArea(area) => {
1381 let mut builder =
1385 StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
1386 builder.rules = style.rules.clone();
1387 builder.mutate_position().set_position_area(area);
1388 return Some(builder.build());
1389 },
1390 PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
1391 name_and_try_tactic
1392 },
1393 };
1394
1395 let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
1396 Some(self.lookup_position_try(&name_and_try_tactic.ident.0, element)?)
1397 } else {
1398 None
1399 };
1400 let fallback_block = fallback_rule
1401 .as_ref()
1402 .map(|r| &r.read_with(guards.author).block);
1403 let pseudo = style
1404 .pseudo()
1405 .or_else(|| element.implemented_pseudo_element());
1406 let inputs = {
1407 let mut inputs = CascadeInputs::new_from_style(style);
1408 inputs.visited_rules = None;
1410 let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
1411 let mut important_rules_changed = false;
1412 if let Some(fallback_block) = fallback_block {
1413 let new_rules = self.rule_tree.update_rule_at_level(
1414 CascadeLevel::PositionFallback,
1415 LayerOrder::root(),
1416 Some(fallback_block.borrow_arc()),
1417 rules,
1418 guards,
1419 &mut important_rules_changed,
1420 );
1421 if new_rules.is_some() {
1422 inputs.rules = new_rules;
1423 } else {
1424 }
1428 }
1429 inputs
1430 };
1431 crate::style_resolver::with_default_parent_styles(
1432 element,
1433 |parent_style, layout_parent_style| {
1434 Some(self.cascade_style_and_visited(
1435 Some(element),
1436 pseudo.as_ref(),
1437 inputs,
1438 guards,
1439 parent_style,
1440 layout_parent_style,
1441 FirstLineReparenting::No,
1442 &name_and_try_tactic.try_tactic,
1443 None,
1444 &mut RuleCacheConditions::default(),
1445 ))
1446 },
1447 )
1448 }
1449
1450 pub fn cascade_style_and_visited<E>(
1463 &self,
1464 element: Option<E>,
1465 pseudo: Option<&PseudoElement>,
1466 inputs: CascadeInputs,
1467 guards: &StylesheetGuards,
1468 parent_style: Option<&ComputedValues>,
1469 layout_parent_style: Option<&ComputedValues>,
1470 first_line_reparenting: FirstLineReparenting,
1471 try_tactic: &PositionTryFallbacksTryTactic,
1472 rule_cache: Option<&RuleCache>,
1473 rule_cache_conditions: &mut RuleCacheConditions,
1474 ) -> Arc<ComputedValues>
1475 where
1476 E: TElement,
1477 {
1478 debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1479
1480 let visited_rules = match inputs.visited_rules.as_ref() {
1483 Some(rules) => Some(rules),
1484 None => {
1485 if parent_style.and_then(|s| s.visited_style()).is_some() {
1486 Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1487 } else {
1488 None
1489 }
1490 },
1491 };
1492
1493 let mut implemented_pseudo = None;
1494 properties::cascade::<E>(
1501 &self,
1502 pseudo.or_else(|| {
1503 implemented_pseudo = element.unwrap().implemented_pseudo_element();
1504 implemented_pseudo.as_ref()
1505 }),
1506 inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1507 guards,
1508 parent_style,
1509 layout_parent_style,
1510 first_line_reparenting,
1511 try_tactic,
1512 visited_rules,
1513 inputs.flags,
1514 rule_cache,
1515 rule_cache_conditions,
1516 element,
1517 )
1518 }
1519
1520 fn lazy_pseudo_rules<E>(
1525 &self,
1526 guards: &StylesheetGuards,
1527 element: E,
1528 originating_element_style: &ComputedValues,
1529 pseudo: &PseudoElement,
1530 is_probe: bool,
1531 rule_inclusion: RuleInclusion,
1532 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1533 ) -> Option<CascadeInputs>
1534 where
1535 E: TElement,
1536 {
1537 debug_assert!(pseudo.is_lazy());
1538
1539 let mut selector_caches = SelectorCaches::default();
1540 let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1543 NeedsSelectorFlags::No
1544 } else {
1545 NeedsSelectorFlags::Yes
1546 };
1547
1548 let mut declarations = ApplicableDeclarationList::new();
1549 let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1550 MatchingMode::ForStatelessPseudoElement,
1551 None,
1552 &mut selector_caches,
1553 self.quirks_mode,
1554 needs_selector_flags,
1555 MatchingForInvalidation::No,
1556 );
1557
1558 matching_context.pseudo_element_matching_fn = matching_fn;
1559 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1560
1561 self.push_applicable_declarations(
1562 element,
1563 Some(&pseudo),
1564 None,
1565 None,
1566 Default::default(),
1567 rule_inclusion,
1568 &mut declarations,
1569 &mut matching_context,
1570 );
1571
1572 if declarations.is_empty() && is_probe {
1573 return None;
1574 }
1575
1576 let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1577
1578 let mut visited_rules = None;
1579 if originating_element_style.visited_style().is_some() {
1580 let mut declarations = ApplicableDeclarationList::new();
1581 let mut selector_caches = SelectorCaches::default();
1582
1583 let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1584 MatchingMode::ForStatelessPseudoElement,
1585 None,
1586 &mut selector_caches,
1587 VisitedHandlingMode::RelevantLinkVisited,
1588 selectors::matching::IncludeStartingStyle::No,
1589 self.quirks_mode,
1590 needs_selector_flags,
1591 MatchingForInvalidation::No,
1592 );
1593 matching_context.pseudo_element_matching_fn = matching_fn;
1594 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1595
1596 self.push_applicable_declarations(
1597 element,
1598 Some(&pseudo),
1599 None,
1600 None,
1601 Default::default(),
1602 rule_inclusion,
1603 &mut declarations,
1604 &mut matching_context,
1605 );
1606 if !declarations.is_empty() {
1607 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1608 declarations.drain(..).map(|a| a.for_rule_tree()),
1609 guards,
1610 );
1611 if rule_node != *self.rule_tree.root() {
1612 visited_rules = Some(rule_node);
1613 }
1614 }
1615 }
1616
1617 Some(CascadeInputs {
1618 rules: Some(rules),
1619 visited_rules,
1620 flags: matching_context.extra_data.cascade_input_flags,
1621 })
1622 }
1623
1624 pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1635 self.device = device;
1636 self.media_features_change_changed_style(guards, &self.device)
1637 }
1638
1639 pub fn media_features_change_changed_style(
1643 &self,
1644 guards: &StylesheetGuards,
1645 device: &Device,
1646 ) -> OriginSet {
1647 debug!("Stylist::media_features_change_changed_style {:?}", device);
1648
1649 let mut origins = OriginSet::empty();
1650 let stylesheets = self.stylesheets.iter();
1651
1652 for (stylesheet, origin) in stylesheets {
1653 if origins.contains(origin.into()) {
1654 continue;
1655 }
1656
1657 let guard = guards.for_origin(origin);
1658 let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1659
1660 let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1661 stylesheet,
1662 guard,
1663 device,
1664 self.quirks_mode,
1665 );
1666
1667 if affected_changed {
1668 origins |= origin;
1669 }
1670 }
1671
1672 origins
1673 }
1674
1675 pub fn quirks_mode(&self) -> QuirksMode {
1677 self.quirks_mode
1678 }
1679
1680 pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1682 if self.quirks_mode == quirks_mode {
1683 return;
1684 }
1685 self.quirks_mode = quirks_mode;
1686 self.force_stylesheet_origins_dirty(OriginSet::all());
1687 }
1688
1689 pub fn push_applicable_declarations<E>(
1691 &self,
1692 element: E,
1693 pseudo_element: Option<&PseudoElement>,
1694 style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1695 smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1696 animation_declarations: AnimationDeclarations,
1697 rule_inclusion: RuleInclusion,
1698 applicable_declarations: &mut ApplicableDeclarationList,
1699 context: &mut MatchingContext<E::Impl>,
1700 ) where
1701 E: TElement,
1702 {
1703 let mut cur = element;
1704 let mut pseudos = SmallVec::new();
1705 if let Some(pseudo) = pseudo_element {
1706 pseudos.push(pseudo.clone());
1707 }
1708 while let Some(p) = cur.implemented_pseudo_element() {
1709 pseudos.push(p);
1710 let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
1711 break;
1712 };
1713 cur = parent_pseudo;
1714 }
1715 RuleCollector::new(
1716 self,
1717 element,
1718 pseudos,
1719 style_attribute,
1720 smil_override,
1721 animation_declarations,
1722 rule_inclusion,
1723 applicable_declarations,
1724 context,
1725 )
1726 .collect_all();
1727 }
1728
1729 #[inline]
1732 pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1733 where
1734 E: TElement,
1735 {
1736 match self.quirks_mode().classes_and_ids_case_sensitivity() {
1739 CaseSensitivity::AsciiCaseInsensitive => return true,
1740 CaseSensitivity::CaseSensitive => {},
1741 }
1742
1743 self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1744 }
1745
1746 #[inline]
1754 fn lookup_element_dependent_at_rule<'a, T, F, E>(
1755 &'a self,
1756 element: E,
1757 find_in: F,
1758 ) -> Option<&'a T>
1759 where
1760 E: TElement + 'a,
1761 F: Fn(&'a CascadeData) -> Option<&'a T>,
1762 {
1763 macro_rules! try_find_in {
1764 ($data:expr) => {
1765 if let Some(thing) = find_in(&$data) {
1766 return Some(thing);
1767 }
1768 };
1769 }
1770
1771 let mut result = None;
1772 let doc_rules_apply =
1773 element.each_applicable_non_document_style_rule_data(|data, _host| {
1774 if result.is_none() {
1775 result = find_in(data);
1776 }
1777 });
1778
1779 if result.is_some() {
1780 return result;
1781 }
1782
1783 if doc_rules_apply {
1784 try_find_in!(self.cascade_data.author);
1785 }
1786 try_find_in!(self.cascade_data.user);
1787 try_find_in!(self.cascade_data.user_agent.cascade_data);
1788
1789 None
1790 }
1791
1792 #[inline]
1794 pub fn lookup_keyframes<'a, E>(
1795 &'a self,
1796 name: &Atom,
1797 element: E,
1798 ) -> Option<&'a KeyframesAnimation>
1799 where
1800 E: TElement + 'a,
1801 {
1802 self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1803 }
1804
1805 #[inline]
1807 #[cfg(feature = "gecko")]
1808 fn lookup_position_try<'a, E>(
1809 &'a self,
1810 name: &Atom,
1811 element: E,
1812 ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1813 where
1814 E: TElement + 'a,
1815 {
1816 self.lookup_element_dependent_at_rule(element, |data| {
1817 data.extra_data.position_try_rules.get(name)
1818 })
1819 }
1820
1821 pub fn match_revalidation_selectors<E>(
1824 &self,
1825 element: E,
1826 bloom: Option<&BloomFilter>,
1827 selector_caches: &mut SelectorCaches,
1828 needs_selector_flags: NeedsSelectorFlags,
1829 ) -> RevalidationResult
1830 where
1831 E: TElement,
1832 {
1833 let mut matching_context = MatchingContext::new_for_revalidation(
1834 bloom,
1835 selector_caches,
1836 self.quirks_mode,
1837 needs_selector_flags,
1838 );
1839
1840 let mut result = RevalidationResult::default();
1846 let mut relevant_attributes = &mut result.relevant_attributes;
1847 let selectors_matched = &mut result.selectors_matched;
1848
1849 let matches_document_rules =
1850 element.each_applicable_non_document_style_rule_data(|data, host| {
1851 matching_context.with_shadow_host(Some(host), |matching_context| {
1852 data.selectors_for_cache_revalidation.lookup(
1853 element,
1854 self.quirks_mode,
1855 Some(&mut relevant_attributes),
1856 |selector_and_hashes| {
1857 selectors_matched.push(matches_selector(
1858 &selector_and_hashes.selector,
1859 selector_and_hashes.selector_offset,
1860 Some(&selector_and_hashes.hashes),
1861 &element,
1862 matching_context,
1863 ));
1864 true
1865 },
1866 );
1867 })
1868 });
1869
1870 for (data, origin) in self.cascade_data.iter_origins() {
1871 if origin == Origin::Author && !matches_document_rules {
1872 continue;
1873 }
1874
1875 data.selectors_for_cache_revalidation.lookup(
1876 element,
1877 self.quirks_mode,
1878 Some(&mut relevant_attributes),
1879 |selector_and_hashes| {
1880 selectors_matched.push(matches_selector(
1881 &selector_and_hashes.selector,
1882 selector_and_hashes.selector_offset,
1883 Some(&selector_and_hashes.hashes),
1884 &element,
1885 &mut matching_context,
1886 ));
1887 true
1888 },
1889 );
1890 }
1891
1892 result
1893 }
1894
1895 pub fn revalidate_scopes<E: TElement>(
1897 &self,
1898 element: &E,
1899 selector_caches: &mut SelectorCaches,
1900 needs_selector_flags: NeedsSelectorFlags,
1901 ) -> ScopeRevalidationResult {
1902 let mut matching_context = MatchingContext::new(
1903 MatchingMode::Normal,
1904 None,
1905 selector_caches,
1906 self.quirks_mode,
1907 needs_selector_flags,
1908 MatchingForInvalidation::No,
1909 );
1910
1911 let mut result = ScopeRevalidationResult::default();
1912 let matches_document_rules =
1913 element.each_applicable_non_document_style_rule_data(|data, host| {
1914 matching_context.with_shadow_host(Some(host), |matching_context| {
1915 data.revalidate_scopes(element, matching_context, &mut result);
1916 })
1917 });
1918
1919 for (data, origin) in self.cascade_data.iter_origins() {
1920 if origin == Origin::Author && !matches_document_rules {
1921 continue;
1922 }
1923
1924 data.revalidate_scopes(element, &mut matching_context, &mut result);
1925 }
1926
1927 result
1928 }
1929
1930 pub fn compute_for_declarations<E>(
1938 &self,
1939 guards: &StylesheetGuards,
1940 parent_style: &ComputedValues,
1941 declarations: Arc<Locked<PropertyDeclarationBlock>>,
1942 ) -> Arc<ComputedValues>
1943 where
1944 E: TElement,
1945 {
1946 let block = declarations.read_with(guards.author);
1947
1948 properties::apply_declarations::<E, _>(
1955 &self,
1956 None,
1957 self.rule_tree.root(),
1958 guards,
1959 block.declaration_importance_iter().map(|(declaration, _)| {
1960 (
1961 declaration,
1962 CascadePriority::new(
1963 CascadeLevel::same_tree_author_normal(),
1964 LayerOrder::root(),
1965 ),
1966 )
1967 }),
1968 Some(parent_style),
1969 Some(parent_style),
1970 FirstLineReparenting::No,
1971 &PositionTryFallbacksTryTactic::default(),
1972 CascadeMode::Unvisited {
1973 visited_rules: None,
1974 },
1975 Default::default(),
1976 None,
1977 &mut Default::default(),
1978 None,
1979 )
1980 }
1981
1982 #[inline]
1984 pub fn device(&self) -> &Device {
1985 &self.device
1986 }
1987
1988 #[inline]
1990 pub fn device_mut(&mut self) -> &mut Device {
1991 &mut self.device
1992 }
1993
1994 #[inline]
1996 pub fn rule_tree(&self) -> &RuleTree {
1997 &self.rule_tree
1998 }
1999
2000 #[inline]
2002 pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
2003 &self.script_custom_properties
2004 }
2005
2006 #[inline]
2008 pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2009 &mut self.script_custom_properties
2010 }
2011
2012 #[cfg(feature = "gecko")]
2014 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2015 self.cascade_data.add_size_of(ops, sizes);
2016 self.author_data_cache.add_size_of(ops, sizes);
2017 sizes.mRuleTree += self.rule_tree.size_of(ops);
2018
2019 }
2021
2022 pub fn shutdown() {
2024 let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2025 }
2026}
2027
2028#[allow(missing_docs)]
2029#[repr(u8)]
2030pub enum RegisterCustomPropertyResult {
2031 SuccessfullyRegistered,
2032 InvalidName,
2033 AlreadyRegistered,
2034 InvalidSyntax,
2035 NoInitialValue,
2036 InvalidInitialValue,
2037 InitialValueNotComputationallyIndependent,
2038}
2039
2040impl Stylist {
2041 pub fn register_custom_property(
2043 &mut self,
2044 url_data: &UrlExtraData,
2045 name: &str,
2046 syntax: &str,
2047 inherits: bool,
2048 initial_value: Option<&str>,
2049 ) -> RegisterCustomPropertyResult {
2050 use RegisterCustomPropertyResult::*;
2051
2052 let Ok(name) = parse_name(name).map(Atom::from) else {
2054 return InvalidName;
2055 };
2056
2057 if self.custom_property_script_registry().get(&name).is_some() {
2060 return AlreadyRegistered;
2061 }
2062 let Ok(syntax) = Descriptor::from_str(syntax, false) else {
2065 return InvalidSyntax;
2066 };
2067
2068 let initial_value = match initial_value {
2069 Some(value) => {
2070 let mut input = ParserInput::new(value);
2071 let parsed = Parser::new(&mut input)
2072 .parse_entirely(|input| {
2073 input.skip_whitespace();
2074 SpecifiedValue::parse(input, None, url_data).map(Arc::new)
2075 })
2076 .ok();
2077 if parsed.is_none() {
2078 return InvalidInitialValue;
2079 }
2080 parsed
2081 },
2082 None => None,
2083 };
2084
2085 if let Err(error) =
2086 PropertyRegistration::validate_initial_value(&syntax, initial_value.as_deref())
2087 {
2088 return match error {
2089 PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
2090 InitialValueNotComputationallyIndependent
2091 },
2092 PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
2093 PropertyRegistrationError::NoInitialValue => NoInitialValue,
2094 };
2095 }
2096
2097 let property_registration = PropertyRegistration {
2098 name: PropertyRuleName(name),
2099 data: PropertyRegistrationData {
2100 syntax,
2101 inherits: if inherits {
2102 Inherits::True
2103 } else {
2104 Inherits::False
2105 },
2106 initial_value,
2107 },
2108 url_data: url_data.clone(),
2109 source_location: SourceLocation { line: 0, column: 0 },
2110 };
2111 self.custom_property_script_registry_mut()
2112 .register(property_registration);
2113 self.rebuild_initial_values_for_custom_properties();
2114
2115 SuccessfullyRegistered
2116 }
2117}
2118
2119#[derive(Clone, Debug, Deref, MallocSizeOf)]
2121pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2122impl<T> Default for LayerOrderedVec<T> {
2123 fn default() -> Self {
2124 Self(Default::default())
2125 }
2126}
2127
2128#[derive(Clone, Debug, Deref, MallocSizeOf)]
2130pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2131impl<T> Default for LayerOrderedMap<T> {
2132 fn default() -> Self {
2133 Self(Default::default())
2134 }
2135}
2136
2137impl<T: 'static> LayerOrderedVec<T> {
2138 fn clear(&mut self) {
2139 self.0.clear();
2140 }
2141 fn push(&mut self, v: T, id: LayerId) {
2142 self.0.push((v, id));
2143 }
2144 fn sort(&mut self, layers: &[CascadeLayer]) {
2145 self.0
2146 .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
2147 }
2148}
2149
2150impl<T: 'static> LayerOrderedMap<T> {
2151 fn shrink_if_needed(&mut self) {
2152 self.0.shrink_if_needed();
2153 }
2154 fn clear(&mut self) {
2155 self.0.clear();
2156 }
2157 fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2158 self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2159 }
2160 fn try_insert_with(
2161 &mut self,
2162 name: Atom,
2163 v: T,
2164 id: LayerId,
2165 cmp: impl Fn(&T, &T) -> Ordering,
2166 ) -> Result<(), AllocErr> {
2167 self.0.try_reserve(1)?;
2168 let vec = self.0.entry(name).or_default();
2169 if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
2170 if *last_id == id {
2171 if cmp(&val, &v) != Ordering::Greater {
2172 *val = v;
2173 }
2174 return Ok(());
2175 }
2176 }
2177 vec.push((v, id));
2178 Ok(())
2179 }
2180 fn sort(&mut self, layers: &[CascadeLayer]) {
2181 self.sort_with(layers, |_, _| Ordering::Equal)
2182 }
2183 fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2184 for (_, v) in self.0.iter_mut() {
2185 v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
2186 let order1 = layers[id1.0 as usize].order;
2187 let order2 = layers[id2.0 as usize].order;
2188 order1.cmp(&order2).then_with(|| cmp(v1, v2))
2189 })
2190 }
2191 }
2192 pub fn get(&self, name: &Atom) -> Option<&T> {
2194 let vec = self.0.get(name)?;
2195 Some(&vec.last()?.0)
2196 }
2197}
2198
2199#[derive(Clone, Debug, MallocSizeOf)]
2203pub struct PageRuleData {
2204 pub layer: LayerId,
2206 #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2208 pub rule: Arc<Locked<PageRule>>,
2209}
2210
2211#[derive(Clone, Debug, Default, MallocSizeOf)]
2213pub struct PageRuleMap {
2214 pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2216}
2217
2218impl PageRuleMap {
2219 #[inline]
2220 fn clear(&mut self) {
2221 self.rules.clear();
2222 }
2223
2224 pub fn match_and_append_rules(
2228 &self,
2229 matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2230 origin: Origin,
2231 guards: &StylesheetGuards,
2232 cascade_data: &DocumentCascadeData,
2233 name: &Option<Atom>,
2234 pseudos: PagePseudoClassFlags,
2235 ) {
2236 let level = match origin {
2237 Origin::UserAgent => CascadeLevel::UANormal,
2238 Origin::User => CascadeLevel::UserNormal,
2239 Origin::Author => CascadeLevel::same_tree_author_normal(),
2240 };
2241 let cascade_data = cascade_data.borrow_for_origin(origin);
2242 let start = matched_rules.len();
2243
2244 self.match_and_add_rules(
2245 matched_rules,
2246 level,
2247 guards,
2248 cascade_data,
2249 &atom!(""),
2250 pseudos,
2251 );
2252 if let Some(name) = name {
2253 self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2254 }
2255
2256 matched_rules[start..].sort_by_key(|block| block.sort_key());
2259 }
2260
2261 fn match_and_add_rules(
2262 &self,
2263 extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2264 level: CascadeLevel,
2265 guards: &StylesheetGuards,
2266 cascade_data: &CascadeData,
2267 name: &Atom,
2268 pseudos: PagePseudoClassFlags,
2269 ) {
2270 let rules = match self.rules.get(name) {
2271 Some(rules) => rules,
2272 None => return,
2273 };
2274 for data in rules.iter() {
2275 let rule = data.rule.read_with(level.guard(&guards));
2276 let specificity = match rule.match_specificity(pseudos) {
2277 Some(specificity) => specificity,
2278 None => continue,
2279 };
2280 let block = rule.block.clone();
2281 extra_declarations.push(ApplicableDeclarationBlock::new(
2282 StyleSource::from_declarations(block),
2283 0,
2284 level,
2285 specificity,
2286 cascade_data.layer_order_for(data.layer),
2287 ScopeProximity::infinity(), ));
2289 }
2290 }
2291}
2292
2293impl MallocShallowSizeOf for PageRuleMap {
2294 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2295 self.rules.shallow_size_of(ops)
2296 }
2297}
2298
2299type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2300
2301#[derive(Clone, Debug, Default)]
2304pub struct ExtraStyleData {
2305 pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2307
2308 pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2310
2311 pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2313
2314 pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2316
2317 pub position_try_rules: PositionTryMap,
2319
2320 pub pages: PageRuleMap,
2322}
2323
2324impl ExtraStyleData {
2325 fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2327 self.font_faces.push(rule.clone(), layer);
2328 }
2329
2330 fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2332 self.font_feature_values.push(rule.clone(), layer);
2333 }
2334
2335 fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2337 self.font_palette_values.push(rule.clone(), layer);
2338 }
2339
2340 fn add_counter_style(
2342 &mut self,
2343 guard: &SharedRwLockReadGuard,
2344 rule: &Arc<Locked<CounterStyleRule>>,
2345 layer: LayerId,
2346 ) -> Result<(), AllocErr> {
2347 let name = rule.read_with(guard).name().0.clone();
2348 self.counter_styles.try_insert(name, rule.clone(), layer)
2349 }
2350
2351 fn add_position_try(
2353 &mut self,
2354 name: Atom,
2355 rule: Arc<Locked<PositionTryRule>>,
2356 layer: LayerId,
2357 ) -> Result<(), AllocErr> {
2358 self.position_try_rules.try_insert(name, rule, layer)
2359 }
2360
2361 fn add_page(
2363 &mut self,
2364 guard: &SharedRwLockReadGuard,
2365 rule: &Arc<Locked<PageRule>>,
2366 layer: LayerId,
2367 ) -> Result<(), AllocErr> {
2368 let page_rule = rule.read_with(guard);
2369 let mut add_rule = |name| {
2370 let vec = self.pages.rules.entry(name).or_default();
2371 vec.push(PageRuleData {
2372 layer,
2373 rule: rule.clone(),
2374 });
2375 };
2376 if page_rule.selectors.0.is_empty() {
2377 add_rule(atom!(""));
2378 } else {
2379 for selector in page_rule.selectors.as_slice() {
2380 add_rule(selector.name.0.clone());
2381 }
2382 }
2383 Ok(())
2384 }
2385
2386 fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2387 self.font_faces.sort(layers);
2388 self.font_feature_values.sort(layers);
2389 self.font_palette_values.sort(layers);
2390 self.counter_styles.sort(layers);
2391 self.position_try_rules.sort(layers);
2392 }
2393
2394 fn clear(&mut self) {
2395 self.font_faces.clear();
2396 self.font_feature_values.clear();
2397 self.font_palette_values.clear();
2398 self.counter_styles.clear();
2399 self.position_try_rules.clear();
2400 self.pages.clear();
2401 }
2402}
2403
2404fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2407 if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2408 Ordering::Equal
2409 } else if v2.vendor_prefix.is_some() {
2410 Ordering::Greater
2411 } else {
2412 Ordering::Less
2413 }
2414}
2415
2416pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2418
2419impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2420 type Item = (&'a ExtraStyleData, Origin);
2421
2422 fn next(&mut self) -> Option<Self::Item> {
2423 self.0.next().map(|d| (&d.0.extra_data, d.1))
2424 }
2425}
2426
2427impl MallocSizeOf for ExtraStyleData {
2428 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2430 let mut n = 0;
2431 n += self.font_faces.shallow_size_of(ops);
2432 n += self.font_feature_values.shallow_size_of(ops);
2433 n += self.font_palette_values.shallow_size_of(ops);
2434 n += self.counter_styles.shallow_size_of(ops);
2435 n += self.position_try_rules.shallow_size_of(ops);
2436 n += self.pages.shallow_size_of(ops);
2437 n
2438 }
2439}
2440
2441#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2443#[derive(Clone, Debug)]
2444struct RevalidationSelectorAndHashes {
2445 #[cfg_attr(
2446 feature = "gecko",
2447 ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2448 )]
2449 selector: Selector<SelectorImpl>,
2450 selector_offset: usize,
2451 hashes: AncestorHashes,
2452}
2453
2454impl RevalidationSelectorAndHashes {
2455 fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2456 let selector_offset = {
2457 let mut index = 0;
2461 let mut iter = selector.iter();
2462
2463 for _ in &mut iter {
2468 index += 1; }
2470
2471 match iter.next_sequence() {
2472 Some(Combinator::PseudoElement) => index + 1, _ => 0,
2474 }
2475 };
2476
2477 RevalidationSelectorAndHashes {
2478 selector,
2479 selector_offset,
2480 hashes,
2481 }
2482 }
2483}
2484
2485impl SelectorMapEntry for RevalidationSelectorAndHashes {
2486 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2487 self.selector.iter_from(self.selector_offset)
2488 }
2489}
2490
2491struct StylistSelectorVisitor<'a> {
2494 passed_rightmost_selector: bool,
2497
2498 needs_revalidation: &'a mut bool,
2500
2501 in_selector_list_of: SelectorListKind,
2504
2505 mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2508
2509 nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2512
2513 attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2515
2516 nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2519
2520 nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2524
2525 nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2529
2530 state_dependencies: &'a mut ElementState,
2532
2533 nth_of_state_dependencies: &'a mut ElementState,
2536
2537 document_state_dependencies: &'a mut DocumentState,
2539}
2540
2541fn component_needs_revalidation(
2542 c: &Component<SelectorImpl>,
2543 passed_rightmost_selector: bool,
2544) -> bool {
2545 match *c {
2546 Component::ID(_) => {
2547 passed_rightmost_selector
2553 },
2554 Component::AttributeInNoNamespaceExists { .. }
2555 | Component::AttributeInNoNamespace { .. }
2556 | Component::AttributeOther(_)
2557 | Component::Empty
2558 | Component::Nth(_)
2559 | Component::NthOf(_)
2560 | Component::Has(_) => true,
2561 Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2562 _ => false,
2563 }
2564}
2565
2566impl<'a> StylistSelectorVisitor<'a> {
2567 fn visit_nested_selector(
2568 &mut self,
2569 in_selector_list_of: SelectorListKind,
2570 selector: &Selector<SelectorImpl>,
2571 ) {
2572 let old_passed_rightmost_selector = self.passed_rightmost_selector;
2573 let old_in_selector_list_of = self.in_selector_list_of;
2574
2575 self.passed_rightmost_selector = false;
2576 self.in_selector_list_of = in_selector_list_of;
2577 let _ret = selector.visit(self);
2578 debug_assert!(_ret, "We never return false");
2579
2580 self.passed_rightmost_selector = old_passed_rightmost_selector;
2581 self.in_selector_list_of = old_in_selector_list_of;
2582 }
2583}
2584
2585impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2586 type Impl = SelectorImpl;
2587
2588 fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2589 *self.needs_revalidation =
2590 *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2591
2592 self.passed_rightmost_selector = self.passed_rightmost_selector
2596 || !matches!(combinator, None | Some(Combinator::PseudoElement));
2597
2598 true
2599 }
2600
2601 fn visit_selector_list(
2602 &mut self,
2603 list_kind: SelectorListKind,
2604 list: &[Selector<Self::Impl>],
2605 ) -> bool {
2606 let in_selector_list_of = self.in_selector_list_of | list_kind;
2607 for selector in list {
2608 self.visit_nested_selector(in_selector_list_of, selector);
2609 }
2610 true
2611 }
2612
2613 fn visit_relative_selector_list(
2614 &mut self,
2615 list: &[selectors::parser::RelativeSelector<Self::Impl>],
2616 ) -> bool {
2617 let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2618 for selector in list {
2619 self.visit_nested_selector(in_selector_list_of, &selector.selector);
2620 }
2621 true
2622 }
2623
2624 fn visit_attribute_selector(
2625 &mut self,
2626 _ns: &NamespaceConstraint<&Namespace>,
2627 name: &LocalName,
2628 lower_name: &LocalName,
2629 ) -> bool {
2630 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2631 self.nth_of_attribute_dependencies.insert(name.clone());
2632 if name != lower_name {
2633 self.nth_of_attribute_dependencies
2634 .insert(lower_name.clone());
2635 }
2636 }
2637
2638 self.attribute_dependencies.insert(name.clone());
2639 if name != lower_name {
2640 self.attribute_dependencies.insert(lower_name.clone());
2641 }
2642
2643 true
2644 }
2645
2646 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2647 *self.needs_revalidation = *self.needs_revalidation
2648 || component_needs_revalidation(s, self.passed_rightmost_selector);
2649
2650 match *s {
2651 Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2652 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2658 self.nth_of_custom_state_dependencies.insert(name.0.clone());
2659 }
2660 },
2661 Component::NonTSPseudoClass(ref p) => {
2662 self.state_dependencies.insert(p.state_flag());
2663 self.document_state_dependencies
2664 .insert(p.document_state_flag());
2665
2666 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2667 self.nth_of_state_dependencies.insert(p.state_flag());
2668 }
2669 },
2670 Component::ID(ref id) => {
2671 if !self.passed_rightmost_selector {
2683 self.mapped_ids.insert(id.0.clone());
2684 }
2685
2686 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2687 self.nth_of_mapped_ids.insert(id.0.clone());
2688 }
2689 },
2690 Component::Class(ref class)
2691 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2692 {
2693 self.nth_of_class_dependencies.insert(class.0.clone());
2694 },
2695 _ => {},
2696 }
2697
2698 true
2699 }
2700}
2701
2702#[derive(Clone, Debug, Default, MallocSizeOf)]
2704struct GenericElementAndPseudoRules<Map> {
2705 element_map: Map,
2707
2708 pseudos_map: PerPseudoElementMap<Self>,
2715}
2716
2717impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2718 #[inline(always)]
2719 fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2720 let mut current = self;
2721 for &pseudo_element in pseudo_elements {
2722 debug_assert!(
2723 !pseudo_element.is_precomputed()
2724 && !pseudo_element.is_unknown_webkit_pseudo_element(),
2725 "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2726 and unknown webkit pseudos should be discarded before getting here"
2727 );
2728
2729 current = current
2730 .pseudos_map
2731 .get_or_insert_with(pseudo_element, Default::default);
2732 }
2733
2734 &mut current.element_map
2735 }
2736
2737 #[inline]
2738 fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2739 let mut current = self;
2740 for pseudo in pseudo_elements {
2741 current = current.pseudos_map.get(&pseudo)?;
2742 }
2743 Some(¤t.element_map)
2744 }
2745
2746 #[cfg(feature = "gecko")]
2748 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2749 sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2750
2751 for elem in self.pseudos_map.iter() {
2752 sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2753 }
2754 }
2755}
2756
2757type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2758type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2759type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2760
2761impl ElementAndPseudoRules {
2762 fn clear(&mut self) {
2764 self.element_map.clear();
2765 self.pseudos_map.clear();
2766 }
2767
2768 fn shrink_if_needed(&mut self) {
2769 self.element_map.shrink_if_needed();
2770 for pseudo in self.pseudos_map.iter_mut() {
2771 pseudo.shrink_if_needed();
2772 }
2773 }
2774}
2775
2776impl PartElementAndPseudoRules {
2777 fn clear(&mut self) {
2779 self.element_map.clear();
2780 self.pseudos_map.clear();
2781 }
2782}
2783
2784#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2786pub struct LayerId(u16);
2787
2788impl LayerId {
2789 pub const fn root() -> Self {
2791 Self(0)
2792 }
2793}
2794
2795#[derive(Clone, Debug, MallocSizeOf)]
2796struct CascadeLayer {
2797 id: LayerId,
2798 order: LayerOrder,
2799 children: Vec<LayerId>,
2800}
2801
2802impl CascadeLayer {
2803 const fn root() -> Self {
2804 Self {
2805 id: LayerId::root(),
2806 order: LayerOrder::root(),
2807 children: vec![],
2808 }
2809 }
2810}
2811
2812#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2815pub struct ContainerConditionId(u16);
2816
2817impl ContainerConditionId {
2818 pub const fn none() -> Self {
2820 Self(0)
2821 }
2822}
2823
2824#[derive(Clone, Debug, MallocSizeOf)]
2825struct ContainerConditionReference {
2826 parent: ContainerConditionId,
2827 #[ignore_malloc_size_of = "Arc"]
2828 condition: Option<Arc<ContainerCondition>>,
2829}
2830
2831impl ContainerConditionReference {
2832 const fn none() -> Self {
2833 Self {
2834 parent: ContainerConditionId::none(),
2835 condition: None,
2836 }
2837 }
2838}
2839
2840#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2843pub struct ScopeConditionId(u16);
2844
2845impl ScopeConditionId {
2846 pub fn new(id: u16) -> Self {
2848 Self(id)
2849 }
2850
2851 pub const fn none() -> Self {
2853 Self(0)
2854 }
2855}
2856
2857#[derive(Clone, Debug, MallocSizeOf)]
2859pub struct ScopeConditionReference {
2860 parent: ScopeConditionId,
2862 condition: Option<ScopeBoundsWithHashes>,
2864 #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2867 implicit_scope_root: StylistImplicitScopeRoot,
2868 is_trivial: bool,
2870}
2871
2872impl ScopeConditionReference {
2873 pub fn new(
2875 parent: ScopeConditionId,
2876 condition: Option<ScopeBoundsWithHashes>,
2877 implicit_scope_root: ImplicitScopeRoot,
2878 is_trivial: bool,
2879 ) -> Self {
2880 Self {
2881 parent,
2882 condition,
2883 implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2884 is_trivial,
2885 }
2886 }
2887
2888 pub const fn none() -> Self {
2890 Self {
2891 parent: ScopeConditionId::none(),
2892 condition: None,
2893 implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2894 is_trivial: true,
2895 }
2896 }
2897}
2898
2899pub struct ScopeRootCandidates {
2901 pub candidates: Vec<ScopeRootCandidate>,
2903 pub is_trivial: bool,
2905}
2906
2907impl Default for ScopeRootCandidates {
2908 fn default() -> Self {
2909 Self {
2910 candidates: vec![],
2911 is_trivial: true,
2912 }
2913 }
2914}
2915
2916impl ScopeRootCandidates {
2917 fn empty(is_trivial: bool) -> Self {
2918 Self {
2919 candidates: vec![],
2920 is_trivial,
2921 }
2922 }
2923}
2924
2925#[derive(Clone, Debug, MallocSizeOf)]
2927pub struct ScopeBoundWithHashes {
2928 #[ignore_malloc_size_of = "Arc"]
2930 selectors: SelectorList<SelectorImpl>,
2931 hashes: SmallVec<[AncestorHashes; 1]>,
2932}
2933
2934impl ScopeBoundWithHashes {
2935 fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2936 let mut hashes = SmallVec::with_capacity(selectors.len());
2937 for selector in selectors.slice() {
2938 hashes.push(AncestorHashes::new(selector, quirks_mode));
2939 }
2940 Self { selectors, hashes }
2941 }
2942
2943 fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
2944 let hashes = selectors
2945 .slice()
2946 .iter()
2947 .map(|_| AncestorHashes {
2948 packed_hashes: [0, 0, 0],
2949 })
2950 .collect();
2951 Self { selectors, hashes }
2952 }
2953}
2954
2955#[derive(Clone, Debug, MallocSizeOf)]
2957pub struct ScopeBoundsWithHashes {
2958 start: Option<ScopeBoundWithHashes>,
2960 end: Option<ScopeBoundWithHashes>,
2962}
2963
2964impl ScopeBoundsWithHashes {
2965 fn new(
2967 quirks_mode: QuirksMode,
2968 start: Option<SelectorList<SelectorImpl>>,
2969 end: Option<SelectorList<SelectorImpl>>,
2970 ) -> Self {
2971 Self {
2972 start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2973 end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2974 }
2975 }
2976
2977 pub fn new_no_hash(
2979 start: Option<SelectorList<SelectorImpl>>,
2980 end: Option<SelectorList<SelectorImpl>>,
2981 ) -> Self {
2982 Self {
2983 start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2984 end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2985 }
2986 }
2987
2988 fn selectors_for<'a>(
2989 bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
2990 ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2991 bound_with_hashes
2992 .map(|b| b.selectors.slice().iter())
2993 .into_iter()
2994 .flatten()
2995 }
2996
2997 fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2998 Self::selectors_for(self.start.as_ref())
2999 }
3000
3001 fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3002 Self::selectors_for(self.end.as_ref())
3003 }
3004
3005 fn is_trivial(&self) -> bool {
3006 fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
3007 bound.as_ref().map_or(default, |bound| {
3008 scope_selector_list_is_trivial(&bound.selectors)
3009 })
3010 }
3011
3012 scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
3014 }
3015}
3016
3017pub fn scope_root_candidates<E>(
3019 scope_conditions: &[ScopeConditionReference],
3020 id: ScopeConditionId,
3021 element: &E,
3022 override_matches_shadow_host_for_part: bool,
3023 scope_subject_map: &ScopeSubjectMap,
3024 context: &mut MatchingContext<SelectorImpl>,
3025) -> ScopeRootCandidates
3026where
3027 E: TElement,
3028{
3029 let condition_ref = &scope_conditions[id.0 as usize];
3030 let bounds = match condition_ref.condition {
3031 None => return ScopeRootCandidates::default(),
3032 Some(ref c) => c,
3033 };
3034 let outer_result = scope_root_candidates(
3038 scope_conditions,
3039 condition_ref.parent,
3040 element,
3041 override_matches_shadow_host_for_part,
3042 scope_subject_map,
3043 context,
3044 );
3045
3046 let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
3047 let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
3048 if !is_outermost_scope && outer_result.candidates.is_empty() {
3049 return ScopeRootCandidates::empty(is_trivial);
3050 }
3051
3052 let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
3053 if let Some(filter) = context.bloom_filter {
3054 if !start
3059 .hashes
3060 .iter()
3061 .any(|entry| selector_may_match(entry, filter))
3062 {
3063 return ScopeRootCandidates::empty(is_trivial);
3064 }
3065 }
3066 (
3067 ScopeTarget::Selector(&start.selectors),
3068 scope_start_matches_shadow_host(&start.selectors),
3069 )
3070 } else {
3071 let implicit_root = condition_ref.implicit_scope_root;
3072 match implicit_root {
3073 StylistImplicitScopeRoot::Normal(r) => (
3074 ScopeTarget::Implicit(r.element(context.current_host.clone())),
3075 r.matches_shadow_host(),
3076 ),
3077 StylistImplicitScopeRoot::Cached(index) => {
3078 let host = context
3079 .current_host
3080 .expect("Cached implicit scope for light DOM implicit scope");
3081 match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
3082 None => return ScopeRootCandidates::empty(is_trivial),
3083 Some(root) => (
3084 ScopeTarget::Implicit(root.element(context.current_host.clone())),
3085 root.matches_shadow_host(),
3086 ),
3087 }
3088 },
3089 }
3090 };
3091 let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
3094
3095 let potential_scope_roots = if is_outermost_scope {
3096 collect_scope_roots(
3097 *element,
3098 None,
3099 context,
3100 &root_target,
3101 matches_shadow_host,
3102 scope_subject_map,
3103 )
3104 } else {
3105 let mut result = vec![];
3106 for activation in outer_result.candidates {
3107 let mut this_result = collect_scope_roots(
3108 *element,
3109 Some(activation.root),
3110 context,
3111 &root_target,
3112 matches_shadow_host,
3113 scope_subject_map,
3114 );
3115 result.append(&mut this_result);
3116 }
3117 result
3118 };
3119
3120 if potential_scope_roots.is_empty() {
3121 return ScopeRootCandidates::empty(is_trivial);
3122 }
3123
3124 let candidates = if let Some(end) = bounds.end.as_ref() {
3125 let mut result = vec![];
3126 for scope_root in potential_scope_roots {
3128 if end
3129 .selectors
3130 .slice()
3131 .iter()
3132 .zip(end.hashes.iter())
3133 .all(|(selector, hashes)| {
3134 if let Some(filter) = context.bloom_filter {
3136 if !selector_may_match(hashes, filter) {
3137 return true;
3139 }
3140 }
3141
3142 !element_is_outside_of_scope(
3143 selector,
3144 *element,
3145 scope_root.root,
3146 context,
3147 matches_shadow_host,
3148 )
3149 })
3150 {
3151 result.push(scope_root);
3152 }
3153 }
3154 result
3155 } else {
3156 potential_scope_roots
3157 };
3158
3159 ScopeRootCandidates {
3160 candidates,
3161 is_trivial,
3162 }
3163}
3164
3165#[derive(Copy, Clone, Debug, MallocSizeOf)]
3168enum StylistImplicitScopeRoot {
3169 Normal(ImplicitScopeRoot),
3170 Cached(usize),
3171}
3172unsafe impl Sync for StylistImplicitScopeRoot {}
3174
3175impl StylistImplicitScopeRoot {
3176 const fn default_const() -> Self {
3177 Self::Normal(ImplicitScopeRoot::DocumentElement)
3179 }
3180}
3181
3182impl Default for StylistImplicitScopeRoot {
3183 fn default() -> Self {
3184 Self::default_const()
3185 }
3186}
3187
3188#[derive(Debug, Clone, MallocSizeOf)]
3194pub struct CascadeData {
3195 normal_rules: ElementAndPseudoRules,
3198
3199 featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3203
3204 slotted_rules: Option<Box<ElementAndPseudoRules>>,
3212
3213 part_rules: Option<Box<PartElementAndPseudoRules>>,
3218
3219 invalidation_map: InvalidationMap,
3221
3222 relative_selector_invalidation_map: InvalidationMap,
3224
3225 additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3226
3227 attribute_dependencies: PrecomputedHashSet<LocalName>,
3232
3233 nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3237
3238 nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3242
3243 nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3247
3248 state_dependencies: ElementState,
3252
3253 nth_of_state_dependencies: ElementState,
3256
3257 document_state_dependencies: DocumentState,
3261
3262 mapped_ids: PrecomputedHashSet<Atom>,
3267
3268 nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3272
3273 #[ignore_malloc_size_of = "Arc"]
3277 selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3278
3279 animations: LayerOrderedMap<KeyframesAnimation>,
3282
3283 #[ignore_malloc_size_of = "Arc"]
3286 custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3287
3288 custom_media: CustomMediaMap,
3290
3291 layer_id: FxHashMap<LayerName, LayerId>,
3293
3294 layers: SmallVec<[CascadeLayer; 1]>,
3296
3297 container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3299
3300 scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3302
3303 scope_subject_map: ScopeSubjectMap,
3305
3306 effective_media_query_results: EffectiveMediaQueryResults,
3308
3309 extra_data: ExtraStyleData,
3311
3312 rules_source_order: u32,
3315
3316 num_selectors: usize,
3318
3319 num_declarations: usize,
3321}
3322
3323static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3324 let list = SelectorList::implicit_scope();
3328 list.mark_as_intentionally_leaked();
3329 list
3330});
3331
3332fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3333 start
3336 .slice()
3337 .iter()
3338 .any(|s| s.matches_featureless_host(true).may_match())
3339}
3340
3341pub fn replace_parent_selector_with_implicit_scope(
3343 selectors: &SelectorList<SelectorImpl>,
3344) -> SelectorList<SelectorImpl> {
3345 selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3346}
3347
3348impl CascadeData {
3349 pub fn new() -> Self {
3351 Self {
3352 normal_rules: ElementAndPseudoRules::default(),
3353 featureless_host_rules: None,
3354 slotted_rules: None,
3355 part_rules: None,
3356 invalidation_map: InvalidationMap::new(),
3357 relative_selector_invalidation_map: InvalidationMap::new(),
3358 additional_relative_selector_invalidation_map:
3359 AdditionalRelativeSelectorInvalidationMap::new(),
3360 nth_of_mapped_ids: PrecomputedHashSet::default(),
3361 nth_of_class_dependencies: PrecomputedHashSet::default(),
3362 nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3363 nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3364 nth_of_state_dependencies: ElementState::empty(),
3365 attribute_dependencies: PrecomputedHashSet::default(),
3366 state_dependencies: ElementState::empty(),
3367 document_state_dependencies: DocumentState::empty(),
3368 mapped_ids: PrecomputedHashSet::default(),
3369 selectors_for_cache_revalidation: SelectorMap::new(),
3370 animations: Default::default(),
3371 custom_property_registrations: Default::default(),
3372 custom_media: Default::default(),
3373 layer_id: Default::default(),
3374 layers: smallvec::smallvec![CascadeLayer::root()],
3375 container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3376 scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3377 scope_subject_map: Default::default(),
3378 extra_data: ExtraStyleData::default(),
3379 effective_media_query_results: EffectiveMediaQueryResults::new(),
3380 rules_source_order: 0,
3381 num_selectors: 0,
3382 num_declarations: 0,
3383 }
3384 }
3385
3386 pub fn rebuild<'a, S>(
3388 &mut self,
3389 device: &Device,
3390 quirks_mode: QuirksMode,
3391 collection: SheetCollectionFlusher<S>,
3392 guard: &SharedRwLockReadGuard,
3393 difference: &mut CascadeDataDifference,
3394 ) -> Result<(), AllocErr>
3395 where
3396 S: StylesheetInDocument + PartialEq + 'static,
3397 {
3398 if !collection.dirty() {
3399 return Ok(());
3400 }
3401
3402 let validity = collection.data_validity();
3403
3404 let mut old_position_try_data = LayerOrderedMap::default();
3405 if validity != DataValidity::Valid {
3406 old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3407 self.clear_cascade_data();
3408 if validity == DataValidity::FullyInvalid {
3409 self.clear_invalidation_data();
3410 }
3411 }
3412
3413 let mut result = Ok(());
3414
3415 collection.each(|index, stylesheet, rebuild_kind| {
3416 result = self.add_stylesheet(
3417 device,
3418 quirks_mode,
3419 stylesheet,
3420 index,
3421 guard,
3422 rebuild_kind,
3423 None,
3424 if validity == DataValidity::Valid {
3425 Some(difference)
3426 } else {
3427 None
3428 },
3429 );
3430 result.is_ok()
3431 });
3432
3433 self.did_finish_rebuild();
3434
3435 if validity != DataValidity::Valid {
3438 difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3439 }
3440
3441 result
3442 }
3443
3444 pub fn custom_media_map(&self) -> &CustomMediaMap {
3446 &self.custom_media
3447 }
3448
3449 pub fn invalidation_map(&self) -> &InvalidationMap {
3451 &self.invalidation_map
3452 }
3453
3454 pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3456 &self.relative_selector_invalidation_map
3457 }
3458
3459 pub fn relative_invalidation_map_attributes(
3461 &self,
3462 ) -> &AdditionalRelativeSelectorInvalidationMap {
3463 &self.additional_relative_selector_invalidation_map
3464 }
3465
3466 #[inline]
3469 pub fn has_state_dependency(&self, state: ElementState) -> bool {
3470 self.state_dependencies.intersects(state)
3471 }
3472
3473 #[inline]
3476 pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3477 self.nth_of_custom_state_dependencies.contains(state)
3478 }
3479
3480 #[inline]
3483 pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3484 self.nth_of_state_dependencies.intersects(state)
3485 }
3486
3487 #[inline]
3490 pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3491 self.attribute_dependencies.contains(local_name)
3492 }
3493
3494 #[inline]
3497 pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3498 self.nth_of_mapped_ids.contains(id)
3499 }
3500
3501 #[inline]
3504 pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3505 self.nth_of_class_dependencies.contains(class)
3506 }
3507
3508 #[inline]
3511 pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3512 self.nth_of_attribute_dependencies.contains(local_name)
3513 }
3514
3515 #[inline]
3517 pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3518 self.normal_rules.rules(pseudo_elements)
3519 }
3520
3521 #[inline]
3523 pub fn featureless_host_rules(
3524 &self,
3525 pseudo_elements: &[PseudoElement],
3526 ) -> Option<&SelectorMap<Rule>> {
3527 self.featureless_host_rules
3528 .as_ref()
3529 .and_then(|d| d.rules(pseudo_elements))
3530 }
3531
3532 pub fn any_featureless_host_rules(&self) -> bool {
3534 self.featureless_host_rules.is_some()
3535 }
3536
3537 #[inline]
3539 pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3540 self.slotted_rules
3541 .as_ref()
3542 .and_then(|d| d.rules(pseudo_elements))
3543 }
3544
3545 pub fn any_slotted_rule(&self) -> bool {
3547 self.slotted_rules.is_some()
3548 }
3549
3550 #[inline]
3552 pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3553 self.part_rules
3554 .as_ref()
3555 .and_then(|d| d.rules(pseudo_elements))
3556 }
3557
3558 pub fn any_part_rule(&self) -> bool {
3560 self.part_rules.is_some()
3561 }
3562
3563 #[inline]
3564 fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3565 self.layers[id.0 as usize].order
3566 }
3567
3568 pub(crate) fn container_condition_matches<E>(
3569 &self,
3570 mut id: ContainerConditionId,
3571 stylist: &Stylist,
3572 element: E,
3573 context: &mut MatchingContext<E::Impl>,
3574 ) -> bool
3575 where
3576 E: TElement,
3577 {
3578 loop {
3579 let condition_ref = &self.container_conditions[id.0 as usize];
3580 let condition = match condition_ref.condition {
3581 None => return true,
3582 Some(ref c) => c,
3583 };
3584 let matches = condition
3585 .matches(
3586 stylist,
3587 element,
3588 context.extra_data.originating_element_style,
3589 &mut context.extra_data.cascade_input_flags,
3590 )
3591 .to_bool(false);
3592 if !matches {
3593 return false;
3594 }
3595 id = condition_ref.parent;
3596 }
3597 }
3598
3599 pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3600 &self,
3601 rule: &Rule,
3602 element: E,
3603 context: &mut MatchingContext<E::Impl>,
3604 ) -> ScopeProximity {
3605 context
3606 .extra_data
3607 .cascade_input_flags
3608 .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3609
3610 let result = scope_root_candidates(
3614 &self.scope_conditions,
3615 rule.scope_condition_id,
3616 &element,
3617 rule.selector.is_part(),
3618 &self.scope_subject_map,
3619 context,
3620 );
3621 for candidate in result.candidates {
3622 if context.nest_for_scope(Some(candidate.root), |context| {
3623 matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3624 }) {
3625 return candidate.proximity;
3626 }
3627 }
3628 ScopeProximity::infinity()
3629 }
3630
3631 fn did_finish_rebuild(&mut self) {
3632 self.shrink_maps_if_needed();
3633 self.compute_layer_order();
3634 }
3635
3636 fn shrink_maps_if_needed(&mut self) {
3637 self.normal_rules.shrink_if_needed();
3638 if let Some(ref mut host_rules) = self.featureless_host_rules {
3639 host_rules.shrink_if_needed();
3640 }
3641 if let Some(ref mut slotted_rules) = self.slotted_rules {
3642 slotted_rules.shrink_if_needed();
3643 }
3644 self.animations.shrink_if_needed();
3645 self.custom_property_registrations.shrink_if_needed();
3646 self.invalidation_map.shrink_if_needed();
3647 self.relative_selector_invalidation_map.shrink_if_needed();
3648 self.additional_relative_selector_invalidation_map
3649 .shrink_if_needed();
3650 self.attribute_dependencies.shrink_if_needed();
3651 self.nth_of_attribute_dependencies.shrink_if_needed();
3652 self.nth_of_custom_state_dependencies.shrink_if_needed();
3653 self.nth_of_class_dependencies.shrink_if_needed();
3654 self.nth_of_mapped_ids.shrink_if_needed();
3655 self.mapped_ids.shrink_if_needed();
3656 self.layer_id.shrink_if_needed();
3657 self.selectors_for_cache_revalidation.shrink_if_needed();
3658 self.scope_subject_map.shrink_if_needed();
3659 }
3660
3661 fn compute_layer_order(&mut self) {
3662 debug_assert_ne!(
3663 self.layers.len(),
3664 0,
3665 "There should be at least the root layer!"
3666 );
3667 if self.layers.len() == 1 {
3668 return; }
3670 let (first, remaining) = self.layers.split_at_mut(1);
3671 let root = &mut first[0];
3672 let mut order = LayerOrder::first();
3673 compute_layer_order_for_subtree(root, remaining, &mut order);
3674
3675 fn compute_layer_order_for_subtree(
3678 parent: &mut CascadeLayer,
3679 remaining_layers: &mut [CascadeLayer],
3680 order: &mut LayerOrder,
3681 ) {
3682 for child in parent.children.iter() {
3683 debug_assert!(
3684 parent.id < *child,
3685 "Children are always registered after parents"
3686 );
3687 let child_index = (child.0 - parent.id.0 - 1) as usize;
3688 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3689 let child = &mut first[child_index];
3690 compute_layer_order_for_subtree(child, remaining, order);
3691 }
3692
3693 if parent.id != LayerId::root() {
3694 parent.order = *order;
3695 order.inc();
3696 }
3697 }
3698 self.extra_data.sort_by_layer(&self.layers);
3699 self.animations
3700 .sort_with(&self.layers, compare_keyframes_in_same_layer);
3701 self.custom_property_registrations.sort(&self.layers)
3702 }
3703
3704 fn collect_applicable_media_query_results_into<S>(
3713 device: &Device,
3714 stylesheet: &S,
3715 guard: &SharedRwLockReadGuard,
3716 results: &mut Vec<MediaListKey>,
3717 contents_list: &mut StyleSheetContentList,
3718 custom_media_map: &mut CustomMediaMap,
3719 ) where
3720 S: StylesheetInDocument + 'static,
3721 {
3722 if !stylesheet.enabled() {
3723 return;
3724 }
3725 if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
3726 return;
3727 }
3728
3729 debug!(" + {:?}", stylesheet);
3730 let contents = stylesheet.contents(guard);
3731 results.push(contents.to_media_list_key());
3732
3733 contents_list.push(StylesheetContentsPtr(unsafe {
3735 Arc::from_raw_addrefed(&*contents)
3736 }));
3737
3738 let mut iter = stylesheet
3739 .contents(guard)
3740 .effective_rules(device, custom_media_map, guard);
3741 while let Some(rule) = iter.next() {
3742 match *rule {
3743 CssRule::CustomMedia(ref custom_media) => {
3744 iter.custom_media()
3745 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3746 },
3747 CssRule::Import(ref lock) => {
3748 let import_rule = lock.read_with(guard);
3749 debug!(" + {:?}", import_rule.stylesheet.media(guard));
3750 results.push(import_rule.to_media_list_key());
3751 },
3752 CssRule::Media(ref media_rule) => {
3753 debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3754 results.push(media_rule.to_media_list_key());
3755 },
3756 _ => {},
3757 }
3758 }
3759 }
3760
3761 fn add_styles(
3762 &mut self,
3763 selectors: &SelectorList<SelectorImpl>,
3764 declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3765 ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3766 containing_rule_state: &ContainingRuleState,
3767 mut replaced_selectors: Option<&mut ReplacedSelectors>,
3768 guard: &SharedRwLockReadGuard,
3769 rebuild_kind: SheetRebuildKind,
3770 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3771 quirks_mode: QuirksMode,
3772 mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3773 ) -> Result<(), AllocErr> {
3774 self.num_declarations += declarations.read_with(guard).len();
3775 for selector in selectors.slice() {
3776 self.num_selectors += 1;
3777
3778 let pseudo_elements = selector.pseudo_elements();
3779 let inner_pseudo_element = pseudo_elements.get(0);
3780 if let Some(pseudo) = inner_pseudo_element {
3781 if pseudo.is_precomputed() {
3782 debug_assert!(selector.is_universal());
3783 debug_assert!(ancestor_selectors.is_none());
3784 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3785 debug_assert!(!containing_rule_state.scope_is_effective());
3787 precomputed_pseudo_element_decls
3788 .as_mut()
3789 .expect("Expected precomputed declarations for the UA level")
3790 .get_or_insert_with(pseudo, Vec::new)
3791 .push(ApplicableDeclarationBlock::new(
3792 StyleSource::from_declarations(declarations.clone()),
3793 self.rules_source_order,
3794 CascadeLevel::UANormal,
3795 selector.specificity(),
3796 LayerOrder::root(),
3797 ScopeProximity::infinity(),
3798 ));
3799 continue;
3800 }
3801 if pseudo_elements
3802 .iter()
3803 .any(|p| p.is_unknown_webkit_pseudo_element())
3804 {
3805 continue;
3806 }
3807 }
3808
3809 debug_assert!(!pseudo_elements
3810 .iter()
3811 .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3812
3813 let selector = match ancestor_selectors {
3814 Some(ref s) => selector.replace_parent_selector(&s),
3815 None => selector.clone(),
3816 };
3817
3818 let hashes = AncestorHashes::new(&selector, quirks_mode);
3819
3820 let rule = Rule::new(
3821 selector,
3822 hashes,
3823 StyleSource::from_declarations(declarations.clone()),
3824 self.rules_source_order,
3825 containing_rule_state.layer_id,
3826 containing_rule_state.container_condition_id,
3827 containing_rule_state.in_starting_style,
3828 containing_rule_state.containing_scope_rule_state.id,
3829 );
3830
3831 if let Some(ref mut replaced_selectors) = replaced_selectors {
3832 replaced_selectors.push(rule.selector.clone())
3833 }
3834
3835 if rebuild_kind.should_rebuild_invalidation() {
3836 let mut scope_dependencies = note_selector_for_invalidation(
3837 &rule.selector,
3838 quirks_mode,
3839 &mut self.invalidation_map,
3840 &mut self.relative_selector_invalidation_map,
3841 &mut self.additional_relative_selector_invalidation_map,
3842 None,
3843 None,
3844 )?;
3845 let mut needs_revalidation = false;
3846 let mut visitor = StylistSelectorVisitor {
3847 needs_revalidation: &mut needs_revalidation,
3848 passed_rightmost_selector: false,
3849 in_selector_list_of: SelectorListKind::default(),
3850 mapped_ids: &mut self.mapped_ids,
3851 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3852 attribute_dependencies: &mut self.attribute_dependencies,
3853 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3854 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3855 nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3856 state_dependencies: &mut self.state_dependencies,
3857 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3858 document_state_dependencies: &mut self.document_state_dependencies,
3859 };
3860 rule.selector.visit(&mut visitor);
3861
3862 if needs_revalidation {
3863 self.selectors_for_cache_revalidation.insert(
3864 RevalidationSelectorAndHashes::new(
3865 rule.selector.clone(),
3866 rule.hashes.clone(),
3867 ),
3868 quirks_mode,
3869 )?;
3870 }
3871
3872 match (
3873 scope_dependencies.as_mut(),
3874 collected_scope_dependencies.as_mut(),
3875 ) {
3876 (Some(inner_scope_deps), Some(scope_deps)) => {
3877 scope_deps.append(inner_scope_deps)
3878 },
3879 _ => {},
3880 }
3881 }
3882
3883 if let Some(parts) = rule.selector.parts() {
3887 let map = self
3894 .part_rules
3895 .get_or_insert_with(|| Box::new(Default::default()))
3896 .for_insertion(&pseudo_elements);
3897 map.try_reserve(1)?;
3898 let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3899 vec.try_reserve(1)?;
3900 vec.push(rule);
3901 } else {
3902 let scope_matches_shadow_host = containing_rule_state
3903 .containing_scope_rule_state
3904 .matches_shadow_host
3905 == ScopeMatchesShadowHost::Yes;
3906 let matches_featureless_host_only = match rule
3907 .selector
3908 .matches_featureless_host(scope_matches_shadow_host)
3909 {
3910 MatchesFeaturelessHost::Only => true,
3911 MatchesFeaturelessHost::Yes => {
3912 self.featureless_host_rules
3914 .get_or_insert_with(|| Box::new(Default::default()))
3915 .for_insertion(&pseudo_elements)
3916 .insert(rule.clone(), quirks_mode)?;
3917 false
3918 },
3919 MatchesFeaturelessHost::Never => false,
3920 };
3921
3922 let rules = if matches_featureless_host_only {
3929 self.featureless_host_rules
3930 .get_or_insert_with(|| Box::new(Default::default()))
3931 } else if rule.selector.is_slotted() {
3932 self.slotted_rules
3933 .get_or_insert_with(|| Box::new(Default::default()))
3934 } else {
3935 &mut self.normal_rules
3936 }
3937 .for_insertion(&pseudo_elements);
3938 rules.insert(rule, quirks_mode)?;
3939 }
3940 }
3941 self.rules_source_order += 1;
3942 Ok(())
3943 }
3944
3945 fn add_rule_list<S>(
3946 &mut self,
3947 rules: std::slice::Iter<CssRule>,
3948 device: &Device,
3949 quirks_mode: QuirksMode,
3950 stylesheet: &S,
3951 sheet_index: usize,
3952 guard: &SharedRwLockReadGuard,
3953 rebuild_kind: SheetRebuildKind,
3954 containing_rule_state: &mut ContainingRuleState,
3955 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3956 mut difference: Option<&mut CascadeDataDifference>,
3957 ) -> Result<(), AllocErr>
3958 where
3959 S: StylesheetInDocument + 'static,
3960 {
3961 for rule in rules {
3962 let mut handled = true;
3965 let mut list_for_nested_rules = None;
3966 match *rule {
3967 CssRule::Style(ref locked) => {
3968 let style_rule = locked.read_with(guard);
3969 let has_nested_rules = style_rule.rules.is_some();
3970 let mut replaced_selectors = ReplacedSelectors::new();
3971 let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
3972 let collect_replaced_selectors =
3973 has_nested_rules && ancestor_selectors.is_some();
3974 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
3975 .scope_is_effective()
3976 .then(|| Vec::new());
3977 self.add_styles(
3978 &style_rule.selectors,
3979 &style_rule.block,
3980 ancestor_selectors,
3981 containing_rule_state,
3982 if collect_replaced_selectors {
3983 Some(&mut replaced_selectors)
3984 } else {
3985 None
3986 },
3987 guard,
3988 rebuild_kind,
3989 precomputed_pseudo_element_decls.as_deref_mut(),
3990 quirks_mode,
3991 inner_dependencies.as_mut(),
3992 )?;
3993 if let Some(mut scope_dependencies) = inner_dependencies {
3994 containing_rule_state
3995 .containing_scope_rule_state
3996 .inner_dependencies
3997 .append(&mut scope_dependencies);
3998 }
3999 if has_nested_rules {
4000 handled = false;
4001 list_for_nested_rules = Some(if collect_replaced_selectors {
4002 SelectorList::from_iter(replaced_selectors.drain(..))
4003 } else {
4004 style_rule.selectors.clone()
4005 });
4006 }
4007 },
4008 CssRule::NestedDeclarations(ref rule) => {
4009 if let Some(ref ancestor_selectors) =
4010 containing_rule_state.ancestor_selector_lists.last()
4011 {
4012 let decls = &rule.read_with(guard).block;
4013 let selectors = match containing_rule_state.nested_declarations_context {
4014 NestedDeclarationsContext::Style => ancestor_selectors,
4015 NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
4016 };
4017 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4018 .scope_is_effective()
4019 .then(|| Vec::new());
4020 self.add_styles(
4021 selectors,
4022 decls,
4023 None,
4024 containing_rule_state,
4025 None,
4026 guard,
4027 SheetRebuildKind::CascadeOnly,
4030 precomputed_pseudo_element_decls.as_deref_mut(),
4031 quirks_mode,
4032 inner_dependencies.as_mut(),
4033 )?;
4034 if let Some(mut scope_dependencies) = inner_dependencies {
4035 containing_rule_state
4036 .containing_scope_rule_state
4037 .inner_dependencies
4038 .append(&mut scope_dependencies);
4039 }
4040 }
4041 },
4042 CssRule::Keyframes(ref keyframes_rule) => {
4043 debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
4044 let keyframes_rule = keyframes_rule.read_with(guard);
4045 let name = keyframes_rule.name.as_atom().clone();
4046 let animation = KeyframesAnimation::from_keyframes(
4047 &keyframes_rule.keyframes,
4048 keyframes_rule.vendor_prefix.clone(),
4049 guard,
4050 );
4051 self.animations.try_insert_with(
4052 name,
4053 animation,
4054 containing_rule_state.layer_id,
4055 compare_keyframes_in_same_layer,
4056 )?;
4057 },
4058 CssRule::Property(ref registration) => {
4059 self.custom_property_registrations.try_insert(
4060 registration.name.0.clone(),
4061 Arc::clone(registration),
4062 containing_rule_state.layer_id,
4063 )?;
4064 },
4065 CssRule::FontFace(ref rule) => {
4066 self.extra_data
4077 .add_font_face(rule, containing_rule_state.layer_id);
4078 },
4079 CssRule::FontFeatureValues(ref rule) => {
4080 self.extra_data
4081 .add_font_feature_values(rule, containing_rule_state.layer_id);
4082 },
4083 CssRule::FontPaletteValues(ref rule) => {
4084 self.extra_data
4085 .add_font_palette_values(rule, containing_rule_state.layer_id);
4086 },
4087 CssRule::CounterStyle(ref rule) => {
4088 self.extra_data.add_counter_style(
4089 guard,
4090 rule,
4091 containing_rule_state.layer_id,
4092 )?;
4093 },
4094 CssRule::PositionTry(ref rule) => {
4095 let name = rule.read_with(guard).name.0.clone();
4096 if let Some(ref mut difference) = difference {
4097 difference.changed_position_try_names.insert(name.clone());
4098 }
4099 self.extra_data.add_position_try(
4100 name,
4101 rule.clone(),
4102 containing_rule_state.layer_id,
4103 )?;
4104 },
4105 CssRule::Page(ref rule) => {
4106 self.extra_data
4107 .add_page(guard, rule, containing_rule_state.layer_id)?;
4108 handled = false;
4109 },
4110 _ => {
4111 handled = false;
4112 },
4113 }
4114
4115 if handled {
4116 if cfg!(debug_assertions) {
4119 let mut effective = false;
4120 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4121 rule,
4122 device,
4123 quirks_mode,
4124 &self.custom_media,
4125 guard,
4126 &mut effective,
4127 );
4128 debug_assert!(children.is_none());
4129 debug_assert!(effective);
4130 }
4131 continue;
4132 }
4133
4134 let mut effective = false;
4135 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4136 rule,
4137 device,
4138 quirks_mode,
4139 &self.custom_media,
4140 guard,
4141 &mut effective,
4142 );
4143 if !effective {
4144 continue;
4145 }
4146
4147 fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4148 if let Some(id) = data.layer_id.get(layer) {
4152 return *id;
4153 }
4154 let id = LayerId(data.layers.len() as u16);
4155
4156 let parent_layer_id = if layer.layer_names().len() > 1 {
4157 let mut parent = layer.clone();
4158 parent.0.pop();
4159
4160 *data
4161 .layer_id
4162 .get_mut(&parent)
4163 .expect("Parent layers should be registered before child layers")
4164 } else {
4165 LayerId::root()
4166 };
4167
4168 data.layers[parent_layer_id.0 as usize].children.push(id);
4169 data.layers.push(CascadeLayer {
4170 id,
4171 order: LayerOrder::first(),
4174 children: vec![],
4175 });
4176
4177 data.layer_id.insert(layer.clone(), id);
4178
4179 id
4180 }
4181
4182 fn maybe_register_layers(
4183 data: &mut CascadeData,
4184 name: Option<&LayerName>,
4185 containing_rule_state: &mut ContainingRuleState,
4186 ) {
4187 let anon_name;
4188 let name = match name {
4189 Some(name) => name,
4190 None => {
4191 anon_name = LayerName::new_anonymous();
4192 &anon_name
4193 },
4194 };
4195 for name in name.layer_names() {
4196 containing_rule_state.layer_name.0.push(name.clone());
4197 containing_rule_state.layer_id =
4198 maybe_register_layer(data, &containing_rule_state.layer_name);
4199 }
4200 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4201 }
4202
4203 let saved_containing_rule_state = containing_rule_state.save();
4204 match *rule {
4205 CssRule::Import(ref lock) => {
4206 let import_rule = lock.read_with(guard);
4207 if rebuild_kind.should_rebuild_invalidation() {
4208 self.effective_media_query_results
4209 .saw_effective(import_rule);
4210 }
4211 match import_rule.layer {
4212 ImportLayer::Named(ref name) => {
4213 maybe_register_layers(self, Some(name), containing_rule_state)
4214 },
4215 ImportLayer::Anonymous => {
4216 maybe_register_layers(self, None, containing_rule_state)
4217 },
4218 ImportLayer::None => {},
4219 }
4220 },
4221 CssRule::Media(ref media_rule) => {
4222 if rebuild_kind.should_rebuild_invalidation() {
4223 self.effective_media_query_results
4224 .saw_effective(&**media_rule);
4225 }
4226 },
4227 CssRule::LayerBlock(ref rule) => {
4228 maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4229 },
4230 CssRule::CustomMedia(ref custom_media) => {
4231 self.custom_media
4232 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4233 },
4234 CssRule::LayerStatement(ref rule) => {
4235 for name in &*rule.names {
4236 maybe_register_layers(self, Some(name), containing_rule_state);
4237 containing_rule_state.restore(&saved_containing_rule_state);
4239 }
4240 },
4241 CssRule::Style(..) => {
4242 containing_rule_state.nested_declarations_context =
4243 NestedDeclarationsContext::Style;
4244 if let Some(s) = list_for_nested_rules {
4245 containing_rule_state.ancestor_selector_lists.push(s);
4246 }
4247 },
4248 CssRule::Container(ref rule) => {
4249 let id = ContainerConditionId(self.container_conditions.len() as u16);
4250 self.container_conditions.push(ContainerConditionReference {
4251 parent: containing_rule_state.container_condition_id,
4252 condition: Some(rule.condition.clone()),
4253 });
4254 containing_rule_state.container_condition_id = id;
4255 },
4256 CssRule::StartingStyle(..) => {
4257 containing_rule_state.in_starting_style = true;
4258 },
4259 CssRule::Scope(ref rule) => {
4260 containing_rule_state.nested_declarations_context =
4261 NestedDeclarationsContext::Scope;
4262 let id = ScopeConditionId(self.scope_conditions.len() as u16);
4263 let mut matches_shadow_host = false;
4264 let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4265 matches_shadow_host = scope_start_matches_shadow_host(start);
4266 StylistImplicitScopeRoot::default()
4268 } else {
4269 if let Some(root) = stylesheet.implicit_scope_root() {
4272 matches_shadow_host = root.matches_shadow_host();
4273 match root {
4274 ImplicitScopeRoot::InLightTree(_)
4275 | ImplicitScopeRoot::Constructed
4276 | ImplicitScopeRoot::DocumentElement => {
4277 StylistImplicitScopeRoot::Normal(root)
4278 },
4279 ImplicitScopeRoot::ShadowHost(_)
4280 | ImplicitScopeRoot::InShadowTree(_) => {
4281 StylistImplicitScopeRoot::Cached(sheet_index)
4288 },
4289 }
4290 } else {
4291 StylistImplicitScopeRoot::default()
4293 }
4294 };
4295
4296 let replaced =
4297 {
4298 let start = rule.bounds.start.as_ref().map(|selector| {
4299 match containing_rule_state.ancestor_selector_lists.last() {
4300 Some(s) => selector.replace_parent_selector(s),
4301 None => selector.clone(),
4302 }
4303 });
4304 let implicit_scope_selector = &*IMPLICIT_SCOPE;
4305 let end = rule.bounds.end.as_ref().map(|selector| {
4306 selector.replace_parent_selector(implicit_scope_selector)
4307 });
4308 containing_rule_state
4309 .ancestor_selector_lists
4310 .push(implicit_scope_selector.clone());
4311 ScopeBoundsWithHashes::new(quirks_mode, start, end)
4312 };
4313
4314 if let Some(selectors) = replaced.start.as_ref() {
4315 self.scope_subject_map
4316 .add_bound_start(&selectors.selectors, quirks_mode);
4317 }
4318
4319 let is_trivial = replaced.is_trivial();
4320 self.scope_conditions.push(ScopeConditionReference {
4321 parent: containing_rule_state.containing_scope_rule_state.id,
4322 condition: Some(replaced),
4323 implicit_scope_root,
4324 is_trivial,
4325 });
4326
4327 containing_rule_state
4328 .containing_scope_rule_state
4329 .matches_shadow_host
4330 .nest_for_scope(matches_shadow_host);
4331 containing_rule_state.containing_scope_rule_state.id = id;
4332 containing_rule_state
4333 .containing_scope_rule_state
4334 .inner_dependencies
4335 .reserve(children.iter().len());
4336 },
4337 _ => {},
4339 }
4340
4341 if let Some(children) = children {
4342 self.add_rule_list(
4343 children,
4344 device,
4345 quirks_mode,
4346 stylesheet,
4347 sheet_index,
4348 guard,
4349 rebuild_kind,
4350 containing_rule_state,
4351 precomputed_pseudo_element_decls.as_deref_mut(),
4352 difference.as_deref_mut(),
4353 )?;
4354 }
4355
4356 if let Some(scope_restore_data) =
4357 containing_rule_state.restore(&saved_containing_rule_state)
4358 {
4359 let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4360 let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4361 if let Some(cond) = cur_scope.condition.as_ref() {
4362 let mut _unused = false;
4363 let visitor = StylistSelectorVisitor {
4364 needs_revalidation: &mut _unused,
4365 passed_rightmost_selector: true,
4366 in_selector_list_of: SelectorListKind::default(),
4367 mapped_ids: &mut self.mapped_ids,
4368 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4369 attribute_dependencies: &mut self.attribute_dependencies,
4370 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4371 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4372 nth_of_custom_state_dependencies: &mut self
4373 .nth_of_custom_state_dependencies,
4374 state_dependencies: &mut self.state_dependencies,
4375 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4376 document_state_dependencies: &mut self.document_state_dependencies,
4377 };
4378
4379 let dependency_vector = build_scope_dependencies(
4380 quirks_mode,
4381 cur_scope_inner_dependencies,
4382 visitor,
4383 cond,
4384 &mut self.invalidation_map,
4385 &mut self.relative_selector_invalidation_map,
4386 &mut self.additional_relative_selector_invalidation_map,
4387 )?;
4388
4389 containing_rule_state
4390 .containing_scope_rule_state
4391 .inner_dependencies
4392 .extend(dependency_vector);
4393 }
4394 }
4395 }
4396
4397 Ok(())
4398 }
4399
4400 fn add_stylesheet<S>(
4402 &mut self,
4403 device: &Device,
4404 quirks_mode: QuirksMode,
4405 stylesheet: &S,
4406 sheet_index: usize,
4407 guard: &SharedRwLockReadGuard,
4408 rebuild_kind: SheetRebuildKind,
4409 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4410 mut difference: Option<&mut CascadeDataDifference>,
4411 ) -> Result<(), AllocErr>
4412 where
4413 S: StylesheetInDocument + 'static,
4414 {
4415 if !stylesheet.enabled() {
4416 return Ok(());
4417 }
4418
4419 if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4420 return Ok(());
4421 }
4422
4423 let contents = stylesheet.contents(guard);
4424 if rebuild_kind.should_rebuild_invalidation() {
4425 self.effective_media_query_results.saw_effective(&*contents);
4426 }
4427
4428 let mut state = ContainingRuleState::default();
4429 self.add_rule_list(
4430 contents.rules(guard).iter(),
4431 device,
4432 quirks_mode,
4433 stylesheet,
4434 sheet_index,
4435 guard,
4436 rebuild_kind,
4437 &mut state,
4438 precomputed_pseudo_element_decls.as_deref_mut(),
4439 difference.as_deref_mut(),
4440 )?;
4441
4442 Ok(())
4443 }
4444
4445 pub fn media_feature_affected_matches<S>(
4448 &self,
4449 stylesheet: &S,
4450 guard: &SharedRwLockReadGuard,
4451 device: &Device,
4452 quirks_mode: QuirksMode,
4453 ) -> bool
4454 where
4455 S: StylesheetInDocument + 'static,
4456 {
4457 use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4458
4459 let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4460
4461 let contents = stylesheet.contents(guard);
4462 let effective_then = self.effective_media_query_results.was_effective(contents);
4463
4464 if effective_now != effective_then {
4465 debug!(
4466 " > Stylesheet {:?} changed -> {}, {}",
4467 stylesheet.media(guard),
4468 effective_then,
4469 effective_now
4470 );
4471 return false;
4472 }
4473
4474 if !effective_now {
4475 return true;
4476 }
4477
4478 let custom_media = CustomMediaMap::default();
4480 let mut iter =
4481 contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4482 while let Some(rule) = iter.next() {
4483 match *rule {
4484 CssRule::Style(..)
4485 | CssRule::NestedDeclarations(..)
4486 | CssRule::Namespace(..)
4487 | CssRule::FontFace(..)
4488 | CssRule::Container(..)
4489 | CssRule::CounterStyle(..)
4490 | CssRule::Supports(..)
4491 | CssRule::Keyframes(..)
4492 | CssRule::Margin(..)
4493 | CssRule::Page(..)
4494 | CssRule::Property(..)
4495 | CssRule::Document(..)
4496 | CssRule::LayerBlock(..)
4497 | CssRule::LayerStatement(..)
4498 | CssRule::FontPaletteValues(..)
4499 | CssRule::FontFeatureValues(..)
4500 | CssRule::Scope(..)
4501 | CssRule::StartingStyle(..)
4502 | CssRule::CustomMedia(..)
4503 | CssRule::PositionTry(..) => {
4504 continue;
4507 },
4508 CssRule::Import(ref lock) => {
4509 let import_rule = lock.read_with(guard);
4510 let effective_now = match import_rule.stylesheet.media(guard) {
4511 Some(m) => m.evaluate(
4512 device,
4513 quirks_mode,
4514 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4515 ),
4516 None => true,
4517 };
4518 let effective_then = self
4519 .effective_media_query_results
4520 .was_effective(import_rule);
4521 if effective_now != effective_then {
4522 debug!(
4523 " > @import rule {:?} changed {} -> {}",
4524 import_rule.stylesheet.media(guard),
4525 effective_then,
4526 effective_now
4527 );
4528 return false;
4529 }
4530
4531 if !effective_now {
4532 iter.skip_children();
4533 }
4534 },
4535 CssRule::Media(ref media_rule) => {
4536 let mq = media_rule.media_queries.read_with(guard);
4537 let effective_now = mq.evaluate(
4538 device,
4539 quirks_mode,
4540 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4541 );
4542 let effective_then = self
4543 .effective_media_query_results
4544 .was_effective(&**media_rule);
4545
4546 if effective_now != effective_then {
4547 debug!(
4548 " > @media rule {:?} changed {} -> {}",
4549 mq, effective_then, effective_now
4550 );
4551 return false;
4552 }
4553
4554 if !effective_now {
4555 iter.skip_children();
4556 }
4557 },
4558 }
4559 }
4560
4561 true
4562 }
4563
4564 pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4566 &self.custom_property_registrations
4567 }
4568
4569 fn revalidate_scopes<E: TElement>(
4570 &self,
4571 element: &E,
4572 matching_context: &mut MatchingContext<E::Impl>,
4573 result: &mut ScopeRevalidationResult,
4574 ) {
4575 for condition_id in 1..self.scope_conditions.len() {
4582 let condition = &self.scope_conditions[condition_id];
4583 let matches = if condition.is_trivial {
4584 continue;
4587 } else {
4588 let result = scope_root_candidates(
4589 &self.scope_conditions,
4590 ScopeConditionId(condition_id as u16),
4591 element,
4592 false,
4594 &self.scope_subject_map,
4595 matching_context,
4596 );
4597 !result.candidates.is_empty()
4598 };
4599 result.scopes_matched.push(matches);
4600 }
4601 }
4602
4603 fn clear_cascade_data(&mut self) {
4605 self.normal_rules.clear();
4606 if let Some(ref mut slotted_rules) = self.slotted_rules {
4607 slotted_rules.clear();
4608 }
4609 if let Some(ref mut part_rules) = self.part_rules {
4610 part_rules.clear();
4611 }
4612 if let Some(ref mut host_rules) = self.featureless_host_rules {
4613 host_rules.clear();
4614 }
4615 self.animations.clear();
4616 self.custom_property_registrations.clear();
4617 self.layer_id.clear();
4618 self.layers.clear();
4619 self.layers.push(CascadeLayer::root());
4620 self.custom_media.clear();
4621 self.container_conditions.clear();
4622 self.container_conditions
4623 .push(ContainerConditionReference::none());
4624 self.scope_conditions.clear();
4625 self.scope_conditions.push(ScopeConditionReference::none());
4626 self.extra_data.clear();
4627 self.rules_source_order = 0;
4628 self.num_selectors = 0;
4629 self.num_declarations = 0;
4630 }
4631
4632 fn clear_invalidation_data(&mut self) {
4633 self.invalidation_map.clear();
4634 self.relative_selector_invalidation_map.clear();
4635 self.additional_relative_selector_invalidation_map.clear();
4636 self.attribute_dependencies.clear();
4637 self.nth_of_attribute_dependencies.clear();
4638 self.nth_of_custom_state_dependencies.clear();
4639 self.nth_of_class_dependencies.clear();
4640 self.state_dependencies = ElementState::empty();
4641 self.nth_of_state_dependencies = ElementState::empty();
4642 self.document_state_dependencies = DocumentState::empty();
4643 self.mapped_ids.clear();
4644 self.nth_of_mapped_ids.clear();
4645 self.selectors_for_cache_revalidation.clear();
4646 self.effective_media_query_results.clear();
4647 self.scope_subject_map.clear();
4648 }
4649}
4650
4651fn note_scope_selector_for_invalidation(
4652 quirks_mode: QuirksMode,
4653 scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4654 dependency_vector: &mut Vec<Dependency>,
4655 invalidation_map: &mut InvalidationMap,
4656 relative_selector_invalidation_map: &mut InvalidationMap,
4657 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4658 visitor: &mut StylistSelectorVisitor<'_>,
4659 scope_kind: ScopeDependencyInvalidationKind,
4660 s: &Selector<SelectorImpl>,
4661) -> Result<(), AllocErr> {
4662 let mut new_inner_dependencies = note_selector_for_invalidation(
4663 &s.clone(),
4664 quirks_mode,
4665 invalidation_map,
4666 relative_selector_invalidation_map,
4667 additional_relative_selector_invalidation_map,
4668 Some(&scope_dependencies),
4669 Some(scope_kind),
4670 )?;
4671 s.visit(visitor);
4672 new_inner_dependencies.as_mut().map(|dep| {
4673 dependency_vector.append(dep);
4674 });
4675 Ok(())
4676}
4677
4678fn build_scope_dependencies(
4679 quirks_mode: QuirksMode,
4680 mut cur_scope_inner_dependencies: Vec<Dependency>,
4681 mut visitor: StylistSelectorVisitor<'_>,
4682 cond: &ScopeBoundsWithHashes,
4683 mut invalidation_map: &mut InvalidationMap,
4684 mut relative_selector_invalidation_map: &mut InvalidationMap,
4685 mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4686) -> Result<Vec<Dependency>, AllocErr> {
4687 if cond.end.is_some() {
4688 let deps =
4689 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4690 let mut end_dependency_vector = Vec::new();
4691 for s in cond.end_selectors() {
4692 note_scope_selector_for_invalidation(
4693 quirks_mode,
4694 &deps,
4695 &mut end_dependency_vector,
4696 &mut invalidation_map,
4697 &mut relative_selector_invalidation_map,
4698 &mut additional_relative_selector_invalidation_map,
4699 &mut visitor,
4700 ScopeDependencyInvalidationKind::ScopeEnd,
4701 s,
4702 )?;
4703 }
4704 cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4705 }
4706 let inner_scope_dependencies =
4707 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4708
4709 Ok(if cond.start.is_some() {
4710 let mut dependency_vector = Vec::new();
4711 for s in cond.start_selectors() {
4712 note_scope_selector_for_invalidation(
4713 quirks_mode,
4714 &inner_scope_dependencies,
4715 &mut dependency_vector,
4716 &mut invalidation_map,
4717 &mut relative_selector_invalidation_map,
4718 &mut additional_relative_selector_invalidation_map,
4719 &mut visitor,
4720 ScopeDependencyInvalidationKind::ExplicitScope,
4721 s,
4722 )?;
4723 }
4724 dependency_vector
4725 } else {
4726 vec![Dependency::new(
4727 IMPLICIT_SCOPE.slice()[0].clone(),
4728 0,
4729 Some(inner_scope_dependencies),
4730 DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4731 )]
4732 })
4733}
4734
4735impl CascadeDataCacheEntry for CascadeData {
4736 fn rebuild<S>(
4737 device: &Device,
4738 quirks_mode: QuirksMode,
4739 collection: SheetCollectionFlusher<S>,
4740 guard: &SharedRwLockReadGuard,
4741 old: &Self,
4742 difference: &mut CascadeDataDifference,
4743 ) -> Result<Arc<Self>, AllocErr>
4744 where
4745 S: StylesheetInDocument + PartialEq + 'static,
4746 {
4747 debug_assert!(collection.dirty(), "We surely need to do something?");
4748 let mut updatable_entry = match collection.data_validity() {
4750 DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4751 DataValidity::FullyInvalid => Self::new(),
4752 };
4753 updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4754 Ok(Arc::new(updatable_entry))
4755 }
4756
4757 #[cfg(feature = "gecko")]
4758 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4759 self.normal_rules.add_size_of(ops, sizes);
4760 if let Some(ref slotted_rules) = self.slotted_rules {
4761 slotted_rules.add_size_of(ops, sizes);
4762 }
4763 if let Some(ref part_rules) = self.part_rules {
4764 part_rules.add_size_of(ops, sizes);
4765 }
4766 if let Some(ref host_rules) = self.featureless_host_rules {
4767 host_rules.add_size_of(ops, sizes);
4768 }
4769 sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4770 sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4771 sizes.mOther += self.animations.size_of(ops);
4772 sizes.mOther += self.effective_media_query_results.size_of(ops);
4773 sizes.mOther += self.extra_data.size_of(ops);
4774 }
4775}
4776
4777impl Default for CascadeData {
4778 fn default() -> Self {
4779 CascadeData::new()
4780 }
4781}
4782
4783#[derive(Clone, Debug, MallocSizeOf)]
4786pub struct Rule {
4787 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4792 pub selector: Selector<SelectorImpl>,
4793
4794 pub hashes: AncestorHashes,
4796
4797 pub source_order: u32,
4801
4802 pub layer_id: LayerId,
4804
4805 pub container_condition_id: ContainerConditionId,
4807
4808 pub is_starting_style: bool,
4810
4811 pub scope_condition_id: ScopeConditionId,
4813
4814 #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4816 pub style_source: StyleSource,
4817}
4818
4819impl SelectorMapEntry for Rule {
4820 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4821 self.selector.iter()
4822 }
4823}
4824
4825impl Rule {
4826 pub fn specificity(&self) -> u32 {
4828 self.selector.specificity()
4829 }
4830
4831 pub fn to_applicable_declaration_block(
4834 &self,
4835 level: CascadeLevel,
4836 cascade_data: &CascadeData,
4837 scope_proximity: ScopeProximity,
4838 ) -> ApplicableDeclarationBlock {
4839 ApplicableDeclarationBlock::new(
4840 self.style_source.clone(),
4841 self.source_order,
4842 level,
4843 self.specificity(),
4844 cascade_data.layer_order_for(self.layer_id),
4845 scope_proximity,
4846 )
4847 }
4848
4849 pub fn new(
4851 selector: Selector<SelectorImpl>,
4852 hashes: AncestorHashes,
4853 style_source: StyleSource,
4854 source_order: u32,
4855 layer_id: LayerId,
4856 container_condition_id: ContainerConditionId,
4857 is_starting_style: bool,
4858 scope_condition_id: ScopeConditionId,
4859 ) -> Self {
4860 Self {
4861 selector,
4862 hashes,
4863 style_source,
4864 source_order,
4865 layer_id,
4866 container_condition_id,
4867 is_starting_style,
4868 scope_condition_id,
4869 }
4870 }
4871}
4872
4873size_of_test!(Rule, 40);
4878
4879pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4881 let mut needs_revalidation = false;
4882 let mut mapped_ids = Default::default();
4883 let mut nth_of_mapped_ids = Default::default();
4884 let mut attribute_dependencies = Default::default();
4885 let mut nth_of_class_dependencies = Default::default();
4886 let mut nth_of_attribute_dependencies = Default::default();
4887 let mut nth_of_custom_state_dependencies = Default::default();
4888 let mut state_dependencies = ElementState::empty();
4889 let mut nth_of_state_dependencies = ElementState::empty();
4890 let mut document_state_dependencies = DocumentState::empty();
4891 let mut visitor = StylistSelectorVisitor {
4892 passed_rightmost_selector: false,
4893 needs_revalidation: &mut needs_revalidation,
4894 in_selector_list_of: SelectorListKind::default(),
4895 mapped_ids: &mut mapped_ids,
4896 nth_of_mapped_ids: &mut nth_of_mapped_ids,
4897 attribute_dependencies: &mut attribute_dependencies,
4898 nth_of_class_dependencies: &mut nth_of_class_dependencies,
4899 nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4900 nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4901 state_dependencies: &mut state_dependencies,
4902 nth_of_state_dependencies: &mut nth_of_state_dependencies,
4903 document_state_dependencies: &mut document_state_dependencies,
4904 };
4905 s.visit(&mut visitor);
4906 needs_revalidation
4907}