1use crate::applicable_declarations::{
8 ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
9};
10use crate::computed_value_flags::ComputedValueFlags;
11use crate::context::{CascadeInputs, QuirksMode, TreeCountingCaches};
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::dom::TShadowRoot;
19#[cfg(feature = "gecko")]
20use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
21use crate::invalidation::element::invalidation_map::{
22 note_selector_for_invalidation, AdditionalRelativeSelectorInvalidationMap, Dependency,
23 DependencyInvalidationKind, InvalidationMap, ScopeDependencyInvalidationKind,
24};
25use crate::invalidation::media_queries::{
26 EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
27};
28use crate::invalidation::stylesheets::{RuleChangeKind, StylesheetInvalidationSet};
29#[cfg(feature = "gecko")]
30use crate::properties::StyleBuilder;
31use crate::properties::{
32 self, AnimationDeclarations, CascadeMode, ComputedValues, FirstLineReparenting,
33 PropertyDeclarationBlock,
34};
35use crate::properties_and_values::registry::{
36 PropertyRegistration, ScriptRegistry as CustomPropertyScriptRegistry,
37};
38use crate::properties_and_values::rule::{
39 Descriptors as PropertyDescriptors, Inherits, PropertyRegistrationError, PropertyRuleName,
40};
41use crate::properties_and_values::syntax::Descriptor;
42use crate::rule_cache::{RuleCache, RuleCacheConditions};
43use crate::rule_collector::RuleCollector;
44use crate::rule_tree::{
45 CascadeLevel, CascadeOrigin, RuleCascadeFlags, RuleTree, StrongRuleNode, StyleSource,
46};
47use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
48use crate::selector_parser::{NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl};
49use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
50use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
51use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
52use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
53use crate::stylesheets::container_rule::ContainerCondition;
54use crate::stylesheets::import_rule::ImportLayer;
55use crate::stylesheets::keyframes_rule::KeyframesAnimation;
56use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
57use crate::stylesheets::scope_rule::{
58 collect_scope_roots, element_is_outside_of_scope, scope_selector_list_is_trivial,
59 ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget,
60};
61use crate::stylesheets::UrlExtraData;
62use crate::stylesheets::{
63 CounterStyleRule, CssRule, CssRuleRef, EffectiveRulesIterator, FontFaceRule,
64 FontFeatureValuesRule, FontPaletteValuesRule, Origin, OriginSet, PagePseudoClassFlags,
65 PageRule, PerOrigin, PerOriginIter, PositionTryRule, StylesheetContents, StylesheetInDocument,
66 ViewTransitionRule,
67};
68use crate::stylesheets::{CustomMediaEvaluator, CustomMediaMap};
69#[cfg(feature = "gecko")]
70use crate::values::specified::position::PositionTryFallbacksItem;
71use crate::values::specified::position::PositionTryFallbacksTryTactic;
72use crate::values::{computed, AtomIdent, Parser, SourceLocation};
73use crate::AllocErr;
74use crate::ArcSlice;
75use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
76use cssparser::ParserInput;
77use dom::{DocumentState, ElementState};
78#[cfg(feature = "gecko")]
79use malloc_size_of::MallocUnconditionalShallowSizeOf;
80use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
81use rustc_hash::FxHashMap;
82use selectors::attr::{CaseSensitivity, NamespaceConstraint};
83use selectors::bloom::BloomFilter;
84use selectors::matching::{
85 matches_selector, selector_may_match, MatchingContext, MatchingMode, NeedsSelectorFlags,
86 SelectorCaches,
87};
88use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
89use selectors::parser::{
90 AncestorHashes, Combinator, Component, MatchesFeaturelessHost, Selector, SelectorIter,
91 SelectorList,
92};
93use selectors::visitor::{SelectorListKind, SelectorVisitor};
94use servo_arc::{Arc, ArcBorrow, ThinArc};
95use smallvec::SmallVec;
96use std::cmp::Ordering;
97use std::hash::{Hash, Hasher};
98use std::mem;
99use std::sync::{LazyLock, Mutex};
100
101#[cfg(feature = "servo")]
103pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
104
105#[cfg(feature = "gecko")]
107pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
108
109#[derive(Debug, Clone)]
110struct StylesheetContentsPtr(Arc<StylesheetContents>);
111
112impl PartialEq for StylesheetContentsPtr {
113 #[inline]
114 fn eq(&self, other: &Self) -> bool {
115 Arc::ptr_eq(&self.0, &other.0)
116 }
117}
118
119impl Eq for StylesheetContentsPtr {}
120
121impl Hash for StylesheetContentsPtr {
122 fn hash<H: Hasher>(&self, state: &mut H) {
123 let contents: &StylesheetContents = &*self.0;
124 (contents as *const StylesheetContents).hash(state)
125 }
126}
127
128type StyleSheetContentList = Vec<StylesheetContentsPtr>;
129
130#[derive(Default, Debug, MallocSizeOf)]
132pub struct CascadeDataDifference {
133 pub changed_position_try_names: PrecomputedHashSet<Atom>,
135}
136
137impl CascadeDataDifference {
138 pub fn merge_with(&mut self, other: Self) {
140 self.changed_position_try_names
141 .extend(other.changed_position_try_names.into_iter())
142 }
143
144 pub fn is_empty(&self) -> bool {
146 self.changed_position_try_names.is_empty()
147 }
148
149 fn update(&mut self, old_data: &PositionTryMap, new_data: &PositionTryMap) {
150 let mut any_different_key = false;
151 let different_len = old_data.len() != new_data.len();
152 for (name, rules) in old_data.iter() {
153 let changed = match new_data.get(name) {
154 Some(new_rule) => !Arc::ptr_eq(&rules.last().unwrap().0, new_rule),
155 None => {
156 any_different_key = true;
157 true
158 },
159 };
160 if changed {
161 self.changed_position_try_names.insert(name.clone());
162 }
163 }
164
165 if any_different_key || different_len {
166 for name in new_data.keys() {
167 if !old_data.contains_key(name) {
169 self.changed_position_try_names.insert(name.clone());
170 }
171 }
172 }
173 }
174}
175
176#[derive(Debug, Hash, Default, PartialEq, Eq)]
178struct CascadeDataCacheKey {
179 media_query_results: Vec<MediaListKey>,
180 contents: StyleSheetContentList,
181}
182
183unsafe impl Send for CascadeDataCacheKey {}
184unsafe impl Sync for CascadeDataCacheKey {}
185
186trait CascadeDataCacheEntry: Sized {
187 fn rebuild<S>(
190 device: &Device,
191 quirks_mode: QuirksMode,
192 collection: SheetCollectionFlusher<S>,
193 guard: &SharedRwLockReadGuard,
194 old_entry: &Self,
195 difference: &mut CascadeDataDifference,
196 ) -> Result<Arc<Self>, AllocErr>
197 where
198 S: StylesheetInDocument + PartialEq + 'static;
199 #[cfg(feature = "gecko")]
201 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
202}
203
204struct CascadeDataCache<Entry> {
205 entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
206}
207
208impl<Entry> CascadeDataCache<Entry>
209where
210 Entry: CascadeDataCacheEntry,
211{
212 fn new() -> Self {
213 Self {
214 entries: Default::default(),
215 }
216 }
217
218 fn len(&self) -> usize {
219 self.entries.len()
220 }
221
222 fn lookup<'a, S>(
227 &'a mut self,
228 device: &Device,
229 quirks_mode: QuirksMode,
230 collection: SheetCollectionFlusher<S>,
231 guard: &SharedRwLockReadGuard,
232 old_entry: &Entry,
233 difference: &mut CascadeDataDifference,
234 ) -> Result<Option<Arc<Entry>>, AllocErr>
235 where
236 S: StylesheetInDocument + PartialEq + 'static,
237 {
238 use std::collections::hash_map::Entry as HashMapEntry;
239 debug!("StyleSheetCache::lookup({})", self.len());
240
241 if !collection.dirty() {
242 return Ok(None);
243 }
244
245 let mut key = CascadeDataCacheKey::default();
246 let mut custom_media_map = CustomMediaMap::default();
247 for sheet in collection.sheets() {
248 CascadeData::collect_applicable_media_query_results_into(
249 device,
250 sheet,
251 guard,
252 &mut key.media_query_results,
253 &mut key.contents,
254 &mut custom_media_map,
255 )
256 }
257
258 let new_entry;
259 match self.entries.entry(key) {
260 HashMapEntry::Vacant(e) => {
261 debug!("> Picking the slow path (not in the cache)");
262 new_entry = Entry::rebuild(
263 device,
264 quirks_mode,
265 collection,
266 guard,
267 old_entry,
268 difference,
269 )?;
270 e.insert(new_entry.clone());
271 },
272 HashMapEntry::Occupied(mut e) => {
273 if !std::ptr::eq(&**e.get(), old_entry) {
277 if log_enabled!(log::Level::Debug) {
278 debug!("cache hit for:");
279 for sheet in collection.sheets() {
280 debug!(" > {:?}", sheet);
281 }
282 }
283 collection.each(|_, _, _| true);
286 return Ok(Some(e.get().clone()));
287 }
288
289 debug!("> Picking the slow path due to same entry as old");
290 new_entry = Entry::rebuild(
291 device,
292 quirks_mode,
293 collection,
294 guard,
295 old_entry,
296 difference,
297 )?;
298 e.insert(new_entry.clone());
299 },
300 }
301
302 Ok(Some(new_entry))
303 }
304
305 fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
313 let mut unused = SmallVec::new();
314 self.entries.retain(|_key, value| {
315 if !value.is_unique() {
319 return true;
320 }
321 unused.push(value.clone());
322 false
323 });
324 unused
325 }
326
327 fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
328 mem::take(&mut self.entries)
329 }
330
331 #[cfg(feature = "gecko")]
332 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
333 sizes.mOther += self.entries.shallow_size_of(ops);
334 for (_key, arc) in self.entries.iter() {
335 sizes.mOther += arc.unconditional_shallow_size_of(ops);
338 arc.add_size_of(ops, sizes);
339 }
340 }
341}
342
343#[cfg(feature = "gecko")]
345pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
346 UA_CASCADE_DATA_CACHE
347 .lock()
348 .unwrap()
349 .add_size_of(ops, sizes);
350}
351
352static UA_CASCADE_DATA_CACHE: LazyLock<Mutex<UserAgentCascadeDataCache>> =
354 LazyLock::new(|| Mutex::new(UserAgentCascadeDataCache::new()));
355
356impl CascadeDataCacheEntry for UserAgentCascadeData {
357 fn rebuild<S>(
358 device: &Device,
359 quirks_mode: QuirksMode,
360 collection: SheetCollectionFlusher<S>,
361 guard: &SharedRwLockReadGuard,
362 old: &Self,
363 difference: &mut CascadeDataDifference,
364 ) -> Result<Arc<Self>, AllocErr>
365 where
366 S: StylesheetInDocument + PartialEq + 'static,
367 {
368 let mut new_data = servo_arc::UniqueArc::new(Self {
371 cascade_data: CascadeData::new(),
372 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
373 });
374
375 for (index, sheet) in collection.sheets().enumerate() {
376 let new_data = &mut *new_data;
377 new_data.cascade_data.add_stylesheet(
378 device,
379 quirks_mode,
380 sheet,
381 index,
382 guard,
383 SheetRebuildKind::Full,
384 Some(&mut new_data.precomputed_pseudo_element_decls),
385 None,
386 )?;
387 }
388
389 new_data.cascade_data.did_finish_rebuild();
390 difference.update(
391 &old.cascade_data.extra_data.position_try_rules,
392 &new_data.cascade_data.extra_data.position_try_rules,
393 );
394
395 Ok(new_data.shareable())
396 }
397
398 #[cfg(feature = "gecko")]
399 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
400 self.cascade_data.add_size_of(ops, sizes);
401 sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
402 }
403}
404
405type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
406
407type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
408
409#[derive(Default)]
410struct UserAgentCascadeData {
411 cascade_data: CascadeData,
412
413 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
420}
421
422static EMPTY_UA_CASCADE_DATA: LazyLock<Arc<UserAgentCascadeData>> = LazyLock::new(|| {
424 let arc = Arc::new(UserAgentCascadeData::default());
425 arc.mark_as_intentionally_leaked();
426 arc
427});
428
429#[derive(MallocSizeOf)]
432pub struct DocumentCascadeData {
433 #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
434 user_agent: Arc<UserAgentCascadeData>,
435 user: CascadeData,
436 author: CascadeData,
437 per_origin: PerOrigin<()>,
438}
439
440impl Default for DocumentCascadeData {
441 fn default() -> Self {
442 Self {
443 user_agent: EMPTY_UA_CASCADE_DATA.clone(),
444 user: Default::default(),
445 author: Default::default(),
446 per_origin: Default::default(),
447 }
448 }
449}
450
451pub struct DocumentCascadeDataIter<'a> {
453 iter: PerOriginIter<'a, ()>,
454 cascade_data: &'a DocumentCascadeData,
455}
456
457impl<'a> Iterator for DocumentCascadeDataIter<'a> {
458 type Item = (&'a CascadeData, Origin);
459
460 fn next(&mut self) -> Option<Self::Item> {
461 let (_, origin) = self.iter.next()?;
462 Some((self.cascade_data.borrow_for_origin(origin), origin))
463 }
464}
465
466impl DocumentCascadeData {
467 #[inline]
469 pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
470 match origin {
471 Origin::UserAgent => &self.user_agent.cascade_data,
472 Origin::Author => &self.author,
473 Origin::User => &self.user,
474 }
475 }
476
477 fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
478 DocumentCascadeDataIter {
479 iter: self.per_origin.iter_origins(),
480 cascade_data: self,
481 }
482 }
483
484 fn iter_origins_rev(&self) -> DocumentCascadeDataIter<'_> {
485 DocumentCascadeDataIter {
486 iter: self.per_origin.iter_origins_rev(),
487 cascade_data: self,
488 }
489 }
490
491 fn custom_media_for_sheet(
492 &self,
493 s: &StylistSheet,
494 guard: &SharedRwLockReadGuard,
495 ) -> &CustomMediaMap {
496 let origin = s.contents(guard).origin;
497 &self.borrow_for_origin(origin).custom_media
498 }
499
500 fn rebuild<'a, S>(
504 &mut self,
505 device: &Device,
506 quirks_mode: QuirksMode,
507 mut flusher: DocumentStylesheetFlusher<'a, S>,
508 guards: &StylesheetGuards,
509 difference: &mut CascadeDataDifference,
510 ) -> Result<(), AllocErr>
511 where
512 S: StylesheetInDocument + PartialEq + 'static,
513 {
514 {
516 let origin_flusher = flusher.flush_origin(Origin::UserAgent);
517 if origin_flusher.dirty() {
520 let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
521 let new_data = ua_cache.lookup(
522 device,
523 quirks_mode,
524 origin_flusher,
525 guards.ua_or_user,
526 &self.user_agent,
527 difference,
528 )?;
529 if let Some(new_data) = new_data {
530 self.user_agent = new_data;
531 }
532 let _unused_entries = ua_cache.take_unused();
533 std::mem::drop(ua_cache);
535 }
536 }
537
538 self.user.rebuild(
540 device,
541 quirks_mode,
542 flusher.flush_origin(Origin::User),
543 guards.ua_or_user,
544 difference,
545 )?;
546
547 self.author.rebuild(
549 device,
550 quirks_mode,
551 flusher.flush_origin(Origin::Author),
552 guards.author,
553 difference,
554 )?;
555
556 Ok(())
557 }
558
559 #[cfg(feature = "gecko")]
561 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
562 self.user.add_size_of(ops, sizes);
563 self.author.add_size_of(ops, sizes);
564 }
565}
566
567#[allow(missing_docs)]
571#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
572pub enum AuthorStylesEnabled {
573 Yes,
574 No,
575}
576
577#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
580#[derive(Deref, DerefMut)]
581struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
582unsafe impl Sync for StylistStylesheetSet {}
584
585impl StylistStylesheetSet {
586 fn new() -> Self {
587 StylistStylesheetSet(DocumentStylesheetSet::new())
588 }
589}
590
591#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
599pub struct Stylist {
600 device: Device,
613
614 stylesheets: StylistStylesheetSet,
616
617 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "XXX: how to handle this?")]
619 author_data_cache: CascadeDataCache<CascadeData>,
620
621 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
623 quirks_mode: QuirksMode,
624
625 cascade_data: DocumentCascadeData,
629
630 author_styles_enabled: AuthorStylesEnabled,
632
633 rule_tree: RuleTree,
635
636 script_custom_properties: CustomPropertyScriptRegistry,
639
640 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
642 initial_values_for_custom_properties: ComputedCustomProperties,
643
644 initial_values_for_custom_properties_flags: ComputedValueFlags,
646
647 num_rebuilds: usize,
649}
650
651#[derive(Clone, Copy, PartialEq)]
653pub enum RuleInclusion {
654 All,
657 DefaultOnly,
660}
661
662#[cfg(feature = "gecko")]
663impl From<StyleRuleInclusion> for RuleInclusion {
664 fn from(value: StyleRuleInclusion) -> Self {
665 match value {
666 StyleRuleInclusion::All => RuleInclusion::All,
667 StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
668 }
669 }
670}
671
672#[derive(Clone, Copy, Eq, PartialEq)]
677enum ScopeMatchesShadowHost {
678 NotApplicable,
679 No,
680 Yes,
681}
682
683impl Default for ScopeMatchesShadowHost {
684 fn default() -> Self {
685 Self::NotApplicable
686 }
687}
688
689impl ScopeMatchesShadowHost {
690 fn nest_for_scope(&mut self, matches_shadow_host: bool) {
691 match *self {
692 Self::NotApplicable => {
693 *self = if matches_shadow_host {
695 Self::Yes
696 } else {
697 Self::No
698 };
699 },
700 Self::Yes if !matches_shadow_host => {
701 *self = Self::No;
703 },
704 _ => (),
705 }
706 }
707}
708
709#[derive(Copy, Clone)]
716enum NestedDeclarationsContext {
717 Style,
718 Scope,
719}
720
721struct ContainingScopeRuleState {
723 id: ScopeConditionId,
724 inner_dependencies: Vec<Dependency>,
725 matches_shadow_host: ScopeMatchesShadowHost,
726}
727
728impl Default for ContainingScopeRuleState {
729 fn default() -> Self {
730 Self {
731 id: ScopeConditionId::none(),
732 inner_dependencies: Vec::new(),
733 matches_shadow_host: Default::default(),
734 }
735 }
736}
737
738impl ContainingScopeRuleState {
739 fn save(&self) -> SavedContainingScopeRuleState {
740 SavedContainingScopeRuleState {
741 id: self.id,
742 matches_shadow_host: self.matches_shadow_host,
743 inner_dependencies_len: self.inner_dependencies.len(),
744 }
745 }
746
747 fn restore(
748 &mut self,
749 saved: &SavedContainingScopeRuleState,
750 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
751 debug_assert!(self.inner_dependencies.len() >= saved.inner_dependencies_len);
752
753 if self.id == saved.id {
754 return None;
755 }
756
757 let scope_id = self.id;
758 let inner_deps = self
759 .inner_dependencies
760 .drain(saved.inner_dependencies_len..)
761 .collect();
762
763 self.id = saved.id;
764 self.matches_shadow_host = saved.matches_shadow_host;
765
766 Some((inner_deps, scope_id))
767 }
768}
769
770struct SavedContainingScopeRuleState {
771 id: ScopeConditionId,
772 matches_shadow_host: ScopeMatchesShadowHost,
773 inner_dependencies_len: usize,
774}
775
776struct ContainingRuleState {
779 layer_name: LayerName,
780 layer_id: LayerId,
781 container_condition_id: ContainerConditionId,
782 cascade_flags: RuleCascadeFlags,
783 containing_scope_rule_state: ContainingScopeRuleState,
784 ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
785 nested_declarations_context: NestedDeclarationsContext,
786}
787
788impl Default for ContainingRuleState {
789 fn default() -> Self {
790 Self {
791 layer_name: LayerName::new_empty(),
792 layer_id: LayerId::root(),
793 container_condition_id: ContainerConditionId::none(),
794 cascade_flags: RuleCascadeFlags::empty(),
795 ancestor_selector_lists: Default::default(),
796 containing_scope_rule_state: Default::default(),
797 nested_declarations_context: NestedDeclarationsContext::Style,
798 }
799 }
800}
801
802struct SavedContainingRuleState {
803 ancestor_selector_lists_len: usize,
804 layer_name_len: usize,
805 layer_id: LayerId,
806 container_condition_id: ContainerConditionId,
807 cascade_flags: RuleCascadeFlags,
808 saved_containing_scope_rule_state: SavedContainingScopeRuleState,
809 nested_declarations_context: NestedDeclarationsContext,
810}
811
812impl ContainingRuleState {
813 fn save(&self) -> SavedContainingRuleState {
814 SavedContainingRuleState {
815 ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
816 layer_name_len: self.layer_name.0.len(),
817 layer_id: self.layer_id,
818 container_condition_id: self.container_condition_id,
819 cascade_flags: self.cascade_flags,
820 saved_containing_scope_rule_state: self.containing_scope_rule_state.save(),
821 nested_declarations_context: self.nested_declarations_context,
822 }
823 }
824
825 fn restore(
826 &mut self,
827 saved: &SavedContainingRuleState,
828 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
829 debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
830 debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
831
832 self.ancestor_selector_lists
833 .truncate(saved.ancestor_selector_lists_len);
834 self.layer_name.0.truncate(saved.layer_name_len);
835 self.layer_id = saved.layer_id;
836 self.container_condition_id = saved.container_condition_id;
837 self.cascade_flags = saved.cascade_flags;
838 self.nested_declarations_context = saved.nested_declarations_context;
839
840 self.containing_scope_rule_state
841 .restore(&saved.saved_containing_scope_rule_state)
842 }
843
844 fn scope_is_effective(&self) -> bool {
845 self.containing_scope_rule_state.id != ScopeConditionId::none()
846 }
847
848 fn cascade_flags(&self) -> RuleCascadeFlags {
849 self.cascade_flags
850 }
851}
852
853type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
854
855impl Stylist {
856 #[inline]
860 pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
861 Self {
862 device,
863 quirks_mode,
864 stylesheets: StylistStylesheetSet::new(),
865 author_data_cache: CascadeDataCache::new(),
866 cascade_data: Default::default(),
867 author_styles_enabled: AuthorStylesEnabled::Yes,
868 rule_tree: RuleTree::new(),
869 script_custom_properties: Default::default(),
870 initial_values_for_custom_properties: Default::default(),
871 initial_values_for_custom_properties_flags: Default::default(),
872 num_rebuilds: 0,
873 }
874 }
875
876 #[inline]
878 pub fn cascade_data(&self) -> &DocumentCascadeData {
879 &self.cascade_data
880 }
881
882 #[inline]
884 pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
885 self.author_styles_enabled
886 }
887
888 #[inline]
890 pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
891 self.cascade_data.iter_origins()
892 }
893
894 pub fn remove_unique_author_data_cache_entries(&mut self) {
897 self.author_data_cache.take_unused();
898 }
899
900 pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyDescriptors {
903 if let Some(registration) = self.custom_property_script_registry().get(name) {
904 return ®istration.descriptors;
905 }
906 for (data, _) in self.iter_origins() {
907 if let Some(registration) = data.custom_property_registrations.get(name) {
908 return ®istration.descriptors;
909 }
910 }
911 PropertyDescriptors::unregistered()
912 }
913
914 pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
916 &self.initial_values_for_custom_properties
917 }
918
919 pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
921 self.initial_values_for_custom_properties_flags
922 }
923
924 pub fn rebuild_initial_values_for_custom_properties(&mut self) {
927 let mut initial_values = ComputedCustomProperties::default();
928 let initial_values_flags;
929 {
930 let mut seen_names = PrecomputedHashSet::default();
931 let mut rule_cache_conditions = RuleCacheConditions::default();
932 let mut tree_counting_caches = TreeCountingCaches::default();
933 let context = computed::Context::new_for_initial_at_property_value(
934 self,
935 &mut rule_cache_conditions,
936 &mut tree_counting_caches,
937 );
938
939 for (k, v) in self.custom_property_script_registry().properties().iter() {
940 seen_names.insert(k.clone());
941 let Ok(value) = v.compute_initial_value(&context) else {
942 continue;
943 };
944 let map = if v.descriptors.inherits() {
945 &mut initial_values.inherited
946 } else {
947 &mut initial_values.non_inherited
948 };
949 map.insert(k, value);
950 }
951 for (data, _) in self.iter_origins() {
952 for (k, v) in data.custom_property_registrations.iter() {
953 if seen_names.insert(k.clone()) {
954 let last_value = &v.last().unwrap().0;
955 let Ok(value) = last_value.compute_initial_value(&context) else {
956 continue;
957 };
958 let map = if last_value.descriptors.inherits() {
959 &mut initial_values.inherited
960 } else {
961 &mut initial_values.non_inherited
962 };
963 map.insert(k, value);
964 }
965 }
966 }
967 initial_values_flags = context.builder.flags();
968 }
969 self.initial_values_for_custom_properties_flags = initial_values_flags;
970 self.initial_values_for_custom_properties = initial_values;
971 }
972
973 pub fn rebuild_author_data<S>(
975 &mut self,
976 old_data: &CascadeData,
977 collection: SheetCollectionFlusher<S>,
978 guard: &SharedRwLockReadGuard,
979 difference: &mut CascadeDataDifference,
980 ) -> Result<Option<Arc<CascadeData>>, AllocErr>
981 where
982 S: StylesheetInDocument + PartialEq + 'static,
983 {
984 self.author_data_cache.lookup(
985 &self.device,
986 self.quirks_mode,
987 collection,
988 guard,
989 old_data,
990 difference,
991 )
992 }
993
994 #[inline]
996 pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
997 ExtraStyleDataIterator(self.cascade_data.iter_origins())
998 }
999
1000 #[inline]
1002 pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
1003 ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
1004 }
1005
1006 pub fn num_selectors(&self) -> usize {
1008 self.cascade_data
1009 .iter_origins()
1010 .map(|(d, _)| d.num_selectors)
1011 .sum()
1012 }
1013
1014 pub fn num_declarations(&self) -> usize {
1016 self.cascade_data
1017 .iter_origins()
1018 .map(|(d, _)| d.num_declarations)
1019 .sum()
1020 }
1021
1022 pub fn num_rebuilds(&self) -> usize {
1024 self.num_rebuilds
1025 }
1026
1027 pub fn num_revalidation_selectors(&self) -> usize {
1029 self.cascade_data
1030 .iter_origins()
1031 .map(|(data, _)| data.selectors_for_cache_revalidation.len())
1032 .sum()
1033 }
1034
1035 pub fn num_invalidations(&self) -> usize {
1037 self.cascade_data
1038 .iter_origins()
1039 .map(|(data, _)| {
1040 data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
1041 })
1042 .sum()
1043 }
1044
1045 pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
1048 self.cascade_data
1049 .iter_origins()
1050 .any(|(d, _)| d.document_state_dependencies.intersects(state))
1051 }
1052
1053 pub fn flush(&mut self, guards: &StylesheetGuards) -> StylesheetInvalidationSet {
1056 if !self.stylesheets.has_changed() {
1057 return Default::default();
1058 }
1059
1060 self.num_rebuilds += 1;
1061
1062 let (flusher, mut invalidations) = self.stylesheets.flush();
1063
1064 self.cascade_data
1065 .rebuild(
1066 &self.device,
1067 self.quirks_mode,
1068 flusher,
1069 guards,
1070 &mut invalidations.cascade_data_difference,
1071 )
1072 .unwrap_or_else(|_| {
1073 warn!("OOM in Stylist::flush");
1074 });
1075
1076 self.rebuild_initial_values_for_custom_properties();
1077 invalidations
1078 }
1079
1080 pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
1086 self.stylesheets.force_dirty(origins)
1087 }
1088
1089 pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
1091 self.author_styles_enabled = enabled;
1092 }
1093
1094 pub fn stylesheets_have_changed(&self) -> bool {
1096 self.stylesheets.has_changed()
1097 }
1098
1099 pub fn insert_stylesheet_before(
1101 &mut self,
1102 sheet: StylistSheet,
1103 before_sheet: StylistSheet,
1104 guard: &SharedRwLockReadGuard,
1105 ) {
1106 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1107 self.stylesheets.insert_stylesheet_before(
1108 Some(&self.device),
1109 custom_media,
1110 sheet,
1111 before_sheet,
1112 guard,
1113 )
1114 }
1115
1116 pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1118 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1119 self.stylesheets
1120 .append_stylesheet(Some(&self.device), custom_media, sheet, guard)
1121 }
1122
1123 pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1125 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1126 self.stylesheets
1127 .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
1128 }
1129
1130 pub fn rule_changed(
1132 &mut self,
1133 sheet: &StylistSheet,
1134 rule: &CssRule,
1135 guard: &SharedRwLockReadGuard,
1136 change_kind: RuleChangeKind,
1137 ancestors: &[CssRuleRef],
1138 ) {
1139 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1140 self.stylesheets.rule_changed(
1141 Some(&self.device),
1142 custom_media,
1143 sheet,
1144 rule,
1145 guard,
1146 change_kind,
1147 ancestors,
1148 )
1149 }
1150
1151 #[inline]
1153 pub fn sheet_count(&self, origin: Origin) -> usize {
1154 self.stylesheets.sheet_count(origin)
1155 }
1156
1157 #[inline]
1159 pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
1160 self.stylesheets.get(origin, index)
1161 }
1162
1163 pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
1166 where
1167 E: TElement,
1168 F: FnMut(&CascadeData) -> bool,
1169 {
1170 if f(&self.cascade_data.user_agent.cascade_data) {
1171 return true;
1172 }
1173
1174 let mut maybe = false;
1175
1176 let doc_author_rules_apply =
1177 element.each_applicable_non_document_style_rule_data(|data, _| {
1178 maybe = maybe || f(&*data);
1179 });
1180
1181 if maybe || f(&self.cascade_data.user) {
1182 return true;
1183 }
1184
1185 doc_author_rules_apply && f(&self.cascade_data.author)
1186 }
1187
1188 pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1190 where
1191 E: TElement + 'a,
1192 F: FnMut(&'a CascadeData, Option<E>),
1193 {
1194 f(&self.cascade_data.user_agent.cascade_data, None);
1195 element.each_applicable_non_document_style_rule_data(|data, scope| {
1196 f(data, Some(scope));
1197 });
1198 f(&self.cascade_data.user, None);
1199 f(&self.cascade_data.author, None);
1200 }
1201
1202 pub fn precomputed_values_for_pseudo<E>(
1205 &self,
1206 guards: &StylesheetGuards,
1207 pseudo: &PseudoElement,
1208 parent: Option<&ComputedValues>,
1209 ) -> Arc<ComputedValues>
1210 where
1211 E: TElement,
1212 {
1213 debug_assert!(pseudo.is_precomputed());
1214
1215 let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1216
1217 self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1218 }
1219
1220 pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1226 &self,
1227 guards: &StylesheetGuards,
1228 pseudo: &PseudoElement,
1229 parent: Option<&ComputedValues>,
1230 rules: StrongRuleNode,
1231 ) -> Arc<ComputedValues>
1232 where
1233 E: TElement,
1234 {
1235 self.compute_pseudo_element_style_with_inputs::<E>(
1236 CascadeInputs {
1237 rules: Some(rules),
1238 visited_rules: None,
1239 flags: Default::default(),
1240 included_cascade_flags: RuleCascadeFlags::empty(),
1241 },
1242 pseudo,
1243 guards,
1244 parent,
1245 None,
1246 )
1247 }
1248
1249 pub fn rule_node_for_precomputed_pseudo(
1255 &self,
1256 guards: &StylesheetGuards,
1257 pseudo: &PseudoElement,
1258 mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1259 ) -> StrongRuleNode {
1260 let mut declarations_with_extra;
1261 let declarations = match self
1262 .cascade_data
1263 .user_agent
1264 .precomputed_pseudo_element_decls
1265 .get(pseudo)
1266 {
1267 Some(declarations) => {
1268 if !extra_declarations.is_empty() {
1269 declarations_with_extra = declarations.clone();
1270 declarations_with_extra.append(&mut extra_declarations);
1271 &*declarations_with_extra
1272 } else {
1273 &**declarations
1274 }
1275 },
1276 None => &[],
1277 };
1278
1279 self.rule_tree.insert_ordered_rules_with_important(
1280 declarations.into_iter().map(|a| a.clone().for_rule_tree()),
1281 guards,
1282 )
1283 }
1284
1285 #[cfg(feature = "servo")]
1290 pub fn style_for_anonymous<E>(
1291 &self,
1292 guards: &StylesheetGuards,
1293 pseudo: &PseudoElement,
1294 parent_style: &ComputedValues,
1295 ) -> Arc<ComputedValues>
1296 where
1297 E: TElement,
1298 {
1299 self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1300 }
1301
1302 pub fn lazily_compute_pseudo_element_style<E>(
1310 &self,
1311 guards: &StylesheetGuards,
1312 element: E,
1313 pseudo: &PseudoElement,
1314 rule_inclusion: RuleInclusion,
1315 originating_element_style: &ComputedValues,
1316 is_probe: bool,
1317 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1318 ) -> Option<Arc<ComputedValues>>
1319 where
1320 E: TElement,
1321 {
1322 let cascade_inputs = self.lazy_pseudo_rules(
1323 guards,
1324 element,
1325 originating_element_style,
1326 pseudo,
1327 is_probe,
1328 rule_inclusion,
1329 matching_fn,
1330 )?;
1331
1332 Some(self.compute_pseudo_element_style_with_inputs(
1333 cascade_inputs,
1334 pseudo,
1335 guards,
1336 Some(originating_element_style),
1337 Some(element),
1338 ))
1339 }
1340
1341 pub fn compute_pseudo_element_style_with_inputs<E>(
1346 &self,
1347 inputs: CascadeInputs,
1348 pseudo: &PseudoElement,
1349 guards: &StylesheetGuards,
1350 parent_style: Option<&ComputedValues>,
1351 element: Option<E>,
1352 ) -> Arc<ComputedValues>
1353 where
1354 E: TElement,
1355 {
1356 self.cascade_style_and_visited(
1369 element,
1370 Some(pseudo),
1371 &inputs,
1372 guards,
1373 parent_style,
1374 parent_style,
1375 FirstLineReparenting::No,
1376 &PositionTryFallbacksTryTactic::default(),
1377 None,
1378 &mut RuleCacheConditions::default(),
1379 &mut TreeCountingCaches::default(),
1380 )
1381 }
1382
1383 #[cfg(feature = "gecko")]
1385 pub fn resolve_position_try<E>(
1386 &self,
1387 style: &ComputedValues,
1388 guards: &StylesheetGuards,
1389 scope: CascadeLevel,
1390 element: E,
1391 fallback_item: &PositionTryFallbacksItem,
1392 ) -> Option<Arc<ComputedValues>>
1393 where
1394 E: TElement,
1395 {
1396 let name_and_try_tactic = match *fallback_item {
1397 PositionTryFallbacksItem::PositionArea(area) => {
1398 let mut builder =
1402 StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
1403 builder.rules = style.rules.clone();
1404 builder.mutate_position().set_position_area(area);
1405 return Some(builder.build());
1406 },
1407 PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
1408 name_and_try_tactic
1409 },
1410 };
1411
1412 let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
1413 Some(self.lookup_position_try(&name_and_try_tactic.ident.0, scope, element)?)
1414 } else {
1415 None
1416 };
1417 let fallback_block = fallback_rule
1418 .as_ref()
1419 .map(|r| &r.read_with(guards.author).block);
1420 let pseudo = style
1421 .pseudo()
1422 .or_else(|| element.implemented_pseudo_element());
1423 let inputs = {
1424 let mut inputs = CascadeInputs::new_from_style(style);
1425 inputs.visited_rules = None;
1427 let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
1428 let mut important_rules_changed = false;
1429 if let Some(fallback_block) = fallback_block {
1430 let new_rules = self.rule_tree.update_rule_at_level(
1431 CascadeLevel::new(CascadeOrigin::PositionFallback),
1432 LayerOrder::root(),
1433 Some(fallback_block.borrow_arc()),
1434 rules,
1435 guards,
1436 &mut important_rules_changed,
1437 );
1438 if new_rules.is_some() {
1439 inputs.rules = new_rules;
1440 } else {
1441 }
1445 }
1446 inputs
1447 };
1448 crate::style_resolver::with_default_parent_styles(
1449 element,
1450 |parent_style, layout_parent_style| {
1451 Some(self.cascade_style_and_visited(
1452 Some(element),
1453 pseudo.as_ref(),
1454 &inputs,
1455 guards,
1456 parent_style,
1457 layout_parent_style,
1458 FirstLineReparenting::No,
1459 &name_and_try_tactic.try_tactic,
1460 None,
1461 &mut RuleCacheConditions::default(),
1462 &mut TreeCountingCaches::default(),
1463 ))
1464 },
1465 )
1466 }
1467
1468 pub fn cascade_style_and_visited<E>(
1481 &self,
1482 element: Option<E>,
1483 pseudo: Option<&PseudoElement>,
1484 inputs: &CascadeInputs,
1485 guards: &StylesheetGuards,
1486 parent_style: Option<&ComputedValues>,
1487 layout_parent_style: Option<&ComputedValues>,
1488 first_line_reparenting: FirstLineReparenting,
1489 try_tactic: &PositionTryFallbacksTryTactic,
1490 rule_cache: Option<&RuleCache>,
1491 rule_cache_conditions: &mut RuleCacheConditions,
1492 tree_counting_caches: &mut TreeCountingCaches,
1493 ) -> Arc<ComputedValues>
1494 where
1495 E: TElement,
1496 {
1497 debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1498
1499 let visited_rules = match inputs.visited_rules.as_ref() {
1502 Some(rules) => Some(rules),
1503 None => {
1504 if parent_style.and_then(|s| s.visited_style()).is_some() {
1505 Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1506 } else {
1507 None
1508 }
1509 },
1510 };
1511
1512 let mut implemented_pseudo = None;
1513 properties::cascade::<E>(
1520 &self,
1521 pseudo.or_else(|| {
1522 implemented_pseudo = element.unwrap().implemented_pseudo_element();
1523 implemented_pseudo.as_ref()
1524 }),
1525 inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1526 guards,
1527 parent_style,
1528 layout_parent_style,
1529 first_line_reparenting,
1530 try_tactic,
1531 visited_rules,
1532 inputs.flags,
1533 inputs.included_cascade_flags,
1534 rule_cache,
1535 rule_cache_conditions,
1536 element,
1537 tree_counting_caches,
1538 )
1539 }
1540
1541 fn lazy_pseudo_rules<E>(
1546 &self,
1547 guards: &StylesheetGuards,
1548 element: E,
1549 originating_element_style: &ComputedValues,
1550 pseudo: &PseudoElement,
1551 is_probe: bool,
1552 rule_inclusion: RuleInclusion,
1553 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1554 ) -> Option<CascadeInputs>
1555 where
1556 E: TElement,
1557 {
1558 debug_assert!(pseudo.is_lazy());
1559
1560 let mut selector_caches = SelectorCaches::default();
1561 let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1564 NeedsSelectorFlags::No
1565 } else {
1566 NeedsSelectorFlags::Yes
1567 };
1568
1569 let mut declarations = ApplicableDeclarationList::new();
1570 let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1571 MatchingMode::ForStatelessPseudoElement,
1572 None,
1573 &mut selector_caches,
1574 self.quirks_mode,
1575 needs_selector_flags,
1576 MatchingForInvalidation::No,
1577 );
1578
1579 matching_context.pseudo_element_matching_fn = matching_fn;
1580 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1581
1582 self.push_applicable_declarations(
1583 element,
1584 Some(&pseudo),
1585 None,
1586 None,
1587 Default::default(),
1588 rule_inclusion,
1589 &mut declarations,
1590 &mut matching_context,
1591 );
1592
1593 if declarations.is_empty() && is_probe {
1594 return None;
1595 }
1596
1597 let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1598
1599 let mut visited_rules = None;
1600 if originating_element_style.visited_style().is_some() {
1601 let mut declarations = ApplicableDeclarationList::new();
1602 let mut selector_caches = SelectorCaches::default();
1603
1604 let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1605 MatchingMode::ForStatelessPseudoElement,
1606 None,
1607 &mut selector_caches,
1608 VisitedHandlingMode::RelevantLinkVisited,
1609 self.quirks_mode,
1610 needs_selector_flags,
1611 MatchingForInvalidation::No,
1612 );
1613 matching_context.pseudo_element_matching_fn = matching_fn;
1614 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1615
1616 self.push_applicable_declarations(
1617 element,
1618 Some(&pseudo),
1619 None,
1620 None,
1621 Default::default(),
1622 rule_inclusion,
1623 &mut declarations,
1624 &mut matching_context,
1625 );
1626 if !declarations.is_empty() {
1627 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1628 declarations.drain(..).map(|a| a.for_rule_tree()),
1629 guards,
1630 );
1631 if rule_node != *self.rule_tree.root() {
1632 visited_rules = Some(rule_node);
1633 }
1634 }
1635 }
1636
1637 Some(CascadeInputs {
1638 rules: Some(rules),
1639 visited_rules,
1640 flags: matching_context.extra_data.cascade_input_flags,
1641 included_cascade_flags: RuleCascadeFlags::empty(),
1642 })
1643 }
1644
1645 pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1656 self.device = device;
1657 self.media_features_change_changed_style(guards, &self.device)
1658 }
1659
1660 pub fn media_features_change_changed_style(
1664 &self,
1665 guards: &StylesheetGuards,
1666 device: &Device,
1667 ) -> OriginSet {
1668 debug!("Stylist::media_features_change_changed_style {:?}", device);
1669
1670 let mut origins = OriginSet::empty();
1671 let stylesheets = self.stylesheets.iter();
1672
1673 for (stylesheet, origin) in stylesheets {
1674 if origins.contains(origin.into()) {
1675 continue;
1676 }
1677
1678 let guard = guards.for_origin(origin);
1679 let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1680
1681 let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1682 stylesheet,
1683 guard,
1684 device,
1685 self.quirks_mode,
1686 );
1687
1688 if affected_changed {
1689 origins |= origin;
1690 }
1691 }
1692
1693 origins
1694 }
1695
1696 pub fn quirks_mode(&self) -> QuirksMode {
1698 self.quirks_mode
1699 }
1700
1701 pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1703 if self.quirks_mode == quirks_mode {
1704 return;
1705 }
1706 self.quirks_mode = quirks_mode;
1707 self.force_stylesheet_origins_dirty(OriginSet::all());
1708 }
1709
1710 pub fn push_applicable_declarations<E>(
1712 &self,
1713 element: E,
1714 pseudo_element: Option<&PseudoElement>,
1715 style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1716 smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1717 animation_declarations: AnimationDeclarations,
1718 rule_inclusion: RuleInclusion,
1719 applicable_declarations: &mut ApplicableDeclarationList,
1720 context: &mut MatchingContext<E::Impl>,
1721 ) where
1722 E: TElement,
1723 {
1724 let mut cur = element;
1725 let mut pseudos = SmallVec::<[_; 2]>::new();
1726 if let Some(pseudo) = pseudo_element {
1727 pseudos.push(pseudo.clone());
1728 }
1729 while let Some(p) = cur.implemented_pseudo_element() {
1730 pseudos.push(p);
1731 let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
1732 break;
1733 };
1734 cur = parent_pseudo;
1735 }
1736 RuleCollector::new(
1737 self,
1738 element,
1739 cur,
1740 &pseudos,
1741 style_attribute,
1742 smil_override,
1743 animation_declarations,
1744 rule_inclusion,
1745 applicable_declarations,
1746 context,
1747 )
1748 .collect_all();
1749 }
1750
1751 #[inline]
1754 pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1755 where
1756 E: TElement,
1757 {
1758 match self.quirks_mode().classes_and_ids_case_sensitivity() {
1761 CaseSensitivity::AsciiCaseInsensitive => return true,
1762 CaseSensitivity::CaseSensitive => {},
1763 }
1764
1765 self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1766 }
1767
1768 #[inline]
1776 fn lookup_element_dependent_at_rule<'a, T, F, E>(
1777 &'a self,
1778 element: E,
1779 find_in: F,
1780 ) -> Option<&'a T>
1781 where
1782 E: TElement + 'a,
1783 F: Fn(&'a CascadeData) -> Option<&'a T>,
1784 {
1785 macro_rules! try_find_in {
1786 ($data:expr) => {
1787 if let Some(thing) = find_in(&$data) {
1788 return Some(thing);
1789 }
1790 };
1791 }
1792
1793 let mut result = None;
1794 let doc_rules_apply =
1795 element.each_applicable_non_document_style_rule_data(|data, _host| {
1796 if result.is_none() {
1797 result = find_in(data);
1798 }
1799 });
1800
1801 if result.is_some() {
1802 return result;
1803 }
1804
1805 if doc_rules_apply {
1806 try_find_in!(self.cascade_data.author);
1807 }
1808 try_find_in!(self.cascade_data.user);
1809 try_find_in!(self.cascade_data.user_agent.cascade_data);
1810
1811 None
1812 }
1813
1814 #[inline]
1816 pub fn lookup_keyframes<'a, E>(
1817 &'a self,
1818 name: &Atom,
1819 element: E,
1820 ) -> Option<&'a KeyframesAnimation>
1821 where
1822 E: TElement + 'a,
1823 {
1824 self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1825 }
1826
1827 #[inline]
1830 pub fn last_view_transition_rule(&self) -> Option<&Arc<ViewTransitionRule>> {
1831 self.iter_extra_data_origins()
1833 .flat_map(|(d, _)| d.view_transitions.iter())
1834 .last()
1835 .map(|(rule, _)| rule)
1836 }
1837
1838 #[inline]
1840 #[cfg(feature = "gecko")]
1841 fn lookup_position_try<'a, E>(
1842 &'a self,
1843 name: &Atom,
1844 scope: CascadeLevel,
1845 element: E,
1846 ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1847 where
1848 E: TElement + 'a,
1849 {
1850 let mut shadow_root = scope.get_shadow_root_for_scoped(element);
1851 while let Some(r) = shadow_root {
1854 if let Some(rule) = r
1855 .style_data()
1856 .map(|data| data.extra_data.position_try_rules.get(name))
1857 .flatten()
1858 {
1859 return Some(rule);
1860 }
1861 shadow_root = r.host().containing_shadow();
1863 }
1864
1865 for (data, _) in self.iter_extra_data_origins() {
1866 if let Some(r) = data.position_try_rules.get(name) {
1867 return Some(r);
1868 }
1869 }
1870 None
1871 }
1872
1873 pub fn match_revalidation_selectors<E>(
1876 &self,
1877 element: E,
1878 bloom: Option<&BloomFilter>,
1879 selector_caches: &mut SelectorCaches,
1880 needs_selector_flags: NeedsSelectorFlags,
1881 ) -> RevalidationResult
1882 where
1883 E: TElement,
1884 {
1885 let mut matching_context = MatchingContext::new_for_revalidation(
1886 bloom,
1887 selector_caches,
1888 self.quirks_mode,
1889 needs_selector_flags,
1890 );
1891
1892 let mut result = RevalidationResult::default();
1898 let mut relevant_attributes = &mut result.relevant_attributes;
1899 let selectors_matched = &mut result.selectors_matched;
1900
1901 let matches_document_rules =
1902 element.each_applicable_non_document_style_rule_data(|data, host| {
1903 matching_context.with_shadow_host(Some(host), |matching_context| {
1904 data.selectors_for_cache_revalidation.lookup(
1905 element,
1906 self.quirks_mode,
1907 Some(&mut relevant_attributes),
1908 |selector_and_hashes| {
1909 selectors_matched.push(matches_selector(
1910 &selector_and_hashes.selector,
1911 selector_and_hashes.selector_offset,
1912 Some(&selector_and_hashes.hashes),
1913 &element,
1914 matching_context,
1915 ));
1916 true
1917 },
1918 );
1919 })
1920 });
1921
1922 for (data, origin) in self.cascade_data.iter_origins() {
1923 if origin == Origin::Author && !matches_document_rules {
1924 continue;
1925 }
1926
1927 data.selectors_for_cache_revalidation.lookup(
1928 element,
1929 self.quirks_mode,
1930 Some(&mut relevant_attributes),
1931 |selector_and_hashes| {
1932 selectors_matched.push(matches_selector(
1933 &selector_and_hashes.selector,
1934 selector_and_hashes.selector_offset,
1935 Some(&selector_and_hashes.hashes),
1936 &element,
1937 &mut matching_context,
1938 ));
1939 true
1940 },
1941 );
1942 }
1943
1944 result
1945 }
1946
1947 pub fn revalidate_scopes<E: TElement>(
1949 &self,
1950 element: &E,
1951 selector_caches: &mut SelectorCaches,
1952 needs_selector_flags: NeedsSelectorFlags,
1953 ) -> ScopeRevalidationResult {
1954 let mut matching_context = MatchingContext::new(
1955 MatchingMode::Normal,
1956 None,
1957 selector_caches,
1958 self.quirks_mode,
1959 needs_selector_flags,
1960 MatchingForInvalidation::No,
1961 );
1962
1963 let mut result = ScopeRevalidationResult::default();
1964 let matches_document_rules =
1965 element.each_applicable_non_document_style_rule_data(|data, host| {
1966 matching_context.with_shadow_host(Some(host), |matching_context| {
1967 data.revalidate_scopes(element, matching_context, &mut result);
1968 })
1969 });
1970
1971 for (data, origin) in self.cascade_data.iter_origins() {
1972 if origin == Origin::Author && !matches_document_rules {
1973 continue;
1974 }
1975
1976 data.revalidate_scopes(element, &mut matching_context, &mut result);
1977 }
1978
1979 result
1980 }
1981
1982 pub fn compute_for_declarations<E>(
1990 &self,
1991 guards: &StylesheetGuards,
1992 parent_style: &ComputedValues,
1993 declarations: Arc<Locked<PropertyDeclarationBlock>>,
1994 ) -> Arc<ComputedValues>
1995 where
1996 E: TElement,
1997 {
1998 let block = declarations.read_with(guards.author);
1999
2000 properties::apply_declarations::<E, _>(
2007 &self,
2008 None,
2009 self.rule_tree.root(),
2010 guards,
2011 block.declaration_importance_iter().map(|(declaration, _)| {
2012 (
2013 declaration,
2014 CascadePriority::new(
2015 CascadeLevel::same_tree_author_normal(),
2016 LayerOrder::root(),
2017 RuleCascadeFlags::empty(),
2018 ),
2019 )
2020 }),
2021 Some(parent_style),
2022 Some(parent_style),
2023 FirstLineReparenting::No,
2024 &PositionTryFallbacksTryTactic::default(),
2025 CascadeMode::Unvisited {
2026 visited_rules: None,
2027 },
2028 Default::default(),
2029 RuleCascadeFlags::empty(),
2030 None,
2031 &mut Default::default(),
2032 None,
2033 &mut TreeCountingCaches::default(),
2034 )
2035 }
2036
2037 #[inline]
2039 pub fn device(&self) -> &Device {
2040 &self.device
2041 }
2042
2043 #[inline]
2045 pub fn device_mut(&mut self) -> &mut Device {
2046 &mut self.device
2047 }
2048
2049 #[inline]
2051 pub fn rule_tree(&self) -> &RuleTree {
2052 &self.rule_tree
2053 }
2054
2055 #[inline]
2057 pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
2058 &self.script_custom_properties
2059 }
2060
2061 #[inline]
2063 pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2064 &mut self.script_custom_properties
2065 }
2066
2067 #[cfg(feature = "gecko")]
2069 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2070 self.cascade_data.add_size_of(ops, sizes);
2071 self.author_data_cache.add_size_of(ops, sizes);
2072 sizes.mRuleTree += self.rule_tree.size_of(ops);
2073
2074 }
2076
2077 pub fn shutdown() {
2079 let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2080 }
2081}
2082
2083#[allow(missing_docs)]
2084#[repr(u8)]
2085pub enum RegisterCustomPropertyResult {
2086 SuccessfullyRegistered,
2087 InvalidName,
2088 AlreadyRegistered,
2089 InvalidSyntax,
2090 NoInitialValue,
2091 InvalidInitialValue,
2092 InitialValueNotComputationallyIndependent,
2093}
2094
2095impl Stylist {
2096 pub fn register_custom_property(
2098 &mut self,
2099 url_data: &UrlExtraData,
2100 name: &str,
2101 syntax: &str,
2102 inherits: bool,
2103 initial_value: Option<&str>,
2104 ) -> RegisterCustomPropertyResult {
2105 use RegisterCustomPropertyResult::*;
2106
2107 let Ok(name) = parse_name(name).map(Atom::from) else {
2109 return InvalidName;
2110 };
2111
2112 if self.custom_property_script_registry().get(&name).is_some() {
2115 return AlreadyRegistered;
2116 }
2117 let Ok(syntax) = Descriptor::from_str(syntax, false) else {
2120 return InvalidSyntax;
2121 };
2122
2123 let initial_value = match initial_value {
2124 Some(value) => {
2125 let mut input = ParserInput::new(value);
2126 let parsed = Parser::new(&mut input)
2127 .parse_entirely(|input| {
2128 input.skip_whitespace();
2129 SpecifiedValue::parse(input, None, url_data).map(Arc::new)
2130 })
2131 .ok();
2132 if parsed.is_none() {
2133 return InvalidInitialValue;
2134 }
2135 parsed
2136 },
2137 None => None,
2138 };
2139
2140 if let Err(error) =
2141 PropertyRegistration::validate_initial_value(&syntax, initial_value.as_deref())
2142 {
2143 return match error {
2144 PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
2145 InitialValueNotComputationallyIndependent
2146 },
2147 PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
2148 PropertyRegistrationError::NoInitialValue => NoInitialValue,
2149 };
2150 }
2151
2152 let property_registration = PropertyRegistration {
2153 name: PropertyRuleName(name),
2154 descriptors: PropertyDescriptors {
2155 syntax: Some(syntax),
2156 inherits: Some(if inherits {
2157 Inherits::True
2158 } else {
2159 Inherits::False
2160 }),
2161 initial_value,
2162 },
2163 url_data: url_data.clone(),
2164 source_location: SourceLocation { line: 0, column: 0 },
2165 };
2166 self.custom_property_script_registry_mut()
2167 .register(property_registration);
2168 self.rebuild_initial_values_for_custom_properties();
2169
2170 SuccessfullyRegistered
2171 }
2172}
2173
2174#[derive(Clone, Debug, Deref, MallocSizeOf)]
2176pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2177impl<T> Default for LayerOrderedVec<T> {
2178 fn default() -> Self {
2179 Self(Default::default())
2180 }
2181}
2182
2183#[derive(Clone, Debug, Deref, MallocSizeOf)]
2185pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2186impl<T> Default for LayerOrderedMap<T> {
2187 fn default() -> Self {
2188 Self(Default::default())
2189 }
2190}
2191
2192impl<T: 'static> LayerOrderedVec<T> {
2193 fn clear(&mut self) {
2194 self.0.clear();
2195 }
2196 fn push(&mut self, v: T, id: LayerId) {
2197 self.0.push((v, id));
2198 }
2199 fn sort(&mut self, layers: &[CascadeLayer]) {
2200 self.0
2201 .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
2202 }
2203}
2204
2205impl<T: 'static> LayerOrderedMap<T> {
2206 fn shrink_if_needed(&mut self) {
2207 self.0.shrink_if_needed();
2208 }
2209 fn clear(&mut self) {
2210 self.0.clear();
2211 }
2212 fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2213 self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2214 }
2215 fn try_insert_with(
2216 &mut self,
2217 name: Atom,
2218 v: T,
2219 id: LayerId,
2220 cmp: impl Fn(&T, &T) -> Ordering,
2221 ) -> Result<(), AllocErr> {
2222 self.0.try_reserve(1)?;
2223 let vec = self.0.entry(name).or_default();
2224 if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
2225 if *last_id == id {
2226 if cmp(&val, &v) != Ordering::Greater {
2227 *val = v;
2228 }
2229 return Ok(());
2230 }
2231 }
2232 vec.push((v, id));
2233 Ok(())
2234 }
2235 fn sort(&mut self, layers: &[CascadeLayer]) {
2236 self.sort_with(layers, |_, _| Ordering::Equal)
2237 }
2238 fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2239 for (_, v) in self.0.iter_mut() {
2240 v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
2241 let order1 = layers[id1.0 as usize].order;
2242 let order2 = layers[id2.0 as usize].order;
2243 order1.cmp(&order2).then_with(|| cmp(v1, v2))
2244 })
2245 }
2246 }
2247 pub fn get(&self, name: &Atom) -> Option<&T> {
2249 let vec = self.0.get(name)?;
2250 Some(&vec.last()?.0)
2251 }
2252}
2253
2254#[derive(Clone, Debug, MallocSizeOf)]
2258pub struct PageRuleData {
2259 pub layer: LayerId,
2261 #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2263 pub rule: Arc<Locked<PageRule>>,
2264}
2265
2266#[derive(Clone, Debug, Default, MallocSizeOf)]
2268pub struct PageRuleMap {
2269 pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2271}
2272
2273impl PageRuleMap {
2274 #[inline]
2275 fn clear(&mut self) {
2276 self.rules.clear();
2277 }
2278
2279 pub fn match_and_append_rules(
2283 &self,
2284 matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2285 origin: Origin,
2286 guards: &StylesheetGuards,
2287 cascade_data: &DocumentCascadeData,
2288 name: &Option<Atom>,
2289 pseudos: PagePseudoClassFlags,
2290 ) {
2291 let level = match origin {
2292 Origin::UserAgent => CascadeLevel::new(CascadeOrigin::UA),
2293 Origin::User => CascadeLevel::new(CascadeOrigin::User),
2294 Origin::Author => CascadeLevel::same_tree_author_normal(),
2295 };
2296 let cascade_data = cascade_data.borrow_for_origin(origin);
2297 let start = matched_rules.len();
2298
2299 self.match_and_add_rules(
2300 matched_rules,
2301 level,
2302 guards,
2303 cascade_data,
2304 &atom!(""),
2305 pseudos,
2306 );
2307 if let Some(name) = name {
2308 self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2309 }
2310
2311 matched_rules[start..].sort_by_key(|block| block.sort_key());
2314 }
2315
2316 fn match_and_add_rules(
2317 &self,
2318 extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2319 level: CascadeLevel,
2320 guards: &StylesheetGuards,
2321 cascade_data: &CascadeData,
2322 name: &Atom,
2323 pseudos: PagePseudoClassFlags,
2324 ) {
2325 let rules = match self.rules.get(name) {
2326 Some(rules) => rules,
2327 None => return,
2328 };
2329 for data in rules.iter() {
2330 let rule = data.rule.read_with(level.guard(&guards));
2331 let specificity = match rule.match_specificity(pseudos) {
2332 Some(specificity) => specificity,
2333 None => continue,
2334 };
2335 let block = rule.block.clone();
2336 extra_declarations.push(ApplicableDeclarationBlock::new(
2337 StyleSource::from_declarations(block),
2338 0,
2339 level,
2340 specificity,
2341 cascade_data.layer_order_for(data.layer),
2342 ScopeProximity::infinity(), RuleCascadeFlags::empty(),
2344 ));
2345 }
2346 }
2347}
2348
2349impl MallocShallowSizeOf for PageRuleMap {
2350 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2351 self.rules.shallow_size_of(ops)
2352 }
2353}
2354
2355type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2356
2357#[derive(Clone, Debug, Default)]
2360pub struct ExtraStyleData {
2361 pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2363
2364 pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2366
2367 pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2369
2370 pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2372
2373 pub position_try_rules: PositionTryMap,
2375
2376 pub pages: PageRuleMap,
2378
2379 pub view_transitions: LayerOrderedVec<Arc<ViewTransitionRule>>,
2381}
2382
2383impl ExtraStyleData {
2384 fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2386 self.font_faces.push(rule.clone(), layer);
2387 }
2388
2389 fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2391 self.font_feature_values.push(rule.clone(), layer);
2392 }
2393
2394 fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2396 self.font_palette_values.push(rule.clone(), layer);
2397 }
2398
2399 fn add_counter_style(
2401 &mut self,
2402 guard: &SharedRwLockReadGuard,
2403 rule: &Arc<Locked<CounterStyleRule>>,
2404 layer: LayerId,
2405 ) -> Result<(), AllocErr> {
2406 let name = rule.read_with(guard).name().0.clone();
2407 self.counter_styles.try_insert(name, rule.clone(), layer)
2408 }
2409
2410 fn add_position_try(
2412 &mut self,
2413 name: Atom,
2414 rule: Arc<Locked<PositionTryRule>>,
2415 layer: LayerId,
2416 ) -> Result<(), AllocErr> {
2417 self.position_try_rules.try_insert(name, rule, layer)
2418 }
2419
2420 fn add_page(
2422 &mut self,
2423 guard: &SharedRwLockReadGuard,
2424 rule: &Arc<Locked<PageRule>>,
2425 layer: LayerId,
2426 ) -> Result<(), AllocErr> {
2427 let page_rule = rule.read_with(guard);
2428 let mut add_rule = |name| {
2429 let vec = self.pages.rules.entry(name).or_default();
2430 vec.push(PageRuleData {
2431 layer,
2432 rule: rule.clone(),
2433 });
2434 };
2435 if page_rule.selectors.0.is_empty() {
2436 add_rule(atom!(""));
2437 } else {
2438 for selector in page_rule.selectors.as_slice() {
2439 add_rule(selector.name.0.clone());
2440 }
2441 }
2442 Ok(())
2443 }
2444
2445 fn add_view_transition(&mut self, rule: &Arc<ViewTransitionRule>, layer: LayerId) {
2446 self.view_transitions.push(rule.clone(), layer)
2447 }
2448
2449 fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2450 self.font_faces.sort(layers);
2451 self.font_feature_values.sort(layers);
2452 self.font_palette_values.sort(layers);
2453 self.counter_styles.sort(layers);
2454 self.position_try_rules.sort(layers);
2455 self.view_transitions.sort(layers);
2456 }
2457
2458 fn clear(&mut self) {
2459 self.font_faces.clear();
2460 self.font_feature_values.clear();
2461 self.font_palette_values.clear();
2462 self.counter_styles.clear();
2463 self.position_try_rules.clear();
2464 self.pages.clear();
2465 }
2466}
2467
2468fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2471 if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2472 Ordering::Equal
2473 } else if v2.vendor_prefix.is_some() {
2474 Ordering::Greater
2475 } else {
2476 Ordering::Less
2477 }
2478}
2479
2480pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2482
2483impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2484 type Item = (&'a ExtraStyleData, Origin);
2485
2486 fn next(&mut self) -> Option<Self::Item> {
2487 self.0.next().map(|d| (&d.0.extra_data, d.1))
2488 }
2489}
2490
2491impl MallocSizeOf for ExtraStyleData {
2492 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2494 let mut n = 0;
2495 n += self.font_faces.shallow_size_of(ops);
2496 n += self.font_feature_values.shallow_size_of(ops);
2497 n += self.font_palette_values.shallow_size_of(ops);
2498 n += self.counter_styles.shallow_size_of(ops);
2499 n += self.position_try_rules.shallow_size_of(ops);
2500 n += self.pages.shallow_size_of(ops);
2501 n
2502 }
2503}
2504
2505#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2507#[derive(Clone, Debug)]
2508struct RevalidationSelectorAndHashes {
2509 #[cfg_attr(
2510 feature = "gecko",
2511 ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2512 )]
2513 selector: Selector<SelectorImpl>,
2514 selector_offset: usize,
2515 hashes: AncestorHashes,
2516}
2517
2518impl RevalidationSelectorAndHashes {
2519 fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2520 let selector_offset = {
2521 let mut index = 0;
2525 let mut iter = selector.iter();
2526
2527 for _ in &mut iter {
2532 index += 1; }
2534
2535 match iter.next_sequence() {
2536 Some(Combinator::PseudoElement) => index + 1, _ => 0,
2538 }
2539 };
2540
2541 RevalidationSelectorAndHashes {
2542 selector,
2543 selector_offset,
2544 hashes,
2545 }
2546 }
2547}
2548
2549impl SelectorMapEntry for RevalidationSelectorAndHashes {
2550 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2551 self.selector.iter_from(self.selector_offset)
2552 }
2553}
2554
2555struct StylistSelectorVisitor<'a> {
2558 passed_rightmost_selector: bool,
2561
2562 needs_revalidation: &'a mut bool,
2564
2565 in_selector_list_of: SelectorListKind,
2568
2569 mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2572
2573 nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2576
2577 attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2579
2580 nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2583
2584 nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2588
2589 nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2593
2594 state_dependencies: &'a mut ElementState,
2596
2597 nth_of_state_dependencies: &'a mut ElementState,
2600
2601 document_state_dependencies: &'a mut DocumentState,
2603}
2604
2605fn component_needs_revalidation(
2606 c: &Component<SelectorImpl>,
2607 passed_rightmost_selector: bool,
2608) -> bool {
2609 match *c {
2610 Component::ID(_) => {
2611 passed_rightmost_selector
2617 },
2618 Component::AttributeInNoNamespaceExists { .. }
2619 | Component::AttributeInNoNamespace { .. }
2620 | Component::AttributeOther(_)
2621 | Component::Empty
2622 | Component::Nth(_)
2623 | Component::NthOf(_)
2624 | Component::Has(_) => true,
2625 Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2626 _ => false,
2627 }
2628}
2629
2630impl<'a> StylistSelectorVisitor<'a> {
2631 fn visit_nested_selector(
2632 &mut self,
2633 in_selector_list_of: SelectorListKind,
2634 selector: &Selector<SelectorImpl>,
2635 ) {
2636 let old_passed_rightmost_selector = self.passed_rightmost_selector;
2637 let old_in_selector_list_of = self.in_selector_list_of;
2638
2639 self.passed_rightmost_selector = false;
2640 self.in_selector_list_of = in_selector_list_of;
2641 let _ret = selector.visit(self);
2642 debug_assert!(_ret, "We never return false");
2643
2644 self.passed_rightmost_selector = old_passed_rightmost_selector;
2645 self.in_selector_list_of = old_in_selector_list_of;
2646 }
2647}
2648
2649impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2650 type Impl = SelectorImpl;
2651
2652 fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2653 *self.needs_revalidation =
2654 *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2655
2656 self.passed_rightmost_selector = self.passed_rightmost_selector
2660 || !matches!(combinator, None | Some(Combinator::PseudoElement));
2661
2662 true
2663 }
2664
2665 fn visit_selector_list(
2666 &mut self,
2667 list_kind: SelectorListKind,
2668 list: &[Selector<Self::Impl>],
2669 ) -> bool {
2670 let in_selector_list_of = self.in_selector_list_of | list_kind;
2671 for selector in list {
2672 self.visit_nested_selector(in_selector_list_of, selector);
2673 }
2674 true
2675 }
2676
2677 fn visit_relative_selector_list(
2678 &mut self,
2679 list: &[selectors::parser::RelativeSelector<Self::Impl>],
2680 ) -> bool {
2681 let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2682 for selector in list {
2683 self.visit_nested_selector(in_selector_list_of, &selector.selector);
2684 }
2685 true
2686 }
2687
2688 fn visit_attribute_selector(
2689 &mut self,
2690 _ns: &NamespaceConstraint<&Namespace>,
2691 name: &LocalName,
2692 lower_name: &LocalName,
2693 ) -> bool {
2694 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2695 self.nth_of_attribute_dependencies.insert(name.clone());
2696 if name != lower_name {
2697 self.nth_of_attribute_dependencies
2698 .insert(lower_name.clone());
2699 }
2700 }
2701
2702 self.attribute_dependencies.insert(name.clone());
2703 if name != lower_name {
2704 self.attribute_dependencies.insert(lower_name.clone());
2705 }
2706
2707 true
2708 }
2709
2710 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2711 *self.needs_revalidation = *self.needs_revalidation
2712 || component_needs_revalidation(s, self.passed_rightmost_selector);
2713
2714 match *s {
2715 Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2716 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2722 self.nth_of_custom_state_dependencies.insert(name.0.clone());
2723 }
2724 },
2725 Component::NonTSPseudoClass(ref p) => {
2726 self.state_dependencies.insert(p.state_flag());
2727 self.document_state_dependencies
2728 .insert(p.document_state_flag());
2729
2730 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2731 self.nth_of_state_dependencies.insert(p.state_flag());
2732 }
2733 },
2734 Component::ID(ref id) => {
2735 if !self.passed_rightmost_selector {
2747 self.mapped_ids.insert(id.0.clone());
2748 }
2749
2750 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2751 self.nth_of_mapped_ids.insert(id.0.clone());
2752 }
2753 },
2754 Component::Class(ref class)
2755 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2756 {
2757 self.nth_of_class_dependencies.insert(class.0.clone());
2758 },
2759 _ => {},
2760 }
2761
2762 true
2763 }
2764}
2765
2766#[derive(Clone, Debug, Default, MallocSizeOf)]
2768struct GenericElementAndPseudoRules<Map> {
2769 element_map: Map,
2771
2772 pseudos_map: PerPseudoElementMap<Self>,
2779}
2780
2781impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2782 #[inline(always)]
2783 fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2784 let mut current = self;
2785 for &pseudo_element in pseudo_elements {
2786 debug_assert!(
2787 !pseudo_element.is_precomputed()
2788 && !pseudo_element.is_unknown_webkit_pseudo_element(),
2789 "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2790 and unknown webkit pseudos should be discarded before getting here"
2791 );
2792
2793 current = current
2794 .pseudos_map
2795 .get_or_insert_with(pseudo_element, Default::default);
2796 }
2797
2798 &mut current.element_map
2799 }
2800
2801 #[inline]
2802 fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2803 let mut current = self;
2804 for pseudo in pseudo_elements {
2805 current = current.pseudos_map.get(&pseudo)?;
2806 }
2807 Some(¤t.element_map)
2808 }
2809
2810 #[cfg(feature = "gecko")]
2812 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2813 sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2814
2815 for elem in self.pseudos_map.iter() {
2816 sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2817 }
2818 }
2819}
2820
2821type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2822type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2823type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2824
2825impl ElementAndPseudoRules {
2826 fn clear(&mut self) {
2828 self.element_map.clear();
2829 self.pseudos_map.clear();
2830 }
2831
2832 fn shrink_if_needed(&mut self) {
2833 self.element_map.shrink_if_needed();
2834 for pseudo in self.pseudos_map.iter_mut() {
2835 pseudo.shrink_if_needed();
2836 }
2837 }
2838}
2839
2840impl PartElementAndPseudoRules {
2841 fn clear(&mut self) {
2843 self.element_map.clear();
2844 self.pseudos_map.clear();
2845 }
2846}
2847
2848#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2850pub struct LayerId(u16);
2851
2852impl LayerId {
2853 pub const fn root() -> Self {
2855 Self(0)
2856 }
2857}
2858
2859#[derive(Clone, Debug, MallocSizeOf)]
2860struct CascadeLayer {
2861 id: LayerId,
2862 order: LayerOrder,
2863 children: Vec<LayerId>,
2864}
2865
2866impl CascadeLayer {
2867 const fn root() -> Self {
2868 Self {
2869 id: LayerId::root(),
2870 order: LayerOrder::root(),
2871 children: vec![],
2872 }
2873 }
2874}
2875
2876#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2879pub struct ContainerConditionId(u16);
2880
2881impl ContainerConditionId {
2882 pub const fn none() -> Self {
2884 Self(0)
2885 }
2886}
2887
2888#[derive(Clone, Debug, MallocSizeOf)]
2889struct ContainerConditionReference {
2890 parent: ContainerConditionId,
2891 #[ignore_malloc_size_of = "Arc"]
2896 conditions: ArcSlice<ContainerCondition>,
2897}
2898
2899impl ContainerConditionReference {
2900 fn none() -> Self {
2902 Self {
2903 parent: ContainerConditionId::none(),
2904 conditions: ArcSlice::default(),
2905 }
2906 }
2907}
2908
2909#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2912pub struct ScopeConditionId(u16);
2913
2914impl ScopeConditionId {
2915 pub fn new(id: u16) -> Self {
2917 Self(id)
2918 }
2919
2920 pub const fn none() -> Self {
2922 Self(0)
2923 }
2924}
2925
2926#[derive(Clone, Debug, MallocSizeOf)]
2928pub struct ScopeConditionReference {
2929 parent: ScopeConditionId,
2931 condition: Option<ScopeBoundsWithHashes>,
2933 #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2936 implicit_scope_root: StylistImplicitScopeRoot,
2937 is_trivial: bool,
2939}
2940
2941impl ScopeConditionReference {
2942 pub fn new(
2944 parent: ScopeConditionId,
2945 condition: Option<ScopeBoundsWithHashes>,
2946 implicit_scope_root: ImplicitScopeRoot,
2947 is_trivial: bool,
2948 ) -> Self {
2949 Self {
2950 parent,
2951 condition,
2952 implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2953 is_trivial,
2954 }
2955 }
2956
2957 pub const fn none() -> Self {
2959 Self {
2960 parent: ScopeConditionId::none(),
2961 condition: None,
2962 implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2963 is_trivial: true,
2964 }
2965 }
2966}
2967
2968pub struct ScopeRootCandidates {
2970 pub candidates: Vec<ScopeRootCandidate>,
2972 pub is_trivial: bool,
2974}
2975
2976impl Default for ScopeRootCandidates {
2977 fn default() -> Self {
2978 Self {
2979 candidates: vec![],
2980 is_trivial: true,
2981 }
2982 }
2983}
2984
2985impl ScopeRootCandidates {
2986 fn empty(is_trivial: bool) -> Self {
2987 Self {
2988 candidates: vec![],
2989 is_trivial,
2990 }
2991 }
2992}
2993
2994#[derive(Clone, Debug, MallocSizeOf)]
2996pub struct ScopeBoundWithHashes {
2997 #[ignore_malloc_size_of = "Arc"]
2999 selectors: SelectorList<SelectorImpl>,
3000 hashes: SmallVec<[AncestorHashes; 1]>,
3001}
3002
3003impl ScopeBoundWithHashes {
3004 fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
3005 let mut hashes = SmallVec::with_capacity(selectors.len());
3006 for selector in selectors.slice() {
3007 hashes.push(AncestorHashes::new(selector, quirks_mode));
3008 }
3009 Self { selectors, hashes }
3010 }
3011
3012 fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
3013 let hashes = selectors
3014 .slice()
3015 .iter()
3016 .map(|_| AncestorHashes {
3017 packed_hashes: [0, 0, 0],
3018 })
3019 .collect();
3020 Self { selectors, hashes }
3021 }
3022}
3023
3024#[derive(Clone, Debug, MallocSizeOf)]
3026pub struct ScopeBoundsWithHashes {
3027 start: Option<ScopeBoundWithHashes>,
3029 end: Option<ScopeBoundWithHashes>,
3031}
3032
3033impl ScopeBoundsWithHashes {
3034 fn new(
3036 quirks_mode: QuirksMode,
3037 start: Option<SelectorList<SelectorImpl>>,
3038 end: Option<SelectorList<SelectorImpl>>,
3039 ) -> Self {
3040 Self {
3041 start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3042 end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3043 }
3044 }
3045
3046 pub fn new_no_hash(
3048 start: Option<SelectorList<SelectorImpl>>,
3049 end: Option<SelectorList<SelectorImpl>>,
3050 ) -> Self {
3051 Self {
3052 start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3053 end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3054 }
3055 }
3056
3057 fn selectors_for<'a>(
3058 bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
3059 ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3060 bound_with_hashes
3061 .map(|b| b.selectors.slice().iter())
3062 .into_iter()
3063 .flatten()
3064 }
3065
3066 fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3067 Self::selectors_for(self.start.as_ref())
3068 }
3069
3070 fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3071 Self::selectors_for(self.end.as_ref())
3072 }
3073
3074 fn is_trivial(&self) -> bool {
3075 fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
3076 bound.as_ref().map_or(default, |bound| {
3077 scope_selector_list_is_trivial(&bound.selectors)
3078 })
3079 }
3080
3081 scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
3083 }
3084}
3085
3086pub fn scope_root_candidates<E>(
3088 scope_conditions: &[ScopeConditionReference],
3089 id: ScopeConditionId,
3090 element: &E,
3091 override_matches_shadow_host_for_part: bool,
3092 scope_subject_map: &ScopeSubjectMap,
3093 context: &mut MatchingContext<SelectorImpl>,
3094) -> ScopeRootCandidates
3095where
3096 E: TElement,
3097{
3098 let condition_ref = &scope_conditions[id.0 as usize];
3099 let bounds = match condition_ref.condition {
3100 None => return ScopeRootCandidates::default(),
3101 Some(ref c) => c,
3102 };
3103 let outer_result = scope_root_candidates(
3107 scope_conditions,
3108 condition_ref.parent,
3109 element,
3110 override_matches_shadow_host_for_part,
3111 scope_subject_map,
3112 context,
3113 );
3114
3115 let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
3116 let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
3117 if !is_outermost_scope && outer_result.candidates.is_empty() {
3118 return ScopeRootCandidates::empty(is_trivial);
3119 }
3120
3121 let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
3122 if let Some(filter) = context.bloom_filter {
3123 if !start
3128 .hashes
3129 .iter()
3130 .any(|entry| selector_may_match(entry, filter))
3131 {
3132 return ScopeRootCandidates::empty(is_trivial);
3133 }
3134 }
3135 (
3136 ScopeTarget::Selector(&start.selectors),
3137 scope_start_matches_shadow_host(&start.selectors),
3138 )
3139 } else {
3140 let implicit_root = condition_ref.implicit_scope_root;
3141 match implicit_root {
3142 StylistImplicitScopeRoot::Normal(r) => (
3143 ScopeTarget::Implicit(r.element(context.current_host.clone())),
3144 r.matches_shadow_host(),
3145 ),
3146 StylistImplicitScopeRoot::Cached(index) => {
3147 let host = context
3148 .current_host
3149 .expect("Cached implicit scope for light DOM implicit scope");
3150 match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
3151 None => return ScopeRootCandidates::empty(is_trivial),
3152 Some(root) => (
3153 ScopeTarget::Implicit(root.element(context.current_host.clone())),
3154 root.matches_shadow_host(),
3155 ),
3156 }
3157 },
3158 }
3159 };
3160 let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
3163
3164 let potential_scope_roots = if is_outermost_scope {
3165 collect_scope_roots(
3166 *element,
3167 None,
3168 context,
3169 &root_target,
3170 matches_shadow_host,
3171 scope_subject_map,
3172 )
3173 } else {
3174 let mut result = vec![];
3175 for activation in outer_result.candidates {
3176 let mut this_result = collect_scope_roots(
3177 *element,
3178 Some(activation.root),
3179 context,
3180 &root_target,
3181 matches_shadow_host,
3182 scope_subject_map,
3183 );
3184 result.append(&mut this_result);
3185 }
3186 result
3187 };
3188
3189 if potential_scope_roots.is_empty() {
3190 return ScopeRootCandidates::empty(is_trivial);
3191 }
3192
3193 let candidates = if let Some(end) = bounds.end.as_ref() {
3194 let mut result = vec![];
3195 for scope_root in potential_scope_roots {
3197 if end
3198 .selectors
3199 .slice()
3200 .iter()
3201 .zip(end.hashes.iter())
3202 .all(|(selector, hashes)| {
3203 if let Some(filter) = context.bloom_filter {
3205 if !selector_may_match(hashes, filter) {
3206 return true;
3208 }
3209 }
3210
3211 !element_is_outside_of_scope(
3212 selector,
3213 *element,
3214 scope_root.root,
3215 context,
3216 matches_shadow_host,
3217 )
3218 })
3219 {
3220 result.push(scope_root);
3221 }
3222 }
3223 result
3224 } else {
3225 potential_scope_roots
3226 };
3227
3228 ScopeRootCandidates {
3229 candidates,
3230 is_trivial,
3231 }
3232}
3233
3234#[derive(Copy, Clone, Debug, MallocSizeOf)]
3237enum StylistImplicitScopeRoot {
3238 Normal(ImplicitScopeRoot),
3239 Cached(usize),
3240}
3241unsafe impl Sync for StylistImplicitScopeRoot {}
3243
3244impl StylistImplicitScopeRoot {
3245 const fn default_const() -> Self {
3246 Self::Normal(ImplicitScopeRoot::DocumentElement)
3248 }
3249}
3250
3251impl Default for StylistImplicitScopeRoot {
3252 fn default() -> Self {
3253 Self::default_const()
3254 }
3255}
3256
3257#[derive(Debug, Clone, MallocSizeOf)]
3263pub struct CascadeData {
3264 normal_rules: ElementAndPseudoRules,
3267
3268 featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3272
3273 slotted_rules: Option<Box<ElementAndPseudoRules>>,
3281
3282 part_rules: Option<Box<PartElementAndPseudoRules>>,
3287
3288 invalidation_map: InvalidationMap,
3290
3291 relative_selector_invalidation_map: InvalidationMap,
3293
3294 additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3295
3296 attribute_dependencies: PrecomputedHashSet<LocalName>,
3301
3302 nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3306
3307 nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3311
3312 nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3316
3317 state_dependencies: ElementState,
3321
3322 nth_of_state_dependencies: ElementState,
3325
3326 document_state_dependencies: DocumentState,
3330
3331 mapped_ids: PrecomputedHashSet<Atom>,
3336
3337 nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3341
3342 #[ignore_malloc_size_of = "Arc"]
3346 selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3347
3348 animations: LayerOrderedMap<KeyframesAnimation>,
3351
3352 #[ignore_malloc_size_of = "Arc"]
3355 custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3356
3357 custom_media: CustomMediaMap,
3359
3360 layer_id: FxHashMap<LayerName, LayerId>,
3362
3363 layers: SmallVec<[CascadeLayer; 1]>,
3365
3366 container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3368
3369 scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3371
3372 scope_subject_map: ScopeSubjectMap,
3374
3375 effective_media_query_results: EffectiveMediaQueryResults,
3377
3378 extra_data: ExtraStyleData,
3380
3381 rules_source_order: u32,
3384
3385 num_selectors: usize,
3387
3388 num_declarations: usize,
3390}
3391
3392static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3393 let list = SelectorList::implicit_scope();
3397 list.mark_as_intentionally_leaked();
3398 list
3399});
3400
3401fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3402 start
3405 .slice()
3406 .iter()
3407 .any(|s| s.matches_featureless_host(true).may_match())
3408}
3409
3410pub fn replace_parent_selector_with_implicit_scope(
3412 selectors: &SelectorList<SelectorImpl>,
3413) -> SelectorList<SelectorImpl> {
3414 selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3415}
3416
3417impl CascadeData {
3418 pub fn new() -> Self {
3420 Self {
3421 normal_rules: ElementAndPseudoRules::default(),
3422 featureless_host_rules: None,
3423 slotted_rules: None,
3424 part_rules: None,
3425 invalidation_map: InvalidationMap::new(),
3426 relative_selector_invalidation_map: InvalidationMap::new(),
3427 additional_relative_selector_invalidation_map:
3428 AdditionalRelativeSelectorInvalidationMap::new(),
3429 nth_of_mapped_ids: PrecomputedHashSet::default(),
3430 nth_of_class_dependencies: PrecomputedHashSet::default(),
3431 nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3432 nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3433 nth_of_state_dependencies: ElementState::empty(),
3434 attribute_dependencies: PrecomputedHashSet::default(),
3435 state_dependencies: ElementState::empty(),
3436 document_state_dependencies: DocumentState::empty(),
3437 mapped_ids: PrecomputedHashSet::default(),
3438 selectors_for_cache_revalidation: SelectorMap::new(),
3439 animations: Default::default(),
3440 custom_property_registrations: Default::default(),
3441 custom_media: Default::default(),
3442 layer_id: Default::default(),
3443 layers: smallvec::smallvec![CascadeLayer::root()],
3444 container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3445 scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3446 scope_subject_map: Default::default(),
3447 extra_data: ExtraStyleData::default(),
3448 effective_media_query_results: EffectiveMediaQueryResults::new(),
3449 rules_source_order: 0,
3450 num_selectors: 0,
3451 num_declarations: 0,
3452 }
3453 }
3454
3455 pub fn rebuild<'a, S>(
3457 &mut self,
3458 device: &Device,
3459 quirks_mode: QuirksMode,
3460 collection: SheetCollectionFlusher<S>,
3461 guard: &SharedRwLockReadGuard,
3462 difference: &mut CascadeDataDifference,
3463 ) -> Result<(), AllocErr>
3464 where
3465 S: StylesheetInDocument + PartialEq + 'static,
3466 {
3467 if !collection.dirty() {
3468 return Ok(());
3469 }
3470
3471 let validity = collection.data_validity();
3472
3473 let mut old_position_try_data = LayerOrderedMap::default();
3474 if validity != DataValidity::Valid {
3475 old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3476 self.clear_cascade_data();
3477 if validity == DataValidity::FullyInvalid {
3478 self.clear_invalidation_data();
3479 }
3480 }
3481
3482 let mut result = Ok(());
3483
3484 collection.each(|index, stylesheet, rebuild_kind| {
3485 result = self.add_stylesheet(
3486 device,
3487 quirks_mode,
3488 stylesheet,
3489 index,
3490 guard,
3491 rebuild_kind,
3492 None,
3493 if validity == DataValidity::Valid {
3494 Some(difference)
3495 } else {
3496 None
3497 },
3498 );
3499 result.is_ok()
3500 });
3501
3502 self.did_finish_rebuild();
3503
3504 if validity != DataValidity::Valid {
3507 difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3508 }
3509
3510 result
3511 }
3512
3513 pub fn custom_media_map(&self) -> &CustomMediaMap {
3515 &self.custom_media
3516 }
3517
3518 pub fn invalidation_map(&self) -> &InvalidationMap {
3520 &self.invalidation_map
3521 }
3522
3523 pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3525 &self.relative_selector_invalidation_map
3526 }
3527
3528 pub fn relative_invalidation_map_attributes(
3530 &self,
3531 ) -> &AdditionalRelativeSelectorInvalidationMap {
3532 &self.additional_relative_selector_invalidation_map
3533 }
3534
3535 #[inline]
3538 pub fn has_state_dependency(&self, state: ElementState) -> bool {
3539 self.state_dependencies.intersects(state)
3540 }
3541
3542 #[inline]
3545 pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3546 self.nth_of_custom_state_dependencies.contains(state)
3547 }
3548
3549 #[inline]
3552 pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3553 self.nth_of_state_dependencies.intersects(state)
3554 }
3555
3556 #[inline]
3559 pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3560 self.attribute_dependencies.contains(local_name)
3561 }
3562
3563 #[inline]
3566 pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3567 self.nth_of_mapped_ids.contains(id)
3568 }
3569
3570 #[inline]
3573 pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3574 self.nth_of_class_dependencies.contains(class)
3575 }
3576
3577 #[inline]
3580 pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3581 self.nth_of_attribute_dependencies.contains(local_name)
3582 }
3583
3584 #[inline]
3586 pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3587 self.normal_rules.rules(pseudo_elements)
3588 }
3589
3590 #[inline]
3592 pub fn featureless_host_rules(
3593 &self,
3594 pseudo_elements: &[PseudoElement],
3595 ) -> Option<&SelectorMap<Rule>> {
3596 self.featureless_host_rules
3597 .as_ref()
3598 .and_then(|d| d.rules(pseudo_elements))
3599 }
3600
3601 pub fn any_featureless_host_rules(&self) -> bool {
3603 self.featureless_host_rules.is_some()
3604 }
3605
3606 #[inline]
3608 pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3609 self.slotted_rules
3610 .as_ref()
3611 .and_then(|d| d.rules(pseudo_elements))
3612 }
3613
3614 pub fn any_slotted_rule(&self) -> bool {
3616 self.slotted_rules.is_some()
3617 }
3618
3619 #[inline]
3621 pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3622 self.part_rules
3623 .as_ref()
3624 .and_then(|d| d.rules(pseudo_elements))
3625 }
3626
3627 pub fn any_part_rule(&self) -> bool {
3629 self.part_rules.is_some()
3630 }
3631
3632 #[inline]
3633 fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3634 self.layers[id.0 as usize].order
3635 }
3636
3637 pub(crate) fn container_condition_matches<E>(
3638 &self,
3639 mut id: ContainerConditionId,
3640 stylist: &Stylist,
3641 element: E,
3642 context: &mut MatchingContext<E::Impl>,
3643 ) -> bool
3644 where
3645 E: TElement,
3646 {
3647 loop {
3648 let condition_ref = &self.container_conditions[id.0 as usize];
3649 if condition_ref.conditions.is_empty() {
3650 return true;
3651 }
3652 let matches = condition_ref.conditions.iter().any(|condition| {
3653 condition
3654 .matches(
3655 stylist,
3656 element,
3657 context.extra_data.originating_element_style,
3658 &mut context.extra_data.cascade_input_flags,
3659 )
3660 .to_bool(false)
3661 });
3662 if !matches {
3663 return false;
3664 }
3665 id = condition_ref.parent;
3666 }
3667 }
3668
3669 pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3670 &self,
3671 rule: &Rule,
3672 element: E,
3673 context: &mut MatchingContext<E::Impl>,
3674 ) -> ScopeProximity {
3675 context
3676 .extra_data
3677 .cascade_input_flags
3678 .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3679
3680 let result = scope_root_candidates(
3684 &self.scope_conditions,
3685 rule.scope_condition_id,
3686 &element,
3687 rule.selector.is_part(),
3688 &self.scope_subject_map,
3689 context,
3690 );
3691 for candidate in result.candidates {
3692 if context.nest_for_scope(Some(candidate.root), |context| {
3693 matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3694 }) {
3695 return candidate.proximity;
3696 }
3697 }
3698 ScopeProximity::infinity()
3699 }
3700
3701 fn did_finish_rebuild(&mut self) {
3702 self.shrink_maps_if_needed();
3703 self.compute_layer_order();
3704 }
3705
3706 fn shrink_maps_if_needed(&mut self) {
3707 self.normal_rules.shrink_if_needed();
3708 if let Some(ref mut host_rules) = self.featureless_host_rules {
3709 host_rules.shrink_if_needed();
3710 }
3711 if let Some(ref mut slotted_rules) = self.slotted_rules {
3712 slotted_rules.shrink_if_needed();
3713 }
3714 self.animations.shrink_if_needed();
3715 self.custom_property_registrations.shrink_if_needed();
3716 self.invalidation_map.shrink_if_needed();
3717 self.relative_selector_invalidation_map.shrink_if_needed();
3718 self.additional_relative_selector_invalidation_map
3719 .shrink_if_needed();
3720 self.attribute_dependencies.shrink_if_needed();
3721 self.nth_of_attribute_dependencies.shrink_if_needed();
3722 self.nth_of_custom_state_dependencies.shrink_if_needed();
3723 self.nth_of_class_dependencies.shrink_if_needed();
3724 self.nth_of_mapped_ids.shrink_if_needed();
3725 self.mapped_ids.shrink_if_needed();
3726 self.layer_id.shrink_if_needed();
3727 self.selectors_for_cache_revalidation.shrink_if_needed();
3728 self.scope_subject_map.shrink_if_needed();
3729 }
3730
3731 fn compute_layer_order(&mut self) {
3732 debug_assert_ne!(
3733 self.layers.len(),
3734 0,
3735 "There should be at least the root layer!"
3736 );
3737 if self.layers.len() == 1 {
3738 return; }
3740 let (first, remaining) = self.layers.split_at_mut(1);
3741 let root = &mut first[0];
3742 let mut order = LayerOrder::first();
3743 compute_layer_order_for_subtree(root, remaining, &mut order);
3744
3745 fn compute_layer_order_for_subtree(
3748 parent: &mut CascadeLayer,
3749 remaining_layers: &mut [CascadeLayer],
3750 order: &mut LayerOrder,
3751 ) {
3752 for child in parent.children.iter() {
3753 debug_assert!(
3754 parent.id < *child,
3755 "Children are always registered after parents"
3756 );
3757 let child_index = (child.0 - parent.id.0 - 1) as usize;
3758 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3759 let child = &mut first[child_index];
3760 compute_layer_order_for_subtree(child, remaining, order);
3761 }
3762
3763 if parent.id != LayerId::root() {
3764 parent.order = *order;
3765 order.inc();
3766 }
3767 }
3768 self.extra_data.sort_by_layer(&self.layers);
3769 self.animations
3770 .sort_with(&self.layers, compare_keyframes_in_same_layer);
3771 self.custom_property_registrations.sort(&self.layers)
3772 }
3773
3774 fn collect_applicable_media_query_results_into<S>(
3783 device: &Device,
3784 stylesheet: &S,
3785 guard: &SharedRwLockReadGuard,
3786 results: &mut Vec<MediaListKey>,
3787 contents_list: &mut StyleSheetContentList,
3788 custom_media_map: &mut CustomMediaMap,
3789 ) where
3790 S: StylesheetInDocument + 'static,
3791 {
3792 if !stylesheet.enabled() {
3793 return;
3794 }
3795 if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
3796 return;
3797 }
3798
3799 debug!(" + {:?}", stylesheet);
3800 let contents = stylesheet.contents(guard);
3801 results.push(contents.to_media_list_key());
3802
3803 contents_list.push(StylesheetContentsPtr(unsafe {
3805 Arc::from_raw_addrefed(&*contents)
3806 }));
3807
3808 let mut iter = stylesheet
3809 .contents(guard)
3810 .effective_rules(device, custom_media_map, guard);
3811 while let Some(rule) = iter.next() {
3812 match *rule {
3813 CssRule::CustomMedia(ref custom_media) => {
3814 iter.custom_media()
3815 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3816 },
3817 CssRule::Import(ref lock) => {
3818 let import_rule = lock.read_with(guard);
3819 debug!(" + {:?}", import_rule.stylesheet.media(guard));
3820 results.push(import_rule.to_media_list_key());
3821 },
3822 CssRule::Media(ref media_rule) => {
3823 debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3824 results.push(media_rule.to_media_list_key());
3825 },
3826 _ => {},
3827 }
3828 }
3829 }
3830
3831 fn add_styles(
3832 &mut self,
3833 selectors: &SelectorList<SelectorImpl>,
3834 declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3835 ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3836 containing_rule_state: &ContainingRuleState,
3837 mut replaced_selectors: Option<&mut ReplacedSelectors>,
3838 guard: &SharedRwLockReadGuard,
3839 rebuild_kind: SheetRebuildKind,
3840 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3841 quirks_mode: QuirksMode,
3842 mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3843 ) -> Result<(), AllocErr> {
3844 self.num_declarations += declarations.read_with(guard).len();
3845 for selector in selectors.slice() {
3846 self.num_selectors += 1;
3847
3848 let pseudo_elements = selector.pseudo_elements();
3849 let inner_pseudo_element = pseudo_elements.get(0);
3850 if let Some(pseudo) = inner_pseudo_element {
3851 if pseudo.is_precomputed() {
3852 debug_assert!(selector.is_universal());
3853 debug_assert!(ancestor_selectors.is_none());
3854 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3855 debug_assert!(!containing_rule_state.scope_is_effective());
3857 precomputed_pseudo_element_decls
3858 .as_mut()
3859 .expect("Expected precomputed declarations for the UA level")
3860 .get_or_insert_with(pseudo, Vec::new)
3861 .push(ApplicableDeclarationBlock::new(
3862 StyleSource::from_declarations(declarations.clone()),
3863 self.rules_source_order,
3864 CascadeLevel::new(CascadeOrigin::UA),
3865 selector.specificity(),
3866 LayerOrder::root(),
3867 ScopeProximity::infinity(),
3868 RuleCascadeFlags::empty(),
3869 ));
3870 continue;
3871 }
3872 if pseudo_elements
3873 .iter()
3874 .any(|p| p.is_unknown_webkit_pseudo_element())
3875 {
3876 continue;
3877 }
3878 }
3879
3880 debug_assert!(!pseudo_elements
3881 .iter()
3882 .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3883
3884 let selector = match ancestor_selectors {
3885 Some(ref s) => selector.replace_parent_selector(&s),
3886 None => selector.clone(),
3887 };
3888
3889 let hashes = AncestorHashes::new(&selector, quirks_mode);
3890
3891 let rule = Rule::new(
3892 selector,
3893 hashes,
3894 StyleSource::from_declarations(declarations.clone()),
3895 self.rules_source_order,
3896 containing_rule_state.layer_id,
3897 containing_rule_state.container_condition_id,
3898 containing_rule_state.cascade_flags(),
3899 containing_rule_state.containing_scope_rule_state.id,
3900 );
3901
3902 if let Some(ref mut replaced_selectors) = replaced_selectors {
3903 replaced_selectors.push(rule.selector.clone())
3904 }
3905
3906 if rebuild_kind.should_rebuild_invalidation() {
3907 let mut scope_dependencies = note_selector_for_invalidation(
3908 &rule.selector,
3909 quirks_mode,
3910 &mut self.invalidation_map,
3911 &mut self.relative_selector_invalidation_map,
3912 &mut self.additional_relative_selector_invalidation_map,
3913 None,
3914 None,
3915 )?;
3916 let mut needs_revalidation = false;
3917 let mut visitor = StylistSelectorVisitor {
3918 needs_revalidation: &mut needs_revalidation,
3919 passed_rightmost_selector: false,
3920 in_selector_list_of: SelectorListKind::default(),
3921 mapped_ids: &mut self.mapped_ids,
3922 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3923 attribute_dependencies: &mut self.attribute_dependencies,
3924 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3925 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3926 nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3927 state_dependencies: &mut self.state_dependencies,
3928 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3929 document_state_dependencies: &mut self.document_state_dependencies,
3930 };
3931 rule.selector.visit(&mut visitor);
3932
3933 if needs_revalidation {
3934 self.selectors_for_cache_revalidation.insert(
3935 RevalidationSelectorAndHashes::new(
3936 rule.selector.clone(),
3937 rule.hashes.clone(),
3938 ),
3939 quirks_mode,
3940 )?;
3941 }
3942
3943 match (
3944 scope_dependencies.as_mut(),
3945 collected_scope_dependencies.as_mut(),
3946 ) {
3947 (Some(inner_scope_deps), Some(scope_deps)) => {
3948 scope_deps.append(inner_scope_deps)
3949 },
3950 _ => {},
3951 }
3952 }
3953
3954 if let Some(parts) = rule.selector.parts() {
3958 let map = self
3965 .part_rules
3966 .get_or_insert_with(|| Box::new(Default::default()))
3967 .for_insertion(&pseudo_elements);
3968 map.try_reserve(1)?;
3969 let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3970 vec.try_reserve(1)?;
3971 vec.push(rule);
3972 } else {
3973 let scope_matches_shadow_host = containing_rule_state
3974 .containing_scope_rule_state
3975 .matches_shadow_host
3976 == ScopeMatchesShadowHost::Yes;
3977 let matches_featureless_host_only = match rule
3978 .selector
3979 .matches_featureless_host(scope_matches_shadow_host)
3980 {
3981 MatchesFeaturelessHost::Only => true,
3982 MatchesFeaturelessHost::Yes => {
3983 self.featureless_host_rules
3985 .get_or_insert_with(|| Box::new(Default::default()))
3986 .for_insertion(&pseudo_elements)
3987 .insert(rule.clone(), quirks_mode)?;
3988 false
3989 },
3990 MatchesFeaturelessHost::Never => false,
3991 };
3992
3993 let rules = if matches_featureless_host_only {
4000 self.featureless_host_rules
4001 .get_or_insert_with(|| Box::new(Default::default()))
4002 } else if rule.selector.is_slotted() {
4003 self.slotted_rules
4004 .get_or_insert_with(|| Box::new(Default::default()))
4005 } else {
4006 &mut self.normal_rules
4007 }
4008 .for_insertion(&pseudo_elements);
4009 rules.insert(rule, quirks_mode)?;
4010 }
4011 }
4012 self.rules_source_order += 1;
4013 Ok(())
4014 }
4015
4016 fn add_rule_list<S>(
4017 &mut self,
4018 rules: std::slice::Iter<CssRule>,
4019 device: &Device,
4020 quirks_mode: QuirksMode,
4021 stylesheet: &S,
4022 sheet_index: usize,
4023 guard: &SharedRwLockReadGuard,
4024 rebuild_kind: SheetRebuildKind,
4025 containing_rule_state: &mut ContainingRuleState,
4026 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4027 mut difference: Option<&mut CascadeDataDifference>,
4028 ) -> Result<(), AllocErr>
4029 where
4030 S: StylesheetInDocument + 'static,
4031 {
4032 for rule in rules {
4033 let mut handled = true;
4036 let mut list_for_nested_rules = None;
4037 match *rule {
4038 CssRule::Style(ref locked) => {
4039 let style_rule = locked.read_with(guard);
4040 let has_nested_rules = style_rule.rules.is_some();
4041 let mut replaced_selectors = ReplacedSelectors::new();
4042 let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
4043 let collect_replaced_selectors =
4044 has_nested_rules && ancestor_selectors.is_some();
4045 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4046 .scope_is_effective()
4047 .then(|| Vec::new());
4048 self.add_styles(
4049 &style_rule.selectors,
4050 &style_rule.block,
4051 ancestor_selectors,
4052 containing_rule_state,
4053 if collect_replaced_selectors {
4054 Some(&mut replaced_selectors)
4055 } else {
4056 None
4057 },
4058 guard,
4059 rebuild_kind,
4060 precomputed_pseudo_element_decls.as_deref_mut(),
4061 quirks_mode,
4062 inner_dependencies.as_mut(),
4063 )?;
4064 if let Some(mut scope_dependencies) = inner_dependencies {
4065 containing_rule_state
4066 .containing_scope_rule_state
4067 .inner_dependencies
4068 .append(&mut scope_dependencies);
4069 }
4070 if has_nested_rules {
4071 handled = false;
4072 list_for_nested_rules = Some(if collect_replaced_selectors {
4073 SelectorList::from_iter(replaced_selectors.drain(..))
4074 } else {
4075 style_rule.selectors.clone()
4076 });
4077 }
4078 },
4079 CssRule::NestedDeclarations(ref rule) => {
4080 if let Some(ref ancestor_selectors) =
4081 containing_rule_state.ancestor_selector_lists.last()
4082 {
4083 let decls = &rule.read_with(guard).block;
4084 let selectors = match containing_rule_state.nested_declarations_context {
4085 NestedDeclarationsContext::Style => ancestor_selectors,
4086 NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
4087 };
4088 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4089 .scope_is_effective()
4090 .then(|| Vec::new());
4091 self.add_styles(
4092 selectors,
4093 decls,
4094 None,
4095 containing_rule_state,
4096 None,
4097 guard,
4098 SheetRebuildKind::CascadeOnly,
4101 precomputed_pseudo_element_decls.as_deref_mut(),
4102 quirks_mode,
4103 inner_dependencies.as_mut(),
4104 )?;
4105 if let Some(mut scope_dependencies) = inner_dependencies {
4106 containing_rule_state
4107 .containing_scope_rule_state
4108 .inner_dependencies
4109 .append(&mut scope_dependencies);
4110 }
4111 }
4112 },
4113 CssRule::Keyframes(ref keyframes_rule) => {
4114 debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
4115 let keyframes_rule = keyframes_rule.read_with(guard);
4116 let name = keyframes_rule.name.as_atom().clone();
4117 let animation = KeyframesAnimation::from_keyframes(
4118 &keyframes_rule.keyframes,
4119 keyframes_rule.vendor_prefix.clone(),
4120 guard,
4121 );
4122 self.animations.try_insert_with(
4123 name,
4124 animation,
4125 containing_rule_state.layer_id,
4126 compare_keyframes_in_same_layer,
4127 )?;
4128 },
4129 CssRule::Property(ref registration) => {
4130 self.custom_property_registrations.try_insert(
4131 registration.name.0.clone(),
4132 Arc::clone(registration),
4133 containing_rule_state.layer_id,
4134 )?;
4135 },
4136 CssRule::FontFace(ref rule) => {
4137 self.extra_data
4148 .add_font_face(rule, containing_rule_state.layer_id);
4149 },
4150 CssRule::FontFeatureValues(ref rule) => {
4151 self.extra_data
4152 .add_font_feature_values(rule, containing_rule_state.layer_id);
4153 },
4154 CssRule::FontPaletteValues(ref rule) => {
4155 self.extra_data
4156 .add_font_palette_values(rule, containing_rule_state.layer_id);
4157 },
4158 CssRule::CounterStyle(ref rule) => {
4159 self.extra_data.add_counter_style(
4160 guard,
4161 rule,
4162 containing_rule_state.layer_id,
4163 )?;
4164 },
4165 CssRule::PositionTry(ref rule) => {
4166 let name = rule.read_with(guard).name.0.clone();
4167 if let Some(ref mut difference) = difference {
4168 difference.changed_position_try_names.insert(name.clone());
4169 }
4170 self.extra_data.add_position_try(
4171 name,
4172 rule.clone(),
4173 containing_rule_state.layer_id,
4174 )?;
4175 },
4176 CssRule::Page(ref rule) => {
4177 self.extra_data
4178 .add_page(guard, rule, containing_rule_state.layer_id)?;
4179 handled = false;
4180 },
4181 CssRule::ViewTransition(ref rule) => {
4182 self.extra_data
4183 .add_view_transition(rule, containing_rule_state.layer_id);
4184 },
4185 _ => {
4186 handled = false;
4187 },
4188 }
4189
4190 if handled {
4191 if cfg!(debug_assertions) {
4194 let mut effective = false;
4195 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4196 rule,
4197 device,
4198 quirks_mode,
4199 &self.custom_media,
4200 guard,
4201 &mut effective,
4202 );
4203 debug_assert!(children.is_empty());
4204 debug_assert!(effective);
4205 }
4206 continue;
4207 }
4208
4209 let mut effective = false;
4210 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4211 rule,
4212 device,
4213 quirks_mode,
4214 &self.custom_media,
4215 guard,
4216 &mut effective,
4217 );
4218 if !effective {
4219 continue;
4220 }
4221
4222 fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4223 if let Some(id) = data.layer_id.get(layer) {
4227 return *id;
4228 }
4229 let id = LayerId(data.layers.len() as u16);
4230
4231 let parent_layer_id = if layer.layer_names().len() > 1 {
4232 let mut parent = layer.clone();
4233 parent.0.pop();
4234
4235 *data
4236 .layer_id
4237 .get_mut(&parent)
4238 .expect("Parent layers should be registered before child layers")
4239 } else {
4240 LayerId::root()
4241 };
4242
4243 data.layers[parent_layer_id.0 as usize].children.push(id);
4244 data.layers.push(CascadeLayer {
4245 id,
4246 order: LayerOrder::first(),
4249 children: vec![],
4250 });
4251
4252 data.layer_id.insert(layer.clone(), id);
4253
4254 id
4255 }
4256
4257 fn maybe_register_layers(
4258 data: &mut CascadeData,
4259 name: Option<&LayerName>,
4260 containing_rule_state: &mut ContainingRuleState,
4261 ) {
4262 let anon_name;
4263 let name = match name {
4264 Some(name) => name,
4265 None => {
4266 anon_name = LayerName::new_anonymous();
4267 &anon_name
4268 },
4269 };
4270 for name in name.layer_names() {
4271 containing_rule_state.layer_name.0.push(name.clone());
4272 containing_rule_state.layer_id =
4273 maybe_register_layer(data, &containing_rule_state.layer_name);
4274 }
4275 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4276 }
4277
4278 let saved_containing_rule_state = containing_rule_state.save();
4279 match *rule {
4280 CssRule::Import(ref lock) => {
4281 let import_rule = lock.read_with(guard);
4282 if rebuild_kind.should_rebuild_invalidation() {
4283 self.effective_media_query_results
4284 .saw_effective(import_rule);
4285 }
4286 match import_rule.layer {
4287 ImportLayer::Named(ref name) => {
4288 maybe_register_layers(self, Some(name), containing_rule_state)
4289 },
4290 ImportLayer::Anonymous => {
4291 maybe_register_layers(self, None, containing_rule_state)
4292 },
4293 ImportLayer::None => {},
4294 }
4295 },
4296 CssRule::Media(ref media_rule) => {
4297 if rebuild_kind.should_rebuild_invalidation() {
4298 self.effective_media_query_results
4299 .saw_effective(&**media_rule);
4300 }
4301 },
4302 CssRule::LayerBlock(ref rule) => {
4303 maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4304 },
4305 CssRule::CustomMedia(ref custom_media) => {
4306 self.custom_media
4307 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4308 },
4309 CssRule::LayerStatement(ref rule) => {
4310 for name in &*rule.names {
4311 maybe_register_layers(self, Some(name), containing_rule_state);
4312 containing_rule_state.restore(&saved_containing_rule_state);
4314 }
4315 },
4316 CssRule::Style(..) => {
4317 containing_rule_state.nested_declarations_context =
4318 NestedDeclarationsContext::Style;
4319 if let Some(s) = list_for_nested_rules {
4320 containing_rule_state.ancestor_selector_lists.push(s);
4321 }
4322 },
4323 CssRule::Container(ref rule) => {
4324 let id = ContainerConditionId(self.container_conditions.len() as u16);
4325 let condition = ContainerConditionReference {
4326 parent: containing_rule_state.container_condition_id,
4327 conditions: rule.conditions.0.clone(),
4328 };
4329 self.container_conditions.push(condition);
4330 containing_rule_state.container_condition_id = id;
4331 },
4332 CssRule::StartingStyle(..) => {
4333 containing_rule_state
4334 .cascade_flags
4335 .insert(RuleCascadeFlags::STARTING_STYLE);
4336 },
4337 CssRule::AppearanceBase(..) => {
4338 containing_rule_state
4339 .cascade_flags
4340 .insert(RuleCascadeFlags::APPEARANCE_BASE);
4341 },
4342 CssRule::Scope(ref rule) => {
4343 containing_rule_state.nested_declarations_context =
4344 NestedDeclarationsContext::Scope;
4345 let id = ScopeConditionId(self.scope_conditions.len() as u16);
4346 let mut matches_shadow_host = false;
4347 let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4348 matches_shadow_host = scope_start_matches_shadow_host(start);
4349 StylistImplicitScopeRoot::default()
4351 } else {
4352 if let Some(root) = stylesheet.implicit_scope_root() {
4355 matches_shadow_host = root.matches_shadow_host();
4356 match root {
4357 ImplicitScopeRoot::InLightTree(_)
4358 | ImplicitScopeRoot::Constructed
4359 | ImplicitScopeRoot::DocumentElement => {
4360 StylistImplicitScopeRoot::Normal(root)
4361 },
4362 ImplicitScopeRoot::ShadowHost(_)
4363 | ImplicitScopeRoot::InShadowTree(_) => {
4364 StylistImplicitScopeRoot::Cached(sheet_index)
4371 },
4372 }
4373 } else {
4374 StylistImplicitScopeRoot::default()
4376 }
4377 };
4378
4379 let replaced =
4380 {
4381 let start = rule.bounds.start.as_ref().map(|selector| {
4382 match containing_rule_state.ancestor_selector_lists.last() {
4383 Some(s) => selector.replace_parent_selector(s),
4384 None => selector.clone(),
4385 }
4386 });
4387 let implicit_scope_selector = &*IMPLICIT_SCOPE;
4388 let end = rule.bounds.end.as_ref().map(|selector| {
4389 selector.replace_parent_selector(implicit_scope_selector)
4390 });
4391 containing_rule_state
4392 .ancestor_selector_lists
4393 .push(implicit_scope_selector.clone());
4394 ScopeBoundsWithHashes::new(quirks_mode, start, end)
4395 };
4396
4397 if let Some(selectors) = replaced.start.as_ref() {
4398 self.scope_subject_map
4399 .add_bound_start(&selectors.selectors, quirks_mode);
4400 }
4401
4402 let is_trivial = replaced.is_trivial();
4403 self.scope_conditions.push(ScopeConditionReference {
4404 parent: containing_rule_state.containing_scope_rule_state.id,
4405 condition: Some(replaced),
4406 implicit_scope_root,
4407 is_trivial,
4408 });
4409
4410 containing_rule_state
4411 .containing_scope_rule_state
4412 .matches_shadow_host
4413 .nest_for_scope(matches_shadow_host);
4414 containing_rule_state.containing_scope_rule_state.id = id;
4415 containing_rule_state
4416 .containing_scope_rule_state
4417 .inner_dependencies
4418 .reserve(children.iter().len());
4419 },
4420 _ => {},
4422 }
4423
4424 if !children.is_empty() {
4425 self.add_rule_list(
4426 children.iter(),
4427 device,
4428 quirks_mode,
4429 stylesheet,
4430 sheet_index,
4431 guard,
4432 rebuild_kind,
4433 containing_rule_state,
4434 precomputed_pseudo_element_decls.as_deref_mut(),
4435 difference.as_deref_mut(),
4436 )?;
4437 }
4438
4439 if let Some(scope_restore_data) =
4440 containing_rule_state.restore(&saved_containing_rule_state)
4441 {
4442 let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4443 let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4444 if let Some(cond) = cur_scope.condition.as_ref() {
4445 let mut _unused = false;
4446 let visitor = StylistSelectorVisitor {
4447 needs_revalidation: &mut _unused,
4448 passed_rightmost_selector: true,
4449 in_selector_list_of: SelectorListKind::default(),
4450 mapped_ids: &mut self.mapped_ids,
4451 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4452 attribute_dependencies: &mut self.attribute_dependencies,
4453 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4454 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4455 nth_of_custom_state_dependencies: &mut self
4456 .nth_of_custom_state_dependencies,
4457 state_dependencies: &mut self.state_dependencies,
4458 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4459 document_state_dependencies: &mut self.document_state_dependencies,
4460 };
4461
4462 let dependency_vector = build_scope_dependencies(
4463 quirks_mode,
4464 cur_scope_inner_dependencies,
4465 visitor,
4466 cond,
4467 &mut self.invalidation_map,
4468 &mut self.relative_selector_invalidation_map,
4469 &mut self.additional_relative_selector_invalidation_map,
4470 )?;
4471
4472 containing_rule_state
4473 .containing_scope_rule_state
4474 .inner_dependencies
4475 .extend(dependency_vector);
4476 }
4477 }
4478 }
4479
4480 Ok(())
4481 }
4482
4483 fn add_stylesheet<S>(
4485 &mut self,
4486 device: &Device,
4487 quirks_mode: QuirksMode,
4488 stylesheet: &S,
4489 sheet_index: usize,
4490 guard: &SharedRwLockReadGuard,
4491 rebuild_kind: SheetRebuildKind,
4492 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4493 mut difference: Option<&mut CascadeDataDifference>,
4494 ) -> Result<(), AllocErr>
4495 where
4496 S: StylesheetInDocument + 'static,
4497 {
4498 if !stylesheet.enabled() {
4499 return Ok(());
4500 }
4501
4502 if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4503 return Ok(());
4504 }
4505
4506 let contents = stylesheet.contents(guard);
4507 if rebuild_kind.should_rebuild_invalidation() {
4508 self.effective_media_query_results.saw_effective(&*contents);
4509 }
4510
4511 let mut state = ContainingRuleState::default();
4512 self.add_rule_list(
4513 contents.rules(guard).iter(),
4514 device,
4515 quirks_mode,
4516 stylesheet,
4517 sheet_index,
4518 guard,
4519 rebuild_kind,
4520 &mut state,
4521 precomputed_pseudo_element_decls.as_deref_mut(),
4522 difference.as_deref_mut(),
4523 )?;
4524
4525 Ok(())
4526 }
4527
4528 pub fn media_feature_affected_matches<S>(
4531 &self,
4532 stylesheet: &S,
4533 guard: &SharedRwLockReadGuard,
4534 device: &Device,
4535 quirks_mode: QuirksMode,
4536 ) -> bool
4537 where
4538 S: StylesheetInDocument + 'static,
4539 {
4540 use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4541
4542 let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4543
4544 let contents = stylesheet.contents(guard);
4545 let effective_then = self.effective_media_query_results.was_effective(contents);
4546
4547 if effective_now != effective_then {
4548 debug!(
4549 " > Stylesheet {:?} changed -> {}, {}",
4550 stylesheet.media(guard),
4551 effective_then,
4552 effective_now
4553 );
4554 return false;
4555 }
4556
4557 if !effective_now {
4558 return true;
4559 }
4560
4561 let custom_media = CustomMediaMap::default();
4563 let mut iter =
4564 contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4565 while let Some(rule) = iter.next() {
4566 match *rule {
4567 CssRule::Style(..)
4568 | CssRule::NestedDeclarations(..)
4569 | CssRule::Namespace(..)
4570 | CssRule::FontFace(..)
4571 | CssRule::Container(..)
4572 | CssRule::CounterStyle(..)
4573 | CssRule::Supports(..)
4574 | CssRule::Keyframes(..)
4575 | CssRule::Margin(..)
4576 | CssRule::Page(..)
4577 | CssRule::Property(..)
4578 | CssRule::Document(..)
4579 | CssRule::LayerBlock(..)
4580 | CssRule::LayerStatement(..)
4581 | CssRule::FontPaletteValues(..)
4582 | CssRule::FontFeatureValues(..)
4583 | CssRule::Scope(..)
4584 | CssRule::StartingStyle(..)
4585 | CssRule::AppearanceBase(..)
4586 | CssRule::CustomMedia(..)
4587 | CssRule::PositionTry(..)
4588 | CssRule::ViewTransition(..) => {
4589 continue;
4592 },
4593 CssRule::Import(ref lock) => {
4594 let import_rule = lock.read_with(guard);
4595 let effective_now = match import_rule.stylesheet.media(guard) {
4596 Some(m) => m.evaluate(
4597 device,
4598 quirks_mode,
4599 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4600 ),
4601 None => true,
4602 };
4603 let effective_then = self
4604 .effective_media_query_results
4605 .was_effective(import_rule);
4606 if effective_now != effective_then {
4607 debug!(
4608 " > @import rule {:?} changed {} -> {}",
4609 import_rule.stylesheet.media(guard),
4610 effective_then,
4611 effective_now
4612 );
4613 return false;
4614 }
4615
4616 if !effective_now {
4617 iter.skip_children();
4618 }
4619 },
4620 CssRule::Media(ref media_rule) => {
4621 let mq = media_rule.media_queries.read_with(guard);
4622 let effective_now = mq.evaluate(
4623 device,
4624 quirks_mode,
4625 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4626 );
4627 let effective_then = self
4628 .effective_media_query_results
4629 .was_effective(&**media_rule);
4630
4631 if effective_now != effective_then {
4632 debug!(
4633 " > @media rule {:?} changed {} -> {}",
4634 mq, effective_then, effective_now
4635 );
4636 return false;
4637 }
4638
4639 if !effective_now {
4640 iter.skip_children();
4641 }
4642 },
4643 }
4644 }
4645
4646 true
4647 }
4648
4649 pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4651 &self.custom_property_registrations
4652 }
4653
4654 fn revalidate_scopes<E: TElement>(
4655 &self,
4656 element: &E,
4657 matching_context: &mut MatchingContext<E::Impl>,
4658 result: &mut ScopeRevalidationResult,
4659 ) {
4660 for condition_id in 1..self.scope_conditions.len() {
4667 let condition = &self.scope_conditions[condition_id];
4668 let matches = if condition.is_trivial {
4669 continue;
4672 } else {
4673 let result = scope_root_candidates(
4674 &self.scope_conditions,
4675 ScopeConditionId(condition_id as u16),
4676 element,
4677 false,
4679 &self.scope_subject_map,
4680 matching_context,
4681 );
4682 !result.candidates.is_empty()
4683 };
4684 result.scopes_matched.push(matches);
4685 }
4686 }
4687
4688 fn clear_cascade_data(&mut self) {
4690 self.normal_rules.clear();
4691 if let Some(ref mut slotted_rules) = self.slotted_rules {
4692 slotted_rules.clear();
4693 }
4694 if let Some(ref mut part_rules) = self.part_rules {
4695 part_rules.clear();
4696 }
4697 if let Some(ref mut host_rules) = self.featureless_host_rules {
4698 host_rules.clear();
4699 }
4700 self.animations.clear();
4701 self.custom_property_registrations.clear();
4702 self.layer_id.clear();
4703 self.layers.clear();
4704 self.layers.push(CascadeLayer::root());
4705 self.custom_media.clear();
4706 self.container_conditions.clear();
4707 self.container_conditions
4708 .push(ContainerConditionReference::none());
4709 self.scope_conditions.clear();
4710 self.scope_conditions.push(ScopeConditionReference::none());
4711 self.extra_data.clear();
4712 self.rules_source_order = 0;
4713 self.num_selectors = 0;
4714 self.num_declarations = 0;
4715 }
4716
4717 fn clear_invalidation_data(&mut self) {
4718 self.invalidation_map.clear();
4719 self.relative_selector_invalidation_map.clear();
4720 self.additional_relative_selector_invalidation_map.clear();
4721 self.attribute_dependencies.clear();
4722 self.nth_of_attribute_dependencies.clear();
4723 self.nth_of_custom_state_dependencies.clear();
4724 self.nth_of_class_dependencies.clear();
4725 self.state_dependencies = ElementState::empty();
4726 self.nth_of_state_dependencies = ElementState::empty();
4727 self.document_state_dependencies = DocumentState::empty();
4728 self.mapped_ids.clear();
4729 self.nth_of_mapped_ids.clear();
4730 self.selectors_for_cache_revalidation.clear();
4731 self.effective_media_query_results.clear();
4732 self.scope_subject_map.clear();
4733 }
4734}
4735
4736fn note_scope_selector_for_invalidation(
4737 quirks_mode: QuirksMode,
4738 scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4739 dependency_vector: &mut Vec<Dependency>,
4740 invalidation_map: &mut InvalidationMap,
4741 relative_selector_invalidation_map: &mut InvalidationMap,
4742 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4743 visitor: &mut StylistSelectorVisitor<'_>,
4744 scope_kind: ScopeDependencyInvalidationKind,
4745 s: &Selector<SelectorImpl>,
4746) -> Result<(), AllocErr> {
4747 let mut new_inner_dependencies = note_selector_for_invalidation(
4748 &s.clone(),
4749 quirks_mode,
4750 invalidation_map,
4751 relative_selector_invalidation_map,
4752 additional_relative_selector_invalidation_map,
4753 Some(&scope_dependencies),
4754 Some(scope_kind),
4755 )?;
4756 s.visit(visitor);
4757 new_inner_dependencies.as_mut().map(|dep| {
4758 dependency_vector.append(dep);
4759 });
4760 Ok(())
4761}
4762
4763fn build_scope_dependencies(
4764 quirks_mode: QuirksMode,
4765 mut cur_scope_inner_dependencies: Vec<Dependency>,
4766 mut visitor: StylistSelectorVisitor<'_>,
4767 cond: &ScopeBoundsWithHashes,
4768 mut invalidation_map: &mut InvalidationMap,
4769 mut relative_selector_invalidation_map: &mut InvalidationMap,
4770 mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4771) -> Result<Vec<Dependency>, AllocErr> {
4772 if cond.end.is_some() {
4773 let deps =
4774 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4775 let mut end_dependency_vector = Vec::new();
4776 for s in cond.end_selectors() {
4777 note_scope_selector_for_invalidation(
4778 quirks_mode,
4779 &deps,
4780 &mut end_dependency_vector,
4781 &mut invalidation_map,
4782 &mut relative_selector_invalidation_map,
4783 &mut additional_relative_selector_invalidation_map,
4784 &mut visitor,
4785 ScopeDependencyInvalidationKind::ScopeEnd,
4786 s,
4787 )?;
4788 }
4789 cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4790 }
4791 let inner_scope_dependencies =
4792 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4793
4794 Ok(if cond.start.is_some() {
4795 let mut dependency_vector = Vec::new();
4796 for s in cond.start_selectors() {
4797 note_scope_selector_for_invalidation(
4798 quirks_mode,
4799 &inner_scope_dependencies,
4800 &mut dependency_vector,
4801 &mut invalidation_map,
4802 &mut relative_selector_invalidation_map,
4803 &mut additional_relative_selector_invalidation_map,
4804 &mut visitor,
4805 ScopeDependencyInvalidationKind::ExplicitScope,
4806 s,
4807 )?;
4808 }
4809 dependency_vector
4810 } else {
4811 vec![Dependency::new(
4812 IMPLICIT_SCOPE.slice()[0].clone(),
4813 0,
4814 Some(inner_scope_dependencies),
4815 DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4816 )]
4817 })
4818}
4819
4820impl CascadeDataCacheEntry for CascadeData {
4821 fn rebuild<S>(
4822 device: &Device,
4823 quirks_mode: QuirksMode,
4824 collection: SheetCollectionFlusher<S>,
4825 guard: &SharedRwLockReadGuard,
4826 old: &Self,
4827 difference: &mut CascadeDataDifference,
4828 ) -> Result<Arc<Self>, AllocErr>
4829 where
4830 S: StylesheetInDocument + PartialEq + 'static,
4831 {
4832 debug_assert!(collection.dirty(), "We surely need to do something?");
4833 let mut updatable_entry = match collection.data_validity() {
4835 DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4836 DataValidity::FullyInvalid => Self::new(),
4837 };
4838 updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4839 Ok(Arc::new(updatable_entry))
4840 }
4841
4842 #[cfg(feature = "gecko")]
4843 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4844 self.normal_rules.add_size_of(ops, sizes);
4845 if let Some(ref slotted_rules) = self.slotted_rules {
4846 slotted_rules.add_size_of(ops, sizes);
4847 }
4848 if let Some(ref part_rules) = self.part_rules {
4849 part_rules.add_size_of(ops, sizes);
4850 }
4851 if let Some(ref host_rules) = self.featureless_host_rules {
4852 host_rules.add_size_of(ops, sizes);
4853 }
4854 sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4855 sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4856 sizes.mOther += self.animations.size_of(ops);
4857 sizes.mOther += self.effective_media_query_results.size_of(ops);
4858 sizes.mOther += self.extra_data.size_of(ops);
4859 }
4860}
4861
4862impl Default for CascadeData {
4863 fn default() -> Self {
4864 CascadeData::new()
4865 }
4866}
4867
4868#[derive(Clone, Debug, MallocSizeOf)]
4871pub struct Rule {
4872 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4877 pub selector: Selector<SelectorImpl>,
4878
4879 pub hashes: AncestorHashes,
4881
4882 pub source_order: u32,
4886
4887 pub layer_id: LayerId,
4889
4890 pub container_condition_id: ContainerConditionId,
4892
4893 pub cascade_flags: RuleCascadeFlags,
4895
4896 pub scope_condition_id: ScopeConditionId,
4898
4899 #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4901 pub style_source: StyleSource,
4902}
4903
4904impl SelectorMapEntry for Rule {
4905 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4906 self.selector.iter()
4907 }
4908}
4909
4910impl Rule {
4911 pub fn specificity(&self) -> u32 {
4913 self.selector.specificity()
4914 }
4915
4916 pub fn to_applicable_declaration_block(
4919 &self,
4920 level: CascadeLevel,
4921 cascade_data: &CascadeData,
4922 scope_proximity: ScopeProximity,
4923 ) -> ApplicableDeclarationBlock {
4924 ApplicableDeclarationBlock::new(
4925 self.style_source.clone(),
4926 self.source_order,
4927 level,
4928 self.specificity(),
4929 cascade_data.layer_order_for(self.layer_id),
4930 scope_proximity,
4931 self.cascade_flags,
4932 )
4933 }
4934
4935 pub fn new(
4937 selector: Selector<SelectorImpl>,
4938 hashes: AncestorHashes,
4939 style_source: StyleSource,
4940 source_order: u32,
4941 layer_id: LayerId,
4942 container_condition_id: ContainerConditionId,
4943 cascade_flags: RuleCascadeFlags,
4944 scope_condition_id: ScopeConditionId,
4945 ) -> Self {
4946 Self {
4947 selector,
4948 hashes,
4949 style_source,
4950 source_order,
4951 layer_id,
4952 container_condition_id,
4953 cascade_flags,
4954 scope_condition_id,
4955 }
4956 }
4957}
4958
4959size_of_test!(Rule, 40);
4964
4965pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4967 let mut needs_revalidation = false;
4968 let mut mapped_ids = Default::default();
4969 let mut nth_of_mapped_ids = Default::default();
4970 let mut attribute_dependencies = Default::default();
4971 let mut nth_of_class_dependencies = Default::default();
4972 let mut nth_of_attribute_dependencies = Default::default();
4973 let mut nth_of_custom_state_dependencies = Default::default();
4974 let mut state_dependencies = ElementState::empty();
4975 let mut nth_of_state_dependencies = ElementState::empty();
4976 let mut document_state_dependencies = DocumentState::empty();
4977 let mut visitor = StylistSelectorVisitor {
4978 passed_rightmost_selector: false,
4979 needs_revalidation: &mut needs_revalidation,
4980 in_selector_list_of: SelectorListKind::default(),
4981 mapped_ids: &mut mapped_ids,
4982 nth_of_mapped_ids: &mut nth_of_mapped_ids,
4983 attribute_dependencies: &mut attribute_dependencies,
4984 nth_of_class_dependencies: &mut nth_of_class_dependencies,
4985 nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4986 nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4987 state_dependencies: &mut state_dependencies,
4988 nth_of_state_dependencies: &mut nth_of_state_dependencies,
4989 document_state_dependencies: &mut document_state_dependencies,
4990 };
4991 s.visit(&mut visitor);
4992 needs_revalidation
4993}