1use crate::applicable_declarations::{
8 ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
9};
10use crate::computed_value_flags::ComputedValueFlags;
11use crate::context::{CascadeInputs, QuirksMode};
12use crate::custom_properties::ComputedCustomProperties;
13use crate::custom_properties::{parse_name, SpecifiedValue};
14use crate::derives::*;
15use crate::device::Device;
16use crate::dom::TElement;
17#[cfg(feature = "gecko")]
18use crate::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 context = computed::Context::new_for_initial_at_property_value(
933 self,
934 &mut rule_cache_conditions,
935 );
936
937 for (k, v) in self.custom_property_script_registry().properties().iter() {
938 seen_names.insert(k.clone());
939 let Ok(value) = v.compute_initial_value(&context) else {
940 continue;
941 };
942 let map = if v.descriptors.inherits() {
943 &mut initial_values.inherited
944 } else {
945 &mut initial_values.non_inherited
946 };
947 map.insert(k, value);
948 }
949 for (data, _) in self.iter_origins() {
950 for (k, v) in data.custom_property_registrations.iter() {
951 if seen_names.insert(k.clone()) {
952 let last_value = &v.last().unwrap().0;
953 let Ok(value) = last_value.compute_initial_value(&context) else {
954 continue;
955 };
956 let map = if last_value.descriptors.inherits() {
957 &mut initial_values.inherited
958 } else {
959 &mut initial_values.non_inherited
960 };
961 map.insert(k, value);
962 }
963 }
964 }
965 initial_values_flags = context.builder.flags();
966 }
967 self.initial_values_for_custom_properties_flags = initial_values_flags;
968 self.initial_values_for_custom_properties = initial_values;
969 }
970
971 pub fn rebuild_author_data<S>(
973 &mut self,
974 old_data: &CascadeData,
975 collection: SheetCollectionFlusher<S>,
976 guard: &SharedRwLockReadGuard,
977 difference: &mut CascadeDataDifference,
978 ) -> Result<Option<Arc<CascadeData>>, AllocErr>
979 where
980 S: StylesheetInDocument + PartialEq + 'static,
981 {
982 self.author_data_cache.lookup(
983 &self.device,
984 self.quirks_mode,
985 collection,
986 guard,
987 old_data,
988 difference,
989 )
990 }
991
992 #[inline]
994 pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
995 ExtraStyleDataIterator(self.cascade_data.iter_origins())
996 }
997
998 #[inline]
1000 pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
1001 ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
1002 }
1003
1004 pub fn num_selectors(&self) -> usize {
1006 self.cascade_data
1007 .iter_origins()
1008 .map(|(d, _)| d.num_selectors)
1009 .sum()
1010 }
1011
1012 pub fn num_declarations(&self) -> usize {
1014 self.cascade_data
1015 .iter_origins()
1016 .map(|(d, _)| d.num_declarations)
1017 .sum()
1018 }
1019
1020 pub fn num_rebuilds(&self) -> usize {
1022 self.num_rebuilds
1023 }
1024
1025 pub fn num_revalidation_selectors(&self) -> usize {
1027 self.cascade_data
1028 .iter_origins()
1029 .map(|(data, _)| data.selectors_for_cache_revalidation.len())
1030 .sum()
1031 }
1032
1033 pub fn num_invalidations(&self) -> usize {
1035 self.cascade_data
1036 .iter_origins()
1037 .map(|(data, _)| {
1038 data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
1039 })
1040 .sum()
1041 }
1042
1043 pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
1046 self.cascade_data
1047 .iter_origins()
1048 .any(|(d, _)| d.document_state_dependencies.intersects(state))
1049 }
1050
1051 pub fn flush(&mut self, guards: &StylesheetGuards) -> StylesheetInvalidationSet {
1054 if !self.stylesheets.has_changed() {
1055 return Default::default();
1056 }
1057
1058 self.num_rebuilds += 1;
1059
1060 let (flusher, mut invalidations) = self.stylesheets.flush();
1061
1062 self.cascade_data
1063 .rebuild(
1064 &self.device,
1065 self.quirks_mode,
1066 flusher,
1067 guards,
1068 &mut invalidations.cascade_data_difference,
1069 )
1070 .unwrap_or_else(|_| {
1071 warn!("OOM in Stylist::flush");
1072 });
1073
1074 self.rebuild_initial_values_for_custom_properties();
1075 invalidations
1076 }
1077
1078 pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
1084 self.stylesheets.force_dirty(origins)
1085 }
1086
1087 pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
1089 self.author_styles_enabled = enabled;
1090 }
1091
1092 pub fn stylesheets_have_changed(&self) -> bool {
1094 self.stylesheets.has_changed()
1095 }
1096
1097 pub fn insert_stylesheet_before(
1099 &mut self,
1100 sheet: StylistSheet,
1101 before_sheet: StylistSheet,
1102 guard: &SharedRwLockReadGuard,
1103 ) {
1104 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1105 self.stylesheets.insert_stylesheet_before(
1106 Some(&self.device),
1107 custom_media,
1108 sheet,
1109 before_sheet,
1110 guard,
1111 )
1112 }
1113
1114 pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1116 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1117 self.stylesheets
1118 .append_stylesheet(Some(&self.device), custom_media, sheet, guard)
1119 }
1120
1121 pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1123 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1124 self.stylesheets
1125 .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
1126 }
1127
1128 pub fn rule_changed(
1130 &mut self,
1131 sheet: &StylistSheet,
1132 rule: &CssRule,
1133 guard: &SharedRwLockReadGuard,
1134 change_kind: RuleChangeKind,
1135 ancestors: &[CssRuleRef],
1136 ) {
1137 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1138 self.stylesheets.rule_changed(
1139 Some(&self.device),
1140 custom_media,
1141 sheet,
1142 rule,
1143 guard,
1144 change_kind,
1145 ancestors,
1146 )
1147 }
1148
1149 #[inline]
1151 pub fn sheet_count(&self, origin: Origin) -> usize {
1152 self.stylesheets.sheet_count(origin)
1153 }
1154
1155 #[inline]
1157 pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
1158 self.stylesheets.get(origin, index)
1159 }
1160
1161 pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
1164 where
1165 E: TElement,
1166 F: FnMut(&CascadeData) -> bool,
1167 {
1168 if f(&self.cascade_data.user_agent.cascade_data) {
1169 return true;
1170 }
1171
1172 let mut maybe = false;
1173
1174 let doc_author_rules_apply =
1175 element.each_applicable_non_document_style_rule_data(|data, _| {
1176 maybe = maybe || f(&*data);
1177 });
1178
1179 if maybe || f(&self.cascade_data.user) {
1180 return true;
1181 }
1182
1183 doc_author_rules_apply && f(&self.cascade_data.author)
1184 }
1185
1186 pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1188 where
1189 E: TElement + 'a,
1190 F: FnMut(&'a CascadeData, Option<E>),
1191 {
1192 f(&self.cascade_data.user_agent.cascade_data, None);
1193 element.each_applicable_non_document_style_rule_data(|data, scope| {
1194 f(data, Some(scope));
1195 });
1196 f(&self.cascade_data.user, None);
1197 f(&self.cascade_data.author, None);
1198 }
1199
1200 pub fn precomputed_values_for_pseudo<E>(
1203 &self,
1204 guards: &StylesheetGuards,
1205 pseudo: &PseudoElement,
1206 parent: Option<&ComputedValues>,
1207 ) -> Arc<ComputedValues>
1208 where
1209 E: TElement,
1210 {
1211 debug_assert!(pseudo.is_precomputed());
1212
1213 let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1214
1215 self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1216 }
1217
1218 pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1224 &self,
1225 guards: &StylesheetGuards,
1226 pseudo: &PseudoElement,
1227 parent: Option<&ComputedValues>,
1228 rules: StrongRuleNode,
1229 ) -> Arc<ComputedValues>
1230 where
1231 E: TElement,
1232 {
1233 self.compute_pseudo_element_style_with_inputs::<E>(
1234 CascadeInputs {
1235 rules: Some(rules),
1236 visited_rules: None,
1237 flags: Default::default(),
1238 included_cascade_flags: RuleCascadeFlags::empty(),
1239 },
1240 pseudo,
1241 guards,
1242 parent,
1243 None,
1244 )
1245 }
1246
1247 pub fn rule_node_for_precomputed_pseudo(
1253 &self,
1254 guards: &StylesheetGuards,
1255 pseudo: &PseudoElement,
1256 mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1257 ) -> StrongRuleNode {
1258 let mut declarations_with_extra;
1259 let declarations = match self
1260 .cascade_data
1261 .user_agent
1262 .precomputed_pseudo_element_decls
1263 .get(pseudo)
1264 {
1265 Some(declarations) => {
1266 if !extra_declarations.is_empty() {
1267 declarations_with_extra = declarations.clone();
1268 declarations_with_extra.append(&mut extra_declarations);
1269 &*declarations_with_extra
1270 } else {
1271 &**declarations
1272 }
1273 },
1274 None => &[],
1275 };
1276
1277 self.rule_tree.insert_ordered_rules_with_important(
1278 declarations.into_iter().map(|a| a.clone().for_rule_tree()),
1279 guards,
1280 )
1281 }
1282
1283 #[cfg(feature = "servo")]
1288 pub fn style_for_anonymous<E>(
1289 &self,
1290 guards: &StylesheetGuards,
1291 pseudo: &PseudoElement,
1292 parent_style: &ComputedValues,
1293 ) -> Arc<ComputedValues>
1294 where
1295 E: TElement,
1296 {
1297 self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1298 }
1299
1300 pub fn lazily_compute_pseudo_element_style<E>(
1308 &self,
1309 guards: &StylesheetGuards,
1310 element: E,
1311 pseudo: &PseudoElement,
1312 rule_inclusion: RuleInclusion,
1313 originating_element_style: &ComputedValues,
1314 is_probe: bool,
1315 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1316 ) -> Option<Arc<ComputedValues>>
1317 where
1318 E: TElement,
1319 {
1320 let cascade_inputs = self.lazy_pseudo_rules(
1321 guards,
1322 element,
1323 originating_element_style,
1324 pseudo,
1325 is_probe,
1326 rule_inclusion,
1327 matching_fn,
1328 )?;
1329
1330 Some(self.compute_pseudo_element_style_with_inputs(
1331 cascade_inputs,
1332 pseudo,
1333 guards,
1334 Some(originating_element_style),
1335 Some(element),
1336 ))
1337 }
1338
1339 pub fn compute_pseudo_element_style_with_inputs<E>(
1344 &self,
1345 inputs: CascadeInputs,
1346 pseudo: &PseudoElement,
1347 guards: &StylesheetGuards,
1348 parent_style: Option<&ComputedValues>,
1349 element: Option<E>,
1350 ) -> Arc<ComputedValues>
1351 where
1352 E: TElement,
1353 {
1354 self.cascade_style_and_visited(
1367 element,
1368 Some(pseudo),
1369 &inputs,
1370 guards,
1371 parent_style,
1372 parent_style,
1373 FirstLineReparenting::No,
1374 &PositionTryFallbacksTryTactic::default(),
1375 None,
1376 &mut RuleCacheConditions::default(),
1377 )
1378 }
1379
1380 #[cfg(feature = "gecko")]
1382 pub fn resolve_position_try<E>(
1383 &self,
1384 style: &ComputedValues,
1385 guards: &StylesheetGuards,
1386 scope: CascadeLevel,
1387 element: E,
1388 fallback_item: &PositionTryFallbacksItem,
1389 ) -> Option<Arc<ComputedValues>>
1390 where
1391 E: TElement,
1392 {
1393 let name_and_try_tactic = match *fallback_item {
1394 PositionTryFallbacksItem::PositionArea(area) => {
1395 let mut builder =
1399 StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
1400 builder.rules = style.rules.clone();
1401 builder.mutate_position().set_position_area(area);
1402 return Some(builder.build());
1403 },
1404 PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
1405 name_and_try_tactic
1406 },
1407 };
1408
1409 let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
1410 Some(self.lookup_position_try(&name_and_try_tactic.ident.0, scope, element)?)
1411 } else {
1412 None
1413 };
1414 let fallback_block = fallback_rule
1415 .as_ref()
1416 .map(|r| &r.read_with(guards.author).block);
1417 let pseudo = style
1418 .pseudo()
1419 .or_else(|| element.implemented_pseudo_element());
1420 let inputs = {
1421 let mut inputs = CascadeInputs::new_from_style(style);
1422 inputs.visited_rules = None;
1424 let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
1425 let mut important_rules_changed = false;
1426 if let Some(fallback_block) = fallback_block {
1427 let new_rules = self.rule_tree.update_rule_at_level(
1428 CascadeLevel::new(CascadeOrigin::PositionFallback),
1429 LayerOrder::root(),
1430 Some(fallback_block.borrow_arc()),
1431 rules,
1432 guards,
1433 &mut important_rules_changed,
1434 );
1435 if new_rules.is_some() {
1436 inputs.rules = new_rules;
1437 } else {
1438 }
1442 }
1443 inputs
1444 };
1445 crate::style_resolver::with_default_parent_styles(
1446 element,
1447 |parent_style, layout_parent_style| {
1448 Some(self.cascade_style_and_visited(
1449 Some(element),
1450 pseudo.as_ref(),
1451 &inputs,
1452 guards,
1453 parent_style,
1454 layout_parent_style,
1455 FirstLineReparenting::No,
1456 &name_and_try_tactic.try_tactic,
1457 None,
1458 &mut RuleCacheConditions::default(),
1459 ))
1460 },
1461 )
1462 }
1463
1464 pub fn cascade_style_and_visited<E>(
1477 &self,
1478 element: Option<E>,
1479 pseudo: Option<&PseudoElement>,
1480 inputs: &CascadeInputs,
1481 guards: &StylesheetGuards,
1482 parent_style: Option<&ComputedValues>,
1483 layout_parent_style: Option<&ComputedValues>,
1484 first_line_reparenting: FirstLineReparenting,
1485 try_tactic: &PositionTryFallbacksTryTactic,
1486 rule_cache: Option<&RuleCache>,
1487 rule_cache_conditions: &mut RuleCacheConditions,
1488 ) -> Arc<ComputedValues>
1489 where
1490 E: TElement,
1491 {
1492 debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1493
1494 let visited_rules = match inputs.visited_rules.as_ref() {
1497 Some(rules) => Some(rules),
1498 None => {
1499 if parent_style.and_then(|s| s.visited_style()).is_some() {
1500 Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1501 } else {
1502 None
1503 }
1504 },
1505 };
1506
1507 let mut implemented_pseudo = None;
1508 properties::cascade::<E>(
1515 &self,
1516 pseudo.or_else(|| {
1517 implemented_pseudo = element.unwrap().implemented_pseudo_element();
1518 implemented_pseudo.as_ref()
1519 }),
1520 inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1521 guards,
1522 parent_style,
1523 layout_parent_style,
1524 first_line_reparenting,
1525 try_tactic,
1526 visited_rules,
1527 inputs.flags,
1528 inputs.included_cascade_flags,
1529 rule_cache,
1530 rule_cache_conditions,
1531 element,
1532 )
1533 }
1534
1535 fn lazy_pseudo_rules<E>(
1540 &self,
1541 guards: &StylesheetGuards,
1542 element: E,
1543 originating_element_style: &ComputedValues,
1544 pseudo: &PseudoElement,
1545 is_probe: bool,
1546 rule_inclusion: RuleInclusion,
1547 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1548 ) -> Option<CascadeInputs>
1549 where
1550 E: TElement,
1551 {
1552 debug_assert!(pseudo.is_lazy());
1553
1554 let mut selector_caches = SelectorCaches::default();
1555 let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1558 NeedsSelectorFlags::No
1559 } else {
1560 NeedsSelectorFlags::Yes
1561 };
1562
1563 let mut declarations = ApplicableDeclarationList::new();
1564 let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1565 MatchingMode::ForStatelessPseudoElement,
1566 None,
1567 &mut selector_caches,
1568 self.quirks_mode,
1569 needs_selector_flags,
1570 MatchingForInvalidation::No,
1571 );
1572
1573 matching_context.pseudo_element_matching_fn = matching_fn;
1574 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1575
1576 self.push_applicable_declarations(
1577 element,
1578 Some(&pseudo),
1579 None,
1580 None,
1581 Default::default(),
1582 rule_inclusion,
1583 &mut declarations,
1584 &mut matching_context,
1585 );
1586
1587 if declarations.is_empty() && is_probe {
1588 return None;
1589 }
1590
1591 let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1592
1593 let mut visited_rules = None;
1594 if originating_element_style.visited_style().is_some() {
1595 let mut declarations = ApplicableDeclarationList::new();
1596 let mut selector_caches = SelectorCaches::default();
1597
1598 let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1599 MatchingMode::ForStatelessPseudoElement,
1600 None,
1601 &mut selector_caches,
1602 VisitedHandlingMode::RelevantLinkVisited,
1603 self.quirks_mode,
1604 needs_selector_flags,
1605 MatchingForInvalidation::No,
1606 );
1607 matching_context.pseudo_element_matching_fn = matching_fn;
1608 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1609
1610 self.push_applicable_declarations(
1611 element,
1612 Some(&pseudo),
1613 None,
1614 None,
1615 Default::default(),
1616 rule_inclusion,
1617 &mut declarations,
1618 &mut matching_context,
1619 );
1620 if !declarations.is_empty() {
1621 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1622 declarations.drain(..).map(|a| a.for_rule_tree()),
1623 guards,
1624 );
1625 if rule_node != *self.rule_tree.root() {
1626 visited_rules = Some(rule_node);
1627 }
1628 }
1629 }
1630
1631 Some(CascadeInputs {
1632 rules: Some(rules),
1633 visited_rules,
1634 flags: matching_context.extra_data.cascade_input_flags,
1635 included_cascade_flags: RuleCascadeFlags::empty(),
1636 })
1637 }
1638
1639 pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1650 self.device = device;
1651 self.media_features_change_changed_style(guards, &self.device)
1652 }
1653
1654 pub fn media_features_change_changed_style(
1658 &self,
1659 guards: &StylesheetGuards,
1660 device: &Device,
1661 ) -> OriginSet {
1662 debug!("Stylist::media_features_change_changed_style {:?}", device);
1663
1664 let mut origins = OriginSet::empty();
1665 let stylesheets = self.stylesheets.iter();
1666
1667 for (stylesheet, origin) in stylesheets {
1668 if origins.contains(origin.into()) {
1669 continue;
1670 }
1671
1672 let guard = guards.for_origin(origin);
1673 let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1674
1675 let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1676 stylesheet,
1677 guard,
1678 device,
1679 self.quirks_mode,
1680 );
1681
1682 if affected_changed {
1683 origins |= origin;
1684 }
1685 }
1686
1687 origins
1688 }
1689
1690 pub fn quirks_mode(&self) -> QuirksMode {
1692 self.quirks_mode
1693 }
1694
1695 pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1697 if self.quirks_mode == quirks_mode {
1698 return;
1699 }
1700 self.quirks_mode = quirks_mode;
1701 self.force_stylesheet_origins_dirty(OriginSet::all());
1702 }
1703
1704 pub fn push_applicable_declarations<E>(
1706 &self,
1707 element: E,
1708 pseudo_element: Option<&PseudoElement>,
1709 style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1710 smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1711 animation_declarations: AnimationDeclarations,
1712 rule_inclusion: RuleInclusion,
1713 applicable_declarations: &mut ApplicableDeclarationList,
1714 context: &mut MatchingContext<E::Impl>,
1715 ) where
1716 E: TElement,
1717 {
1718 let mut cur = element;
1719 let mut pseudos = SmallVec::<[_; 2]>::new();
1720 if let Some(pseudo) = pseudo_element {
1721 pseudos.push(pseudo.clone());
1722 }
1723 while let Some(p) = cur.implemented_pseudo_element() {
1724 pseudos.push(p);
1725 let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
1726 break;
1727 };
1728 cur = parent_pseudo;
1729 }
1730 RuleCollector::new(
1731 self,
1732 element,
1733 cur,
1734 &pseudos,
1735 style_attribute,
1736 smil_override,
1737 animation_declarations,
1738 rule_inclusion,
1739 applicable_declarations,
1740 context,
1741 )
1742 .collect_all();
1743 }
1744
1745 #[inline]
1748 pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1749 where
1750 E: TElement,
1751 {
1752 match self.quirks_mode().classes_and_ids_case_sensitivity() {
1755 CaseSensitivity::AsciiCaseInsensitive => return true,
1756 CaseSensitivity::CaseSensitive => {},
1757 }
1758
1759 self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1760 }
1761
1762 #[inline]
1770 fn lookup_element_dependent_at_rule<'a, T, F, E>(
1771 &'a self,
1772 element: E,
1773 find_in: F,
1774 ) -> Option<&'a T>
1775 where
1776 E: TElement + 'a,
1777 F: Fn(&'a CascadeData) -> Option<&'a T>,
1778 {
1779 macro_rules! try_find_in {
1780 ($data:expr) => {
1781 if let Some(thing) = find_in(&$data) {
1782 return Some(thing);
1783 }
1784 };
1785 }
1786
1787 let mut result = None;
1788 let doc_rules_apply =
1789 element.each_applicable_non_document_style_rule_data(|data, _host| {
1790 if result.is_none() {
1791 result = find_in(data);
1792 }
1793 });
1794
1795 if result.is_some() {
1796 return result;
1797 }
1798
1799 if doc_rules_apply {
1800 try_find_in!(self.cascade_data.author);
1801 }
1802 try_find_in!(self.cascade_data.user);
1803 try_find_in!(self.cascade_data.user_agent.cascade_data);
1804
1805 None
1806 }
1807
1808 #[inline]
1810 pub fn lookup_keyframes<'a, E>(
1811 &'a self,
1812 name: &Atom,
1813 element: E,
1814 ) -> Option<&'a KeyframesAnimation>
1815 where
1816 E: TElement + 'a,
1817 {
1818 self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1819 }
1820
1821 #[inline]
1824 pub fn last_view_transition_rule(&self) -> Option<&Arc<ViewTransitionRule>> {
1825 self.iter_extra_data_origins()
1827 .flat_map(|(d, _)| d.view_transitions.iter())
1828 .last()
1829 .map(|(rule, _)| rule)
1830 }
1831
1832 #[inline]
1834 #[cfg(feature = "gecko")]
1835 fn lookup_position_try<'a, E>(
1836 &'a self,
1837 name: &Atom,
1838 scope: CascadeLevel,
1839 element: E,
1840 ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1841 where
1842 E: TElement + 'a,
1843 {
1844 let mut shadow_root = scope.get_shadow_root_for_scoped(element);
1845 while let Some(r) = shadow_root {
1848 if let Some(rule) = r
1849 .style_data()
1850 .map(|data| data.extra_data.position_try_rules.get(name))
1851 .flatten()
1852 {
1853 return Some(rule);
1854 }
1855 shadow_root = r.host().containing_shadow();
1857 }
1858
1859 for (data, _) in self.iter_extra_data_origins() {
1860 if let Some(r) = data.position_try_rules.get(name) {
1861 return Some(r);
1862 }
1863 }
1864 None
1865 }
1866
1867 pub fn match_revalidation_selectors<E>(
1870 &self,
1871 element: E,
1872 bloom: Option<&BloomFilter>,
1873 selector_caches: &mut SelectorCaches,
1874 needs_selector_flags: NeedsSelectorFlags,
1875 ) -> RevalidationResult
1876 where
1877 E: TElement,
1878 {
1879 let mut matching_context = MatchingContext::new_for_revalidation(
1880 bloom,
1881 selector_caches,
1882 self.quirks_mode,
1883 needs_selector_flags,
1884 );
1885
1886 let mut result = RevalidationResult::default();
1892 let mut relevant_attributes = &mut result.relevant_attributes;
1893 let selectors_matched = &mut result.selectors_matched;
1894
1895 let matches_document_rules =
1896 element.each_applicable_non_document_style_rule_data(|data, host| {
1897 matching_context.with_shadow_host(Some(host), |matching_context| {
1898 data.selectors_for_cache_revalidation.lookup(
1899 element,
1900 self.quirks_mode,
1901 Some(&mut relevant_attributes),
1902 |selector_and_hashes| {
1903 selectors_matched.push(matches_selector(
1904 &selector_and_hashes.selector,
1905 selector_and_hashes.selector_offset,
1906 Some(&selector_and_hashes.hashes),
1907 &element,
1908 matching_context,
1909 ));
1910 true
1911 },
1912 );
1913 })
1914 });
1915
1916 for (data, origin) in self.cascade_data.iter_origins() {
1917 if origin == Origin::Author && !matches_document_rules {
1918 continue;
1919 }
1920
1921 data.selectors_for_cache_revalidation.lookup(
1922 element,
1923 self.quirks_mode,
1924 Some(&mut relevant_attributes),
1925 |selector_and_hashes| {
1926 selectors_matched.push(matches_selector(
1927 &selector_and_hashes.selector,
1928 selector_and_hashes.selector_offset,
1929 Some(&selector_and_hashes.hashes),
1930 &element,
1931 &mut matching_context,
1932 ));
1933 true
1934 },
1935 );
1936 }
1937
1938 result
1939 }
1940
1941 pub fn revalidate_scopes<E: TElement>(
1943 &self,
1944 element: &E,
1945 selector_caches: &mut SelectorCaches,
1946 needs_selector_flags: NeedsSelectorFlags,
1947 ) -> ScopeRevalidationResult {
1948 let mut matching_context = MatchingContext::new(
1949 MatchingMode::Normal,
1950 None,
1951 selector_caches,
1952 self.quirks_mode,
1953 needs_selector_flags,
1954 MatchingForInvalidation::No,
1955 );
1956
1957 let mut result = ScopeRevalidationResult::default();
1958 let matches_document_rules =
1959 element.each_applicable_non_document_style_rule_data(|data, host| {
1960 matching_context.with_shadow_host(Some(host), |matching_context| {
1961 data.revalidate_scopes(element, matching_context, &mut result);
1962 })
1963 });
1964
1965 for (data, origin) in self.cascade_data.iter_origins() {
1966 if origin == Origin::Author && !matches_document_rules {
1967 continue;
1968 }
1969
1970 data.revalidate_scopes(element, &mut matching_context, &mut result);
1971 }
1972
1973 result
1974 }
1975
1976 pub fn compute_for_declarations<E>(
1984 &self,
1985 guards: &StylesheetGuards,
1986 parent_style: &ComputedValues,
1987 declarations: Arc<Locked<PropertyDeclarationBlock>>,
1988 ) -> Arc<ComputedValues>
1989 where
1990 E: TElement,
1991 {
1992 let block = declarations.read_with(guards.author);
1993
1994 properties::apply_declarations::<E, _>(
2001 &self,
2002 None,
2003 self.rule_tree.root(),
2004 guards,
2005 block.declaration_importance_iter().map(|(declaration, _)| {
2006 (
2007 declaration,
2008 CascadePriority::new(
2009 CascadeLevel::same_tree_author_normal(),
2010 LayerOrder::root(),
2011 RuleCascadeFlags::empty(),
2012 ),
2013 )
2014 }),
2015 Some(parent_style),
2016 Some(parent_style),
2017 FirstLineReparenting::No,
2018 &PositionTryFallbacksTryTactic::default(),
2019 CascadeMode::Unvisited {
2020 visited_rules: None,
2021 },
2022 Default::default(),
2023 RuleCascadeFlags::empty(),
2024 None,
2025 &mut Default::default(),
2026 None,
2027 )
2028 }
2029
2030 #[inline]
2032 pub fn device(&self) -> &Device {
2033 &self.device
2034 }
2035
2036 #[inline]
2038 pub fn device_mut(&mut self) -> &mut Device {
2039 &mut self.device
2040 }
2041
2042 #[inline]
2044 pub fn rule_tree(&self) -> &RuleTree {
2045 &self.rule_tree
2046 }
2047
2048 #[inline]
2050 pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
2051 &self.script_custom_properties
2052 }
2053
2054 #[inline]
2056 pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2057 &mut self.script_custom_properties
2058 }
2059
2060 #[cfg(feature = "gecko")]
2062 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2063 self.cascade_data.add_size_of(ops, sizes);
2064 self.author_data_cache.add_size_of(ops, sizes);
2065 sizes.mRuleTree += self.rule_tree.size_of(ops);
2066
2067 }
2069
2070 pub fn shutdown() {
2072 let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2073 }
2074}
2075
2076#[allow(missing_docs)]
2077#[repr(u8)]
2078pub enum RegisterCustomPropertyResult {
2079 SuccessfullyRegistered,
2080 InvalidName,
2081 AlreadyRegistered,
2082 InvalidSyntax,
2083 NoInitialValue,
2084 InvalidInitialValue,
2085 InitialValueNotComputationallyIndependent,
2086}
2087
2088impl Stylist {
2089 pub fn register_custom_property(
2091 &mut self,
2092 url_data: &UrlExtraData,
2093 name: &str,
2094 syntax: &str,
2095 inherits: bool,
2096 initial_value: Option<&str>,
2097 ) -> RegisterCustomPropertyResult {
2098 use RegisterCustomPropertyResult::*;
2099
2100 let Ok(name) = parse_name(name).map(Atom::from) else {
2102 return InvalidName;
2103 };
2104
2105 if self.custom_property_script_registry().get(&name).is_some() {
2108 return AlreadyRegistered;
2109 }
2110 let Ok(syntax) = Descriptor::from_str(syntax, false) else {
2113 return InvalidSyntax;
2114 };
2115
2116 let initial_value = match initial_value {
2117 Some(value) => {
2118 let mut input = ParserInput::new(value);
2119 let parsed = Parser::new(&mut input)
2120 .parse_entirely(|input| {
2121 input.skip_whitespace();
2122 SpecifiedValue::parse(input, None, url_data).map(Arc::new)
2123 })
2124 .ok();
2125 if parsed.is_none() {
2126 return InvalidInitialValue;
2127 }
2128 parsed
2129 },
2130 None => None,
2131 };
2132
2133 if let Err(error) =
2134 PropertyRegistration::validate_initial_value(&syntax, initial_value.as_deref())
2135 {
2136 return match error {
2137 PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
2138 InitialValueNotComputationallyIndependent
2139 },
2140 PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
2141 PropertyRegistrationError::NoInitialValue => NoInitialValue,
2142 };
2143 }
2144
2145 let property_registration = PropertyRegistration {
2146 name: PropertyRuleName(name),
2147 descriptors: PropertyDescriptors {
2148 syntax: Some(syntax),
2149 inherits: Some(if inherits {
2150 Inherits::True
2151 } else {
2152 Inherits::False
2153 }),
2154 initial_value,
2155 },
2156 url_data: url_data.clone(),
2157 source_location: SourceLocation { line: 0, column: 0 },
2158 };
2159 self.custom_property_script_registry_mut()
2160 .register(property_registration);
2161 self.rebuild_initial_values_for_custom_properties();
2162
2163 SuccessfullyRegistered
2164 }
2165}
2166
2167#[derive(Clone, Debug, Deref, MallocSizeOf)]
2169pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2170impl<T> Default for LayerOrderedVec<T> {
2171 fn default() -> Self {
2172 Self(Default::default())
2173 }
2174}
2175
2176#[derive(Clone, Debug, Deref, MallocSizeOf)]
2178pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2179impl<T> Default for LayerOrderedMap<T> {
2180 fn default() -> Self {
2181 Self(Default::default())
2182 }
2183}
2184
2185impl<T: 'static> LayerOrderedVec<T> {
2186 fn clear(&mut self) {
2187 self.0.clear();
2188 }
2189 fn push(&mut self, v: T, id: LayerId) {
2190 self.0.push((v, id));
2191 }
2192 fn sort(&mut self, layers: &[CascadeLayer]) {
2193 self.0
2194 .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
2195 }
2196}
2197
2198impl<T: 'static> LayerOrderedMap<T> {
2199 fn shrink_if_needed(&mut self) {
2200 self.0.shrink_if_needed();
2201 }
2202 fn clear(&mut self) {
2203 self.0.clear();
2204 }
2205 fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2206 self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2207 }
2208 fn try_insert_with(
2209 &mut self,
2210 name: Atom,
2211 v: T,
2212 id: LayerId,
2213 cmp: impl Fn(&T, &T) -> Ordering,
2214 ) -> Result<(), AllocErr> {
2215 self.0.try_reserve(1)?;
2216 let vec = self.0.entry(name).or_default();
2217 if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
2218 if *last_id == id {
2219 if cmp(&val, &v) != Ordering::Greater {
2220 *val = v;
2221 }
2222 return Ok(());
2223 }
2224 }
2225 vec.push((v, id));
2226 Ok(())
2227 }
2228 fn sort(&mut self, layers: &[CascadeLayer]) {
2229 self.sort_with(layers, |_, _| Ordering::Equal)
2230 }
2231 fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2232 for (_, v) in self.0.iter_mut() {
2233 v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
2234 let order1 = layers[id1.0 as usize].order;
2235 let order2 = layers[id2.0 as usize].order;
2236 order1.cmp(&order2).then_with(|| cmp(v1, v2))
2237 })
2238 }
2239 }
2240 pub fn get(&self, name: &Atom) -> Option<&T> {
2242 let vec = self.0.get(name)?;
2243 Some(&vec.last()?.0)
2244 }
2245}
2246
2247#[derive(Clone, Debug, MallocSizeOf)]
2251pub struct PageRuleData {
2252 pub layer: LayerId,
2254 #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2256 pub rule: Arc<Locked<PageRule>>,
2257}
2258
2259#[derive(Clone, Debug, Default, MallocSizeOf)]
2261pub struct PageRuleMap {
2262 pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2264}
2265
2266impl PageRuleMap {
2267 #[inline]
2268 fn clear(&mut self) {
2269 self.rules.clear();
2270 }
2271
2272 pub fn match_and_append_rules(
2276 &self,
2277 matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2278 origin: Origin,
2279 guards: &StylesheetGuards,
2280 cascade_data: &DocumentCascadeData,
2281 name: &Option<Atom>,
2282 pseudos: PagePseudoClassFlags,
2283 ) {
2284 let level = match origin {
2285 Origin::UserAgent => CascadeLevel::new(CascadeOrigin::UA),
2286 Origin::User => CascadeLevel::new(CascadeOrigin::User),
2287 Origin::Author => CascadeLevel::same_tree_author_normal(),
2288 };
2289 let cascade_data = cascade_data.borrow_for_origin(origin);
2290 let start = matched_rules.len();
2291
2292 self.match_and_add_rules(
2293 matched_rules,
2294 level,
2295 guards,
2296 cascade_data,
2297 &atom!(""),
2298 pseudos,
2299 );
2300 if let Some(name) = name {
2301 self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2302 }
2303
2304 matched_rules[start..].sort_by_key(|block| block.sort_key());
2307 }
2308
2309 fn match_and_add_rules(
2310 &self,
2311 extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2312 level: CascadeLevel,
2313 guards: &StylesheetGuards,
2314 cascade_data: &CascadeData,
2315 name: &Atom,
2316 pseudos: PagePseudoClassFlags,
2317 ) {
2318 let rules = match self.rules.get(name) {
2319 Some(rules) => rules,
2320 None => return,
2321 };
2322 for data in rules.iter() {
2323 let rule = data.rule.read_with(level.guard(&guards));
2324 let specificity = match rule.match_specificity(pseudos) {
2325 Some(specificity) => specificity,
2326 None => continue,
2327 };
2328 let block = rule.block.clone();
2329 extra_declarations.push(ApplicableDeclarationBlock::new(
2330 StyleSource::from_declarations(block),
2331 0,
2332 level,
2333 specificity,
2334 cascade_data.layer_order_for(data.layer),
2335 ScopeProximity::infinity(), RuleCascadeFlags::empty(),
2337 ));
2338 }
2339 }
2340}
2341
2342impl MallocShallowSizeOf for PageRuleMap {
2343 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2344 self.rules.shallow_size_of(ops)
2345 }
2346}
2347
2348type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2349
2350#[derive(Clone, Debug, Default)]
2353pub struct ExtraStyleData {
2354 pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2356
2357 pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2359
2360 pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2362
2363 pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2365
2366 pub position_try_rules: PositionTryMap,
2368
2369 pub pages: PageRuleMap,
2371
2372 pub view_transitions: LayerOrderedVec<Arc<ViewTransitionRule>>,
2374}
2375
2376impl ExtraStyleData {
2377 fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2379 self.font_faces.push(rule.clone(), layer);
2380 }
2381
2382 fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2384 self.font_feature_values.push(rule.clone(), layer);
2385 }
2386
2387 fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2389 self.font_palette_values.push(rule.clone(), layer);
2390 }
2391
2392 fn add_counter_style(
2394 &mut self,
2395 guard: &SharedRwLockReadGuard,
2396 rule: &Arc<Locked<CounterStyleRule>>,
2397 layer: LayerId,
2398 ) -> Result<(), AllocErr> {
2399 let name = rule.read_with(guard).name().0.clone();
2400 self.counter_styles.try_insert(name, rule.clone(), layer)
2401 }
2402
2403 fn add_position_try(
2405 &mut self,
2406 name: Atom,
2407 rule: Arc<Locked<PositionTryRule>>,
2408 layer: LayerId,
2409 ) -> Result<(), AllocErr> {
2410 self.position_try_rules.try_insert(name, rule, layer)
2411 }
2412
2413 fn add_page(
2415 &mut self,
2416 guard: &SharedRwLockReadGuard,
2417 rule: &Arc<Locked<PageRule>>,
2418 layer: LayerId,
2419 ) -> Result<(), AllocErr> {
2420 let page_rule = rule.read_with(guard);
2421 let mut add_rule = |name| {
2422 let vec = self.pages.rules.entry(name).or_default();
2423 vec.push(PageRuleData {
2424 layer,
2425 rule: rule.clone(),
2426 });
2427 };
2428 if page_rule.selectors.0.is_empty() {
2429 add_rule(atom!(""));
2430 } else {
2431 for selector in page_rule.selectors.as_slice() {
2432 add_rule(selector.name.0.clone());
2433 }
2434 }
2435 Ok(())
2436 }
2437
2438 fn add_view_transition(&mut self, rule: &Arc<ViewTransitionRule>, layer: LayerId) {
2439 self.view_transitions.push(rule.clone(), layer)
2440 }
2441
2442 fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2443 self.font_faces.sort(layers);
2444 self.font_feature_values.sort(layers);
2445 self.font_palette_values.sort(layers);
2446 self.counter_styles.sort(layers);
2447 self.position_try_rules.sort(layers);
2448 self.view_transitions.sort(layers);
2449 }
2450
2451 fn clear(&mut self) {
2452 self.font_faces.clear();
2453 self.font_feature_values.clear();
2454 self.font_palette_values.clear();
2455 self.counter_styles.clear();
2456 self.position_try_rules.clear();
2457 self.pages.clear();
2458 }
2459}
2460
2461fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2464 if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2465 Ordering::Equal
2466 } else if v2.vendor_prefix.is_some() {
2467 Ordering::Greater
2468 } else {
2469 Ordering::Less
2470 }
2471}
2472
2473pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2475
2476impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2477 type Item = (&'a ExtraStyleData, Origin);
2478
2479 fn next(&mut self) -> Option<Self::Item> {
2480 self.0.next().map(|d| (&d.0.extra_data, d.1))
2481 }
2482}
2483
2484impl MallocSizeOf for ExtraStyleData {
2485 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2487 let mut n = 0;
2488 n += self.font_faces.shallow_size_of(ops);
2489 n += self.font_feature_values.shallow_size_of(ops);
2490 n += self.font_palette_values.shallow_size_of(ops);
2491 n += self.counter_styles.shallow_size_of(ops);
2492 n += self.position_try_rules.shallow_size_of(ops);
2493 n += self.pages.shallow_size_of(ops);
2494 n
2495 }
2496}
2497
2498#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2500#[derive(Clone, Debug)]
2501struct RevalidationSelectorAndHashes {
2502 #[cfg_attr(
2503 feature = "gecko",
2504 ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2505 )]
2506 selector: Selector<SelectorImpl>,
2507 selector_offset: usize,
2508 hashes: AncestorHashes,
2509}
2510
2511impl RevalidationSelectorAndHashes {
2512 fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2513 let selector_offset = {
2514 let mut index = 0;
2518 let mut iter = selector.iter();
2519
2520 for _ in &mut iter {
2525 index += 1; }
2527
2528 match iter.next_sequence() {
2529 Some(Combinator::PseudoElement) => index + 1, _ => 0,
2531 }
2532 };
2533
2534 RevalidationSelectorAndHashes {
2535 selector,
2536 selector_offset,
2537 hashes,
2538 }
2539 }
2540}
2541
2542impl SelectorMapEntry for RevalidationSelectorAndHashes {
2543 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2544 self.selector.iter_from(self.selector_offset)
2545 }
2546}
2547
2548struct StylistSelectorVisitor<'a> {
2551 passed_rightmost_selector: bool,
2554
2555 needs_revalidation: &'a mut bool,
2557
2558 in_selector_list_of: SelectorListKind,
2561
2562 mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2565
2566 nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2569
2570 attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2572
2573 nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2576
2577 nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2581
2582 nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2586
2587 state_dependencies: &'a mut ElementState,
2589
2590 nth_of_state_dependencies: &'a mut ElementState,
2593
2594 document_state_dependencies: &'a mut DocumentState,
2596}
2597
2598fn component_needs_revalidation(
2599 c: &Component<SelectorImpl>,
2600 passed_rightmost_selector: bool,
2601) -> bool {
2602 match *c {
2603 Component::ID(_) => {
2604 passed_rightmost_selector
2610 },
2611 Component::AttributeInNoNamespaceExists { .. }
2612 | Component::AttributeInNoNamespace { .. }
2613 | Component::AttributeOther(_)
2614 | Component::Empty
2615 | Component::Nth(_)
2616 | Component::NthOf(_)
2617 | Component::Has(_) => true,
2618 Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2619 _ => false,
2620 }
2621}
2622
2623impl<'a> StylistSelectorVisitor<'a> {
2624 fn visit_nested_selector(
2625 &mut self,
2626 in_selector_list_of: SelectorListKind,
2627 selector: &Selector<SelectorImpl>,
2628 ) {
2629 let old_passed_rightmost_selector = self.passed_rightmost_selector;
2630 let old_in_selector_list_of = self.in_selector_list_of;
2631
2632 self.passed_rightmost_selector = false;
2633 self.in_selector_list_of = in_selector_list_of;
2634 let _ret = selector.visit(self);
2635 debug_assert!(_ret, "We never return false");
2636
2637 self.passed_rightmost_selector = old_passed_rightmost_selector;
2638 self.in_selector_list_of = old_in_selector_list_of;
2639 }
2640}
2641
2642impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2643 type Impl = SelectorImpl;
2644
2645 fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2646 *self.needs_revalidation =
2647 *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2648
2649 self.passed_rightmost_selector = self.passed_rightmost_selector
2653 || !matches!(combinator, None | Some(Combinator::PseudoElement));
2654
2655 true
2656 }
2657
2658 fn visit_selector_list(
2659 &mut self,
2660 list_kind: SelectorListKind,
2661 list: &[Selector<Self::Impl>],
2662 ) -> bool {
2663 let in_selector_list_of = self.in_selector_list_of | list_kind;
2664 for selector in list {
2665 self.visit_nested_selector(in_selector_list_of, selector);
2666 }
2667 true
2668 }
2669
2670 fn visit_relative_selector_list(
2671 &mut self,
2672 list: &[selectors::parser::RelativeSelector<Self::Impl>],
2673 ) -> bool {
2674 let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2675 for selector in list {
2676 self.visit_nested_selector(in_selector_list_of, &selector.selector);
2677 }
2678 true
2679 }
2680
2681 fn visit_attribute_selector(
2682 &mut self,
2683 _ns: &NamespaceConstraint<&Namespace>,
2684 name: &LocalName,
2685 lower_name: &LocalName,
2686 ) -> bool {
2687 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2688 self.nth_of_attribute_dependencies.insert(name.clone());
2689 if name != lower_name {
2690 self.nth_of_attribute_dependencies
2691 .insert(lower_name.clone());
2692 }
2693 }
2694
2695 self.attribute_dependencies.insert(name.clone());
2696 if name != lower_name {
2697 self.attribute_dependencies.insert(lower_name.clone());
2698 }
2699
2700 true
2701 }
2702
2703 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2704 *self.needs_revalidation = *self.needs_revalidation
2705 || component_needs_revalidation(s, self.passed_rightmost_selector);
2706
2707 match *s {
2708 Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2709 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2715 self.nth_of_custom_state_dependencies.insert(name.0.clone());
2716 }
2717 },
2718 Component::NonTSPseudoClass(ref p) => {
2719 self.state_dependencies.insert(p.state_flag());
2720 self.document_state_dependencies
2721 .insert(p.document_state_flag());
2722
2723 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2724 self.nth_of_state_dependencies.insert(p.state_flag());
2725 }
2726 },
2727 Component::ID(ref id) => {
2728 if !self.passed_rightmost_selector {
2740 self.mapped_ids.insert(id.0.clone());
2741 }
2742
2743 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2744 self.nth_of_mapped_ids.insert(id.0.clone());
2745 }
2746 },
2747 Component::Class(ref class)
2748 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2749 {
2750 self.nth_of_class_dependencies.insert(class.0.clone());
2751 },
2752 _ => {},
2753 }
2754
2755 true
2756 }
2757}
2758
2759#[derive(Clone, Debug, Default, MallocSizeOf)]
2761struct GenericElementAndPseudoRules<Map> {
2762 element_map: Map,
2764
2765 pseudos_map: PerPseudoElementMap<Self>,
2772}
2773
2774impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2775 #[inline(always)]
2776 fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2777 let mut current = self;
2778 for &pseudo_element in pseudo_elements {
2779 debug_assert!(
2780 !pseudo_element.is_precomputed()
2781 && !pseudo_element.is_unknown_webkit_pseudo_element(),
2782 "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2783 and unknown webkit pseudos should be discarded before getting here"
2784 );
2785
2786 current = current
2787 .pseudos_map
2788 .get_or_insert_with(pseudo_element, Default::default);
2789 }
2790
2791 &mut current.element_map
2792 }
2793
2794 #[inline]
2795 fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2796 let mut current = self;
2797 for pseudo in pseudo_elements {
2798 current = current.pseudos_map.get(&pseudo)?;
2799 }
2800 Some(¤t.element_map)
2801 }
2802
2803 #[cfg(feature = "gecko")]
2805 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2806 sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2807
2808 for elem in self.pseudos_map.iter() {
2809 sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2810 }
2811 }
2812}
2813
2814type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2815type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2816type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2817
2818impl ElementAndPseudoRules {
2819 fn clear(&mut self) {
2821 self.element_map.clear();
2822 self.pseudos_map.clear();
2823 }
2824
2825 fn shrink_if_needed(&mut self) {
2826 self.element_map.shrink_if_needed();
2827 for pseudo in self.pseudos_map.iter_mut() {
2828 pseudo.shrink_if_needed();
2829 }
2830 }
2831}
2832
2833impl PartElementAndPseudoRules {
2834 fn clear(&mut self) {
2836 self.element_map.clear();
2837 self.pseudos_map.clear();
2838 }
2839}
2840
2841#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2843pub struct LayerId(u16);
2844
2845impl LayerId {
2846 pub const fn root() -> Self {
2848 Self(0)
2849 }
2850}
2851
2852#[derive(Clone, Debug, MallocSizeOf)]
2853struct CascadeLayer {
2854 id: LayerId,
2855 order: LayerOrder,
2856 children: Vec<LayerId>,
2857}
2858
2859impl CascadeLayer {
2860 const fn root() -> Self {
2861 Self {
2862 id: LayerId::root(),
2863 order: LayerOrder::root(),
2864 children: vec![],
2865 }
2866 }
2867}
2868
2869#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2872pub struct ContainerConditionId(u16);
2873
2874impl ContainerConditionId {
2875 pub const fn none() -> Self {
2877 Self(0)
2878 }
2879}
2880
2881#[derive(Clone, Debug, MallocSizeOf)]
2882struct ContainerConditionReference {
2883 parent: ContainerConditionId,
2884 #[ignore_malloc_size_of = "Arc"]
2889 conditions: ArcSlice<ContainerCondition>,
2890}
2891
2892impl ContainerConditionReference {
2893 fn none() -> Self {
2895 Self {
2896 parent: ContainerConditionId::none(),
2897 conditions: ArcSlice::default(),
2898 }
2899 }
2900}
2901
2902#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2905pub struct ScopeConditionId(u16);
2906
2907impl ScopeConditionId {
2908 pub fn new(id: u16) -> Self {
2910 Self(id)
2911 }
2912
2913 pub const fn none() -> Self {
2915 Self(0)
2916 }
2917}
2918
2919#[derive(Clone, Debug, MallocSizeOf)]
2921pub struct ScopeConditionReference {
2922 parent: ScopeConditionId,
2924 condition: Option<ScopeBoundsWithHashes>,
2926 #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2929 implicit_scope_root: StylistImplicitScopeRoot,
2930 is_trivial: bool,
2932}
2933
2934impl ScopeConditionReference {
2935 pub fn new(
2937 parent: ScopeConditionId,
2938 condition: Option<ScopeBoundsWithHashes>,
2939 implicit_scope_root: ImplicitScopeRoot,
2940 is_trivial: bool,
2941 ) -> Self {
2942 Self {
2943 parent,
2944 condition,
2945 implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2946 is_trivial,
2947 }
2948 }
2949
2950 pub const fn none() -> Self {
2952 Self {
2953 parent: ScopeConditionId::none(),
2954 condition: None,
2955 implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2956 is_trivial: true,
2957 }
2958 }
2959}
2960
2961pub struct ScopeRootCandidates {
2963 pub candidates: Vec<ScopeRootCandidate>,
2965 pub is_trivial: bool,
2967}
2968
2969impl Default for ScopeRootCandidates {
2970 fn default() -> Self {
2971 Self {
2972 candidates: vec![],
2973 is_trivial: true,
2974 }
2975 }
2976}
2977
2978impl ScopeRootCandidates {
2979 fn empty(is_trivial: bool) -> Self {
2980 Self {
2981 candidates: vec![],
2982 is_trivial,
2983 }
2984 }
2985}
2986
2987#[derive(Clone, Debug, MallocSizeOf)]
2989pub struct ScopeBoundWithHashes {
2990 #[ignore_malloc_size_of = "Arc"]
2992 selectors: SelectorList<SelectorImpl>,
2993 hashes: SmallVec<[AncestorHashes; 1]>,
2994}
2995
2996impl ScopeBoundWithHashes {
2997 fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2998 let mut hashes = SmallVec::with_capacity(selectors.len());
2999 for selector in selectors.slice() {
3000 hashes.push(AncestorHashes::new(selector, quirks_mode));
3001 }
3002 Self { selectors, hashes }
3003 }
3004
3005 fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
3006 let hashes = selectors
3007 .slice()
3008 .iter()
3009 .map(|_| AncestorHashes {
3010 packed_hashes: [0, 0, 0],
3011 })
3012 .collect();
3013 Self { selectors, hashes }
3014 }
3015}
3016
3017#[derive(Clone, Debug, MallocSizeOf)]
3019pub struct ScopeBoundsWithHashes {
3020 start: Option<ScopeBoundWithHashes>,
3022 end: Option<ScopeBoundWithHashes>,
3024}
3025
3026impl ScopeBoundsWithHashes {
3027 fn new(
3029 quirks_mode: QuirksMode,
3030 start: Option<SelectorList<SelectorImpl>>,
3031 end: Option<SelectorList<SelectorImpl>>,
3032 ) -> Self {
3033 Self {
3034 start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3035 end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3036 }
3037 }
3038
3039 pub fn new_no_hash(
3041 start: Option<SelectorList<SelectorImpl>>,
3042 end: Option<SelectorList<SelectorImpl>>,
3043 ) -> Self {
3044 Self {
3045 start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3046 end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3047 }
3048 }
3049
3050 fn selectors_for<'a>(
3051 bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
3052 ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3053 bound_with_hashes
3054 .map(|b| b.selectors.slice().iter())
3055 .into_iter()
3056 .flatten()
3057 }
3058
3059 fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3060 Self::selectors_for(self.start.as_ref())
3061 }
3062
3063 fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3064 Self::selectors_for(self.end.as_ref())
3065 }
3066
3067 fn is_trivial(&self) -> bool {
3068 fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
3069 bound.as_ref().map_or(default, |bound| {
3070 scope_selector_list_is_trivial(&bound.selectors)
3071 })
3072 }
3073
3074 scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
3076 }
3077}
3078
3079pub fn scope_root_candidates<E>(
3081 scope_conditions: &[ScopeConditionReference],
3082 id: ScopeConditionId,
3083 element: &E,
3084 override_matches_shadow_host_for_part: bool,
3085 scope_subject_map: &ScopeSubjectMap,
3086 context: &mut MatchingContext<SelectorImpl>,
3087) -> ScopeRootCandidates
3088where
3089 E: TElement,
3090{
3091 let condition_ref = &scope_conditions[id.0 as usize];
3092 let bounds = match condition_ref.condition {
3093 None => return ScopeRootCandidates::default(),
3094 Some(ref c) => c,
3095 };
3096 let outer_result = scope_root_candidates(
3100 scope_conditions,
3101 condition_ref.parent,
3102 element,
3103 override_matches_shadow_host_for_part,
3104 scope_subject_map,
3105 context,
3106 );
3107
3108 let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
3109 let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
3110 if !is_outermost_scope && outer_result.candidates.is_empty() {
3111 return ScopeRootCandidates::empty(is_trivial);
3112 }
3113
3114 let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
3115 if let Some(filter) = context.bloom_filter {
3116 if !start
3121 .hashes
3122 .iter()
3123 .any(|entry| selector_may_match(entry, filter))
3124 {
3125 return ScopeRootCandidates::empty(is_trivial);
3126 }
3127 }
3128 (
3129 ScopeTarget::Selector(&start.selectors),
3130 scope_start_matches_shadow_host(&start.selectors),
3131 )
3132 } else {
3133 let implicit_root = condition_ref.implicit_scope_root;
3134 match implicit_root {
3135 StylistImplicitScopeRoot::Normal(r) => (
3136 ScopeTarget::Implicit(r.element(context.current_host.clone())),
3137 r.matches_shadow_host(),
3138 ),
3139 StylistImplicitScopeRoot::Cached(index) => {
3140 let host = context
3141 .current_host
3142 .expect("Cached implicit scope for light DOM implicit scope");
3143 match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
3144 None => return ScopeRootCandidates::empty(is_trivial),
3145 Some(root) => (
3146 ScopeTarget::Implicit(root.element(context.current_host.clone())),
3147 root.matches_shadow_host(),
3148 ),
3149 }
3150 },
3151 }
3152 };
3153 let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
3156
3157 let potential_scope_roots = if is_outermost_scope {
3158 collect_scope_roots(
3159 *element,
3160 None,
3161 context,
3162 &root_target,
3163 matches_shadow_host,
3164 scope_subject_map,
3165 )
3166 } else {
3167 let mut result = vec![];
3168 for activation in outer_result.candidates {
3169 let mut this_result = collect_scope_roots(
3170 *element,
3171 Some(activation.root),
3172 context,
3173 &root_target,
3174 matches_shadow_host,
3175 scope_subject_map,
3176 );
3177 result.append(&mut this_result);
3178 }
3179 result
3180 };
3181
3182 if potential_scope_roots.is_empty() {
3183 return ScopeRootCandidates::empty(is_trivial);
3184 }
3185
3186 let candidates = if let Some(end) = bounds.end.as_ref() {
3187 let mut result = vec![];
3188 for scope_root in potential_scope_roots {
3190 if end
3191 .selectors
3192 .slice()
3193 .iter()
3194 .zip(end.hashes.iter())
3195 .all(|(selector, hashes)| {
3196 if let Some(filter) = context.bloom_filter {
3198 if !selector_may_match(hashes, filter) {
3199 return true;
3201 }
3202 }
3203
3204 !element_is_outside_of_scope(
3205 selector,
3206 *element,
3207 scope_root.root,
3208 context,
3209 matches_shadow_host,
3210 )
3211 })
3212 {
3213 result.push(scope_root);
3214 }
3215 }
3216 result
3217 } else {
3218 potential_scope_roots
3219 };
3220
3221 ScopeRootCandidates {
3222 candidates,
3223 is_trivial,
3224 }
3225}
3226
3227#[derive(Copy, Clone, Debug, MallocSizeOf)]
3230enum StylistImplicitScopeRoot {
3231 Normal(ImplicitScopeRoot),
3232 Cached(usize),
3233}
3234unsafe impl Sync for StylistImplicitScopeRoot {}
3236
3237impl StylistImplicitScopeRoot {
3238 const fn default_const() -> Self {
3239 Self::Normal(ImplicitScopeRoot::DocumentElement)
3241 }
3242}
3243
3244impl Default for StylistImplicitScopeRoot {
3245 fn default() -> Self {
3246 Self::default_const()
3247 }
3248}
3249
3250#[derive(Debug, Clone, MallocSizeOf)]
3256pub struct CascadeData {
3257 normal_rules: ElementAndPseudoRules,
3260
3261 featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3265
3266 slotted_rules: Option<Box<ElementAndPseudoRules>>,
3274
3275 part_rules: Option<Box<PartElementAndPseudoRules>>,
3280
3281 invalidation_map: InvalidationMap,
3283
3284 relative_selector_invalidation_map: InvalidationMap,
3286
3287 additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3288
3289 attribute_dependencies: PrecomputedHashSet<LocalName>,
3294
3295 nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3299
3300 nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3304
3305 nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3309
3310 state_dependencies: ElementState,
3314
3315 nth_of_state_dependencies: ElementState,
3318
3319 document_state_dependencies: DocumentState,
3323
3324 mapped_ids: PrecomputedHashSet<Atom>,
3329
3330 nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3334
3335 #[ignore_malloc_size_of = "Arc"]
3339 selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3340
3341 animations: LayerOrderedMap<KeyframesAnimation>,
3344
3345 #[ignore_malloc_size_of = "Arc"]
3348 custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3349
3350 custom_media: CustomMediaMap,
3352
3353 layer_id: FxHashMap<LayerName, LayerId>,
3355
3356 layers: SmallVec<[CascadeLayer; 1]>,
3358
3359 container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3361
3362 scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3364
3365 scope_subject_map: ScopeSubjectMap,
3367
3368 effective_media_query_results: EffectiveMediaQueryResults,
3370
3371 extra_data: ExtraStyleData,
3373
3374 rules_source_order: u32,
3377
3378 num_selectors: usize,
3380
3381 num_declarations: usize,
3383}
3384
3385static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3386 let list = SelectorList::implicit_scope();
3390 list.mark_as_intentionally_leaked();
3391 list
3392});
3393
3394fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3395 start
3398 .slice()
3399 .iter()
3400 .any(|s| s.matches_featureless_host(true).may_match())
3401}
3402
3403pub fn replace_parent_selector_with_implicit_scope(
3405 selectors: &SelectorList<SelectorImpl>,
3406) -> SelectorList<SelectorImpl> {
3407 selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3408}
3409
3410impl CascadeData {
3411 pub fn new() -> Self {
3413 Self {
3414 normal_rules: ElementAndPseudoRules::default(),
3415 featureless_host_rules: None,
3416 slotted_rules: None,
3417 part_rules: None,
3418 invalidation_map: InvalidationMap::new(),
3419 relative_selector_invalidation_map: InvalidationMap::new(),
3420 additional_relative_selector_invalidation_map:
3421 AdditionalRelativeSelectorInvalidationMap::new(),
3422 nth_of_mapped_ids: PrecomputedHashSet::default(),
3423 nth_of_class_dependencies: PrecomputedHashSet::default(),
3424 nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3425 nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3426 nth_of_state_dependencies: ElementState::empty(),
3427 attribute_dependencies: PrecomputedHashSet::default(),
3428 state_dependencies: ElementState::empty(),
3429 document_state_dependencies: DocumentState::empty(),
3430 mapped_ids: PrecomputedHashSet::default(),
3431 selectors_for_cache_revalidation: SelectorMap::new(),
3432 animations: Default::default(),
3433 custom_property_registrations: Default::default(),
3434 custom_media: Default::default(),
3435 layer_id: Default::default(),
3436 layers: smallvec::smallvec![CascadeLayer::root()],
3437 container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3438 scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3439 scope_subject_map: Default::default(),
3440 extra_data: ExtraStyleData::default(),
3441 effective_media_query_results: EffectiveMediaQueryResults::new(),
3442 rules_source_order: 0,
3443 num_selectors: 0,
3444 num_declarations: 0,
3445 }
3446 }
3447
3448 pub fn rebuild<'a, S>(
3450 &mut self,
3451 device: &Device,
3452 quirks_mode: QuirksMode,
3453 collection: SheetCollectionFlusher<S>,
3454 guard: &SharedRwLockReadGuard,
3455 difference: &mut CascadeDataDifference,
3456 ) -> Result<(), AllocErr>
3457 where
3458 S: StylesheetInDocument + PartialEq + 'static,
3459 {
3460 if !collection.dirty() {
3461 return Ok(());
3462 }
3463
3464 let validity = collection.data_validity();
3465
3466 let mut old_position_try_data = LayerOrderedMap::default();
3467 if validity != DataValidity::Valid {
3468 old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3469 self.clear_cascade_data();
3470 if validity == DataValidity::FullyInvalid {
3471 self.clear_invalidation_data();
3472 }
3473 }
3474
3475 let mut result = Ok(());
3476
3477 collection.each(|index, stylesheet, rebuild_kind| {
3478 result = self.add_stylesheet(
3479 device,
3480 quirks_mode,
3481 stylesheet,
3482 index,
3483 guard,
3484 rebuild_kind,
3485 None,
3486 if validity == DataValidity::Valid {
3487 Some(difference)
3488 } else {
3489 None
3490 },
3491 );
3492 result.is_ok()
3493 });
3494
3495 self.did_finish_rebuild();
3496
3497 if validity != DataValidity::Valid {
3500 difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3501 }
3502
3503 result
3504 }
3505
3506 pub fn custom_media_map(&self) -> &CustomMediaMap {
3508 &self.custom_media
3509 }
3510
3511 pub fn invalidation_map(&self) -> &InvalidationMap {
3513 &self.invalidation_map
3514 }
3515
3516 pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3518 &self.relative_selector_invalidation_map
3519 }
3520
3521 pub fn relative_invalidation_map_attributes(
3523 &self,
3524 ) -> &AdditionalRelativeSelectorInvalidationMap {
3525 &self.additional_relative_selector_invalidation_map
3526 }
3527
3528 #[inline]
3531 pub fn has_state_dependency(&self, state: ElementState) -> bool {
3532 self.state_dependencies.intersects(state)
3533 }
3534
3535 #[inline]
3538 pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3539 self.nth_of_custom_state_dependencies.contains(state)
3540 }
3541
3542 #[inline]
3545 pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3546 self.nth_of_state_dependencies.intersects(state)
3547 }
3548
3549 #[inline]
3552 pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3553 self.attribute_dependencies.contains(local_name)
3554 }
3555
3556 #[inline]
3559 pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3560 self.nth_of_mapped_ids.contains(id)
3561 }
3562
3563 #[inline]
3566 pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3567 self.nth_of_class_dependencies.contains(class)
3568 }
3569
3570 #[inline]
3573 pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3574 self.nth_of_attribute_dependencies.contains(local_name)
3575 }
3576
3577 #[inline]
3579 pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3580 self.normal_rules.rules(pseudo_elements)
3581 }
3582
3583 #[inline]
3585 pub fn featureless_host_rules(
3586 &self,
3587 pseudo_elements: &[PseudoElement],
3588 ) -> Option<&SelectorMap<Rule>> {
3589 self.featureless_host_rules
3590 .as_ref()
3591 .and_then(|d| d.rules(pseudo_elements))
3592 }
3593
3594 pub fn any_featureless_host_rules(&self) -> bool {
3596 self.featureless_host_rules.is_some()
3597 }
3598
3599 #[inline]
3601 pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3602 self.slotted_rules
3603 .as_ref()
3604 .and_then(|d| d.rules(pseudo_elements))
3605 }
3606
3607 pub fn any_slotted_rule(&self) -> bool {
3609 self.slotted_rules.is_some()
3610 }
3611
3612 #[inline]
3614 pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3615 self.part_rules
3616 .as_ref()
3617 .and_then(|d| d.rules(pseudo_elements))
3618 }
3619
3620 pub fn any_part_rule(&self) -> bool {
3622 self.part_rules.is_some()
3623 }
3624
3625 #[inline]
3626 fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3627 self.layers[id.0 as usize].order
3628 }
3629
3630 pub(crate) fn container_condition_matches<E>(
3631 &self,
3632 mut id: ContainerConditionId,
3633 stylist: &Stylist,
3634 element: E,
3635 context: &mut MatchingContext<E::Impl>,
3636 ) -> bool
3637 where
3638 E: TElement,
3639 {
3640 loop {
3641 let condition_ref = &self.container_conditions[id.0 as usize];
3642 if condition_ref.conditions.is_empty() {
3643 return true;
3644 }
3645 let matches = condition_ref.conditions.iter().any(|condition| {
3646 condition
3647 .matches(
3648 stylist,
3649 element,
3650 context.extra_data.originating_element_style,
3651 &mut context.extra_data.cascade_input_flags,
3652 )
3653 .to_bool(false)
3654 });
3655 if !matches {
3656 return false;
3657 }
3658 id = condition_ref.parent;
3659 }
3660 }
3661
3662 pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3663 &self,
3664 rule: &Rule,
3665 element: E,
3666 context: &mut MatchingContext<E::Impl>,
3667 ) -> ScopeProximity {
3668 context
3669 .extra_data
3670 .cascade_input_flags
3671 .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3672
3673 let result = scope_root_candidates(
3677 &self.scope_conditions,
3678 rule.scope_condition_id,
3679 &element,
3680 rule.selector.is_part(),
3681 &self.scope_subject_map,
3682 context,
3683 );
3684 for candidate in result.candidates {
3685 if context.nest_for_scope(Some(candidate.root), |context| {
3686 matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3687 }) {
3688 return candidate.proximity;
3689 }
3690 }
3691 ScopeProximity::infinity()
3692 }
3693
3694 fn did_finish_rebuild(&mut self) {
3695 self.shrink_maps_if_needed();
3696 self.compute_layer_order();
3697 }
3698
3699 fn shrink_maps_if_needed(&mut self) {
3700 self.normal_rules.shrink_if_needed();
3701 if let Some(ref mut host_rules) = self.featureless_host_rules {
3702 host_rules.shrink_if_needed();
3703 }
3704 if let Some(ref mut slotted_rules) = self.slotted_rules {
3705 slotted_rules.shrink_if_needed();
3706 }
3707 self.animations.shrink_if_needed();
3708 self.custom_property_registrations.shrink_if_needed();
3709 self.invalidation_map.shrink_if_needed();
3710 self.relative_selector_invalidation_map.shrink_if_needed();
3711 self.additional_relative_selector_invalidation_map
3712 .shrink_if_needed();
3713 self.attribute_dependencies.shrink_if_needed();
3714 self.nth_of_attribute_dependencies.shrink_if_needed();
3715 self.nth_of_custom_state_dependencies.shrink_if_needed();
3716 self.nth_of_class_dependencies.shrink_if_needed();
3717 self.nth_of_mapped_ids.shrink_if_needed();
3718 self.mapped_ids.shrink_if_needed();
3719 self.layer_id.shrink_if_needed();
3720 self.selectors_for_cache_revalidation.shrink_if_needed();
3721 self.scope_subject_map.shrink_if_needed();
3722 }
3723
3724 fn compute_layer_order(&mut self) {
3725 debug_assert_ne!(
3726 self.layers.len(),
3727 0,
3728 "There should be at least the root layer!"
3729 );
3730 if self.layers.len() == 1 {
3731 return; }
3733 let (first, remaining) = self.layers.split_at_mut(1);
3734 let root = &mut first[0];
3735 let mut order = LayerOrder::first();
3736 compute_layer_order_for_subtree(root, remaining, &mut order);
3737
3738 fn compute_layer_order_for_subtree(
3741 parent: &mut CascadeLayer,
3742 remaining_layers: &mut [CascadeLayer],
3743 order: &mut LayerOrder,
3744 ) {
3745 for child in parent.children.iter() {
3746 debug_assert!(
3747 parent.id < *child,
3748 "Children are always registered after parents"
3749 );
3750 let child_index = (child.0 - parent.id.0 - 1) as usize;
3751 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3752 let child = &mut first[child_index];
3753 compute_layer_order_for_subtree(child, remaining, order);
3754 }
3755
3756 if parent.id != LayerId::root() {
3757 parent.order = *order;
3758 order.inc();
3759 }
3760 }
3761 self.extra_data.sort_by_layer(&self.layers);
3762 self.animations
3763 .sort_with(&self.layers, compare_keyframes_in_same_layer);
3764 self.custom_property_registrations.sort(&self.layers)
3765 }
3766
3767 fn collect_applicable_media_query_results_into<S>(
3776 device: &Device,
3777 stylesheet: &S,
3778 guard: &SharedRwLockReadGuard,
3779 results: &mut Vec<MediaListKey>,
3780 contents_list: &mut StyleSheetContentList,
3781 custom_media_map: &mut CustomMediaMap,
3782 ) where
3783 S: StylesheetInDocument + 'static,
3784 {
3785 if !stylesheet.enabled() {
3786 return;
3787 }
3788 if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
3789 return;
3790 }
3791
3792 debug!(" + {:?}", stylesheet);
3793 let contents = stylesheet.contents(guard);
3794 results.push(contents.to_media_list_key());
3795
3796 contents_list.push(StylesheetContentsPtr(unsafe {
3798 Arc::from_raw_addrefed(&*contents)
3799 }));
3800
3801 let mut iter = stylesheet
3802 .contents(guard)
3803 .effective_rules(device, custom_media_map, guard);
3804 while let Some(rule) = iter.next() {
3805 match *rule {
3806 CssRule::CustomMedia(ref custom_media) => {
3807 iter.custom_media()
3808 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3809 },
3810 CssRule::Import(ref lock) => {
3811 let import_rule = lock.read_with(guard);
3812 debug!(" + {:?}", import_rule.stylesheet.media(guard));
3813 results.push(import_rule.to_media_list_key());
3814 },
3815 CssRule::Media(ref media_rule) => {
3816 debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3817 results.push(media_rule.to_media_list_key());
3818 },
3819 _ => {},
3820 }
3821 }
3822 }
3823
3824 fn add_styles(
3825 &mut self,
3826 selectors: &SelectorList<SelectorImpl>,
3827 declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3828 ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3829 containing_rule_state: &ContainingRuleState,
3830 mut replaced_selectors: Option<&mut ReplacedSelectors>,
3831 guard: &SharedRwLockReadGuard,
3832 rebuild_kind: SheetRebuildKind,
3833 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3834 quirks_mode: QuirksMode,
3835 mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3836 ) -> Result<(), AllocErr> {
3837 self.num_declarations += declarations.read_with(guard).len();
3838 for selector in selectors.slice() {
3839 self.num_selectors += 1;
3840
3841 let pseudo_elements = selector.pseudo_elements();
3842 let inner_pseudo_element = pseudo_elements.get(0);
3843 if let Some(pseudo) = inner_pseudo_element {
3844 if pseudo.is_precomputed() {
3845 debug_assert!(selector.is_universal());
3846 debug_assert!(ancestor_selectors.is_none());
3847 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3848 debug_assert!(!containing_rule_state.scope_is_effective());
3850 precomputed_pseudo_element_decls
3851 .as_mut()
3852 .expect("Expected precomputed declarations for the UA level")
3853 .get_or_insert_with(pseudo, Vec::new)
3854 .push(ApplicableDeclarationBlock::new(
3855 StyleSource::from_declarations(declarations.clone()),
3856 self.rules_source_order,
3857 CascadeLevel::new(CascadeOrigin::UA),
3858 selector.specificity(),
3859 LayerOrder::root(),
3860 ScopeProximity::infinity(),
3861 RuleCascadeFlags::empty(),
3862 ));
3863 continue;
3864 }
3865 if pseudo_elements
3866 .iter()
3867 .any(|p| p.is_unknown_webkit_pseudo_element())
3868 {
3869 continue;
3870 }
3871 }
3872
3873 debug_assert!(!pseudo_elements
3874 .iter()
3875 .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3876
3877 let selector = match ancestor_selectors {
3878 Some(ref s) => selector.replace_parent_selector(&s),
3879 None => selector.clone(),
3880 };
3881
3882 let hashes = AncestorHashes::new(&selector, quirks_mode);
3883
3884 let rule = Rule::new(
3885 selector,
3886 hashes,
3887 StyleSource::from_declarations(declarations.clone()),
3888 self.rules_source_order,
3889 containing_rule_state.layer_id,
3890 containing_rule_state.container_condition_id,
3891 containing_rule_state.cascade_flags(),
3892 containing_rule_state.containing_scope_rule_state.id,
3893 );
3894
3895 if let Some(ref mut replaced_selectors) = replaced_selectors {
3896 replaced_selectors.push(rule.selector.clone())
3897 }
3898
3899 if rebuild_kind.should_rebuild_invalidation() {
3900 let mut scope_dependencies = note_selector_for_invalidation(
3901 &rule.selector,
3902 quirks_mode,
3903 &mut self.invalidation_map,
3904 &mut self.relative_selector_invalidation_map,
3905 &mut self.additional_relative_selector_invalidation_map,
3906 None,
3907 None,
3908 )?;
3909 let mut needs_revalidation = false;
3910 let mut visitor = StylistSelectorVisitor {
3911 needs_revalidation: &mut needs_revalidation,
3912 passed_rightmost_selector: false,
3913 in_selector_list_of: SelectorListKind::default(),
3914 mapped_ids: &mut self.mapped_ids,
3915 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3916 attribute_dependencies: &mut self.attribute_dependencies,
3917 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3918 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3919 nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3920 state_dependencies: &mut self.state_dependencies,
3921 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3922 document_state_dependencies: &mut self.document_state_dependencies,
3923 };
3924 rule.selector.visit(&mut visitor);
3925
3926 if needs_revalidation {
3927 self.selectors_for_cache_revalidation.insert(
3928 RevalidationSelectorAndHashes::new(
3929 rule.selector.clone(),
3930 rule.hashes.clone(),
3931 ),
3932 quirks_mode,
3933 )?;
3934 }
3935
3936 match (
3937 scope_dependencies.as_mut(),
3938 collected_scope_dependencies.as_mut(),
3939 ) {
3940 (Some(inner_scope_deps), Some(scope_deps)) => {
3941 scope_deps.append(inner_scope_deps)
3942 },
3943 _ => {},
3944 }
3945 }
3946
3947 if let Some(parts) = rule.selector.parts() {
3951 let map = self
3958 .part_rules
3959 .get_or_insert_with(|| Box::new(Default::default()))
3960 .for_insertion(&pseudo_elements);
3961 map.try_reserve(1)?;
3962 let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3963 vec.try_reserve(1)?;
3964 vec.push(rule);
3965 } else {
3966 let scope_matches_shadow_host = containing_rule_state
3967 .containing_scope_rule_state
3968 .matches_shadow_host
3969 == ScopeMatchesShadowHost::Yes;
3970 let matches_featureless_host_only = match rule
3971 .selector
3972 .matches_featureless_host(scope_matches_shadow_host)
3973 {
3974 MatchesFeaturelessHost::Only => true,
3975 MatchesFeaturelessHost::Yes => {
3976 self.featureless_host_rules
3978 .get_or_insert_with(|| Box::new(Default::default()))
3979 .for_insertion(&pseudo_elements)
3980 .insert(rule.clone(), quirks_mode)?;
3981 false
3982 },
3983 MatchesFeaturelessHost::Never => false,
3984 };
3985
3986 let rules = if matches_featureless_host_only {
3993 self.featureless_host_rules
3994 .get_or_insert_with(|| Box::new(Default::default()))
3995 } else if rule.selector.is_slotted() {
3996 self.slotted_rules
3997 .get_or_insert_with(|| Box::new(Default::default()))
3998 } else {
3999 &mut self.normal_rules
4000 }
4001 .for_insertion(&pseudo_elements);
4002 rules.insert(rule, quirks_mode)?;
4003 }
4004 }
4005 self.rules_source_order += 1;
4006 Ok(())
4007 }
4008
4009 fn add_rule_list<S>(
4010 &mut self,
4011 rules: std::slice::Iter<CssRule>,
4012 device: &Device,
4013 quirks_mode: QuirksMode,
4014 stylesheet: &S,
4015 sheet_index: usize,
4016 guard: &SharedRwLockReadGuard,
4017 rebuild_kind: SheetRebuildKind,
4018 containing_rule_state: &mut ContainingRuleState,
4019 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4020 mut difference: Option<&mut CascadeDataDifference>,
4021 ) -> Result<(), AllocErr>
4022 where
4023 S: StylesheetInDocument + 'static,
4024 {
4025 for rule in rules {
4026 let mut handled = true;
4029 let mut list_for_nested_rules = None;
4030 match *rule {
4031 CssRule::Style(ref locked) => {
4032 let style_rule = locked.read_with(guard);
4033 let has_nested_rules = style_rule.rules.is_some();
4034 let mut replaced_selectors = ReplacedSelectors::new();
4035 let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
4036 let collect_replaced_selectors =
4037 has_nested_rules && ancestor_selectors.is_some();
4038 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4039 .scope_is_effective()
4040 .then(|| Vec::new());
4041 self.add_styles(
4042 &style_rule.selectors,
4043 &style_rule.block,
4044 ancestor_selectors,
4045 containing_rule_state,
4046 if collect_replaced_selectors {
4047 Some(&mut replaced_selectors)
4048 } else {
4049 None
4050 },
4051 guard,
4052 rebuild_kind,
4053 precomputed_pseudo_element_decls.as_deref_mut(),
4054 quirks_mode,
4055 inner_dependencies.as_mut(),
4056 )?;
4057 if let Some(mut scope_dependencies) = inner_dependencies {
4058 containing_rule_state
4059 .containing_scope_rule_state
4060 .inner_dependencies
4061 .append(&mut scope_dependencies);
4062 }
4063 if has_nested_rules {
4064 handled = false;
4065 list_for_nested_rules = Some(if collect_replaced_selectors {
4066 SelectorList::from_iter(replaced_selectors.drain(..))
4067 } else {
4068 style_rule.selectors.clone()
4069 });
4070 }
4071 },
4072 CssRule::NestedDeclarations(ref rule) => {
4073 if let Some(ref ancestor_selectors) =
4074 containing_rule_state.ancestor_selector_lists.last()
4075 {
4076 let decls = &rule.read_with(guard).block;
4077 let selectors = match containing_rule_state.nested_declarations_context {
4078 NestedDeclarationsContext::Style => ancestor_selectors,
4079 NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
4080 };
4081 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4082 .scope_is_effective()
4083 .then(|| Vec::new());
4084 self.add_styles(
4085 selectors,
4086 decls,
4087 None,
4088 containing_rule_state,
4089 None,
4090 guard,
4091 SheetRebuildKind::CascadeOnly,
4094 precomputed_pseudo_element_decls.as_deref_mut(),
4095 quirks_mode,
4096 inner_dependencies.as_mut(),
4097 )?;
4098 if let Some(mut scope_dependencies) = inner_dependencies {
4099 containing_rule_state
4100 .containing_scope_rule_state
4101 .inner_dependencies
4102 .append(&mut scope_dependencies);
4103 }
4104 }
4105 },
4106 CssRule::Keyframes(ref keyframes_rule) => {
4107 debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
4108 let keyframes_rule = keyframes_rule.read_with(guard);
4109 let name = keyframes_rule.name.as_atom().clone();
4110 let animation = KeyframesAnimation::from_keyframes(
4111 &keyframes_rule.keyframes,
4112 keyframes_rule.vendor_prefix.clone(),
4113 guard,
4114 );
4115 self.animations.try_insert_with(
4116 name,
4117 animation,
4118 containing_rule_state.layer_id,
4119 compare_keyframes_in_same_layer,
4120 )?;
4121 },
4122 CssRule::Property(ref registration) => {
4123 self.custom_property_registrations.try_insert(
4124 registration.name.0.clone(),
4125 Arc::clone(registration),
4126 containing_rule_state.layer_id,
4127 )?;
4128 },
4129 CssRule::FontFace(ref rule) => {
4130 self.extra_data
4141 .add_font_face(rule, containing_rule_state.layer_id);
4142 },
4143 CssRule::FontFeatureValues(ref rule) => {
4144 self.extra_data
4145 .add_font_feature_values(rule, containing_rule_state.layer_id);
4146 },
4147 CssRule::FontPaletteValues(ref rule) => {
4148 self.extra_data
4149 .add_font_palette_values(rule, containing_rule_state.layer_id);
4150 },
4151 CssRule::CounterStyle(ref rule) => {
4152 self.extra_data.add_counter_style(
4153 guard,
4154 rule,
4155 containing_rule_state.layer_id,
4156 )?;
4157 },
4158 CssRule::PositionTry(ref rule) => {
4159 let name = rule.read_with(guard).name.0.clone();
4160 if let Some(ref mut difference) = difference {
4161 difference.changed_position_try_names.insert(name.clone());
4162 }
4163 self.extra_data.add_position_try(
4164 name,
4165 rule.clone(),
4166 containing_rule_state.layer_id,
4167 )?;
4168 },
4169 CssRule::Page(ref rule) => {
4170 self.extra_data
4171 .add_page(guard, rule, containing_rule_state.layer_id)?;
4172 handled = false;
4173 },
4174 CssRule::ViewTransition(ref rule) => {
4175 self.extra_data
4176 .add_view_transition(rule, containing_rule_state.layer_id);
4177 },
4178 _ => {
4179 handled = false;
4180 },
4181 }
4182
4183 if handled {
4184 if cfg!(debug_assertions) {
4187 let mut effective = false;
4188 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4189 rule,
4190 device,
4191 quirks_mode,
4192 &self.custom_media,
4193 guard,
4194 &mut effective,
4195 );
4196 debug_assert!(children.is_empty());
4197 debug_assert!(effective);
4198 }
4199 continue;
4200 }
4201
4202 let mut effective = false;
4203 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4204 rule,
4205 device,
4206 quirks_mode,
4207 &self.custom_media,
4208 guard,
4209 &mut effective,
4210 );
4211 if !effective {
4212 continue;
4213 }
4214
4215 fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4216 if let Some(id) = data.layer_id.get(layer) {
4220 return *id;
4221 }
4222 let id = LayerId(data.layers.len() as u16);
4223
4224 let parent_layer_id = if layer.layer_names().len() > 1 {
4225 let mut parent = layer.clone();
4226 parent.0.pop();
4227
4228 *data
4229 .layer_id
4230 .get_mut(&parent)
4231 .expect("Parent layers should be registered before child layers")
4232 } else {
4233 LayerId::root()
4234 };
4235
4236 data.layers[parent_layer_id.0 as usize].children.push(id);
4237 data.layers.push(CascadeLayer {
4238 id,
4239 order: LayerOrder::first(),
4242 children: vec![],
4243 });
4244
4245 data.layer_id.insert(layer.clone(), id);
4246
4247 id
4248 }
4249
4250 fn maybe_register_layers(
4251 data: &mut CascadeData,
4252 name: Option<&LayerName>,
4253 containing_rule_state: &mut ContainingRuleState,
4254 ) {
4255 let anon_name;
4256 let name = match name {
4257 Some(name) => name,
4258 None => {
4259 anon_name = LayerName::new_anonymous();
4260 &anon_name
4261 },
4262 };
4263 for name in name.layer_names() {
4264 containing_rule_state.layer_name.0.push(name.clone());
4265 containing_rule_state.layer_id =
4266 maybe_register_layer(data, &containing_rule_state.layer_name);
4267 }
4268 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4269 }
4270
4271 let saved_containing_rule_state = containing_rule_state.save();
4272 match *rule {
4273 CssRule::Import(ref lock) => {
4274 let import_rule = lock.read_with(guard);
4275 if rebuild_kind.should_rebuild_invalidation() {
4276 self.effective_media_query_results
4277 .saw_effective(import_rule);
4278 }
4279 match import_rule.layer {
4280 ImportLayer::Named(ref name) => {
4281 maybe_register_layers(self, Some(name), containing_rule_state)
4282 },
4283 ImportLayer::Anonymous => {
4284 maybe_register_layers(self, None, containing_rule_state)
4285 },
4286 ImportLayer::None => {},
4287 }
4288 },
4289 CssRule::Media(ref media_rule) => {
4290 if rebuild_kind.should_rebuild_invalidation() {
4291 self.effective_media_query_results
4292 .saw_effective(&**media_rule);
4293 }
4294 },
4295 CssRule::LayerBlock(ref rule) => {
4296 maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4297 },
4298 CssRule::CustomMedia(ref custom_media) => {
4299 self.custom_media
4300 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4301 },
4302 CssRule::LayerStatement(ref rule) => {
4303 for name in &*rule.names {
4304 maybe_register_layers(self, Some(name), containing_rule_state);
4305 containing_rule_state.restore(&saved_containing_rule_state);
4307 }
4308 },
4309 CssRule::Style(..) => {
4310 containing_rule_state.nested_declarations_context =
4311 NestedDeclarationsContext::Style;
4312 if let Some(s) = list_for_nested_rules {
4313 containing_rule_state.ancestor_selector_lists.push(s);
4314 }
4315 },
4316 CssRule::Container(ref rule) => {
4317 let id = ContainerConditionId(self.container_conditions.len() as u16);
4318 let condition = ContainerConditionReference {
4319 parent: containing_rule_state.container_condition_id,
4320 conditions: rule.conditions.0.clone(),
4321 };
4322 self.container_conditions.push(condition);
4323 containing_rule_state.container_condition_id = id;
4324 },
4325 CssRule::StartingStyle(..) => {
4326 containing_rule_state
4327 .cascade_flags
4328 .insert(RuleCascadeFlags::STARTING_STYLE);
4329 },
4330 CssRule::AppearanceBase(..) => {
4331 containing_rule_state
4332 .cascade_flags
4333 .insert(RuleCascadeFlags::APPEARANCE_BASE);
4334 },
4335 CssRule::Scope(ref rule) => {
4336 containing_rule_state.nested_declarations_context =
4337 NestedDeclarationsContext::Scope;
4338 let id = ScopeConditionId(self.scope_conditions.len() as u16);
4339 let mut matches_shadow_host = false;
4340 let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4341 matches_shadow_host = scope_start_matches_shadow_host(start);
4342 StylistImplicitScopeRoot::default()
4344 } else {
4345 if let Some(root) = stylesheet.implicit_scope_root() {
4348 matches_shadow_host = root.matches_shadow_host();
4349 match root {
4350 ImplicitScopeRoot::InLightTree(_)
4351 | ImplicitScopeRoot::Constructed
4352 | ImplicitScopeRoot::DocumentElement => {
4353 StylistImplicitScopeRoot::Normal(root)
4354 },
4355 ImplicitScopeRoot::ShadowHost(_)
4356 | ImplicitScopeRoot::InShadowTree(_) => {
4357 StylistImplicitScopeRoot::Cached(sheet_index)
4364 },
4365 }
4366 } else {
4367 StylistImplicitScopeRoot::default()
4369 }
4370 };
4371
4372 let replaced =
4373 {
4374 let start = rule.bounds.start.as_ref().map(|selector| {
4375 match containing_rule_state.ancestor_selector_lists.last() {
4376 Some(s) => selector.replace_parent_selector(s),
4377 None => selector.clone(),
4378 }
4379 });
4380 let implicit_scope_selector = &*IMPLICIT_SCOPE;
4381 let end = rule.bounds.end.as_ref().map(|selector| {
4382 selector.replace_parent_selector(implicit_scope_selector)
4383 });
4384 containing_rule_state
4385 .ancestor_selector_lists
4386 .push(implicit_scope_selector.clone());
4387 ScopeBoundsWithHashes::new(quirks_mode, start, end)
4388 };
4389
4390 if let Some(selectors) = replaced.start.as_ref() {
4391 self.scope_subject_map
4392 .add_bound_start(&selectors.selectors, quirks_mode);
4393 }
4394
4395 let is_trivial = replaced.is_trivial();
4396 self.scope_conditions.push(ScopeConditionReference {
4397 parent: containing_rule_state.containing_scope_rule_state.id,
4398 condition: Some(replaced),
4399 implicit_scope_root,
4400 is_trivial,
4401 });
4402
4403 containing_rule_state
4404 .containing_scope_rule_state
4405 .matches_shadow_host
4406 .nest_for_scope(matches_shadow_host);
4407 containing_rule_state.containing_scope_rule_state.id = id;
4408 containing_rule_state
4409 .containing_scope_rule_state
4410 .inner_dependencies
4411 .reserve(children.iter().len());
4412 },
4413 _ => {},
4415 }
4416
4417 if !children.is_empty() {
4418 self.add_rule_list(
4419 children.iter(),
4420 device,
4421 quirks_mode,
4422 stylesheet,
4423 sheet_index,
4424 guard,
4425 rebuild_kind,
4426 containing_rule_state,
4427 precomputed_pseudo_element_decls.as_deref_mut(),
4428 difference.as_deref_mut(),
4429 )?;
4430 }
4431
4432 if let Some(scope_restore_data) =
4433 containing_rule_state.restore(&saved_containing_rule_state)
4434 {
4435 let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4436 let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4437 if let Some(cond) = cur_scope.condition.as_ref() {
4438 let mut _unused = false;
4439 let visitor = StylistSelectorVisitor {
4440 needs_revalidation: &mut _unused,
4441 passed_rightmost_selector: true,
4442 in_selector_list_of: SelectorListKind::default(),
4443 mapped_ids: &mut self.mapped_ids,
4444 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4445 attribute_dependencies: &mut self.attribute_dependencies,
4446 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4447 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4448 nth_of_custom_state_dependencies: &mut self
4449 .nth_of_custom_state_dependencies,
4450 state_dependencies: &mut self.state_dependencies,
4451 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4452 document_state_dependencies: &mut self.document_state_dependencies,
4453 };
4454
4455 let dependency_vector = build_scope_dependencies(
4456 quirks_mode,
4457 cur_scope_inner_dependencies,
4458 visitor,
4459 cond,
4460 &mut self.invalidation_map,
4461 &mut self.relative_selector_invalidation_map,
4462 &mut self.additional_relative_selector_invalidation_map,
4463 )?;
4464
4465 containing_rule_state
4466 .containing_scope_rule_state
4467 .inner_dependencies
4468 .extend(dependency_vector);
4469 }
4470 }
4471 }
4472
4473 Ok(())
4474 }
4475
4476 fn add_stylesheet<S>(
4478 &mut self,
4479 device: &Device,
4480 quirks_mode: QuirksMode,
4481 stylesheet: &S,
4482 sheet_index: usize,
4483 guard: &SharedRwLockReadGuard,
4484 rebuild_kind: SheetRebuildKind,
4485 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4486 mut difference: Option<&mut CascadeDataDifference>,
4487 ) -> Result<(), AllocErr>
4488 where
4489 S: StylesheetInDocument + 'static,
4490 {
4491 if !stylesheet.enabled() {
4492 return Ok(());
4493 }
4494
4495 if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4496 return Ok(());
4497 }
4498
4499 let contents = stylesheet.contents(guard);
4500 if rebuild_kind.should_rebuild_invalidation() {
4501 self.effective_media_query_results.saw_effective(&*contents);
4502 }
4503
4504 let mut state = ContainingRuleState::default();
4505 self.add_rule_list(
4506 contents.rules(guard).iter(),
4507 device,
4508 quirks_mode,
4509 stylesheet,
4510 sheet_index,
4511 guard,
4512 rebuild_kind,
4513 &mut state,
4514 precomputed_pseudo_element_decls.as_deref_mut(),
4515 difference.as_deref_mut(),
4516 )?;
4517
4518 Ok(())
4519 }
4520
4521 pub fn media_feature_affected_matches<S>(
4524 &self,
4525 stylesheet: &S,
4526 guard: &SharedRwLockReadGuard,
4527 device: &Device,
4528 quirks_mode: QuirksMode,
4529 ) -> bool
4530 where
4531 S: StylesheetInDocument + 'static,
4532 {
4533 use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4534
4535 let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4536
4537 let contents = stylesheet.contents(guard);
4538 let effective_then = self.effective_media_query_results.was_effective(contents);
4539
4540 if effective_now != effective_then {
4541 debug!(
4542 " > Stylesheet {:?} changed -> {}, {}",
4543 stylesheet.media(guard),
4544 effective_then,
4545 effective_now
4546 );
4547 return false;
4548 }
4549
4550 if !effective_now {
4551 return true;
4552 }
4553
4554 let custom_media = CustomMediaMap::default();
4556 let mut iter =
4557 contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4558 while let Some(rule) = iter.next() {
4559 match *rule {
4560 CssRule::Style(..)
4561 | CssRule::NestedDeclarations(..)
4562 | CssRule::Namespace(..)
4563 | CssRule::FontFace(..)
4564 | CssRule::Container(..)
4565 | CssRule::CounterStyle(..)
4566 | CssRule::Supports(..)
4567 | CssRule::Keyframes(..)
4568 | CssRule::Margin(..)
4569 | CssRule::Page(..)
4570 | CssRule::Property(..)
4571 | CssRule::Document(..)
4572 | CssRule::LayerBlock(..)
4573 | CssRule::LayerStatement(..)
4574 | CssRule::FontPaletteValues(..)
4575 | CssRule::FontFeatureValues(..)
4576 | CssRule::Scope(..)
4577 | CssRule::StartingStyle(..)
4578 | CssRule::AppearanceBase(..)
4579 | CssRule::CustomMedia(..)
4580 | CssRule::PositionTry(..)
4581 | CssRule::ViewTransition(..) => {
4582 continue;
4585 },
4586 CssRule::Import(ref lock) => {
4587 let import_rule = lock.read_with(guard);
4588 let effective_now = match import_rule.stylesheet.media(guard) {
4589 Some(m) => m.evaluate(
4590 device,
4591 quirks_mode,
4592 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4593 ),
4594 None => true,
4595 };
4596 let effective_then = self
4597 .effective_media_query_results
4598 .was_effective(import_rule);
4599 if effective_now != effective_then {
4600 debug!(
4601 " > @import rule {:?} changed {} -> {}",
4602 import_rule.stylesheet.media(guard),
4603 effective_then,
4604 effective_now
4605 );
4606 return false;
4607 }
4608
4609 if !effective_now {
4610 iter.skip_children();
4611 }
4612 },
4613 CssRule::Media(ref media_rule) => {
4614 let mq = media_rule.media_queries.read_with(guard);
4615 let effective_now = mq.evaluate(
4616 device,
4617 quirks_mode,
4618 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4619 );
4620 let effective_then = self
4621 .effective_media_query_results
4622 .was_effective(&**media_rule);
4623
4624 if effective_now != effective_then {
4625 debug!(
4626 " > @media rule {:?} changed {} -> {}",
4627 mq, effective_then, effective_now
4628 );
4629 return false;
4630 }
4631
4632 if !effective_now {
4633 iter.skip_children();
4634 }
4635 },
4636 }
4637 }
4638
4639 true
4640 }
4641
4642 pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4644 &self.custom_property_registrations
4645 }
4646
4647 fn revalidate_scopes<E: TElement>(
4648 &self,
4649 element: &E,
4650 matching_context: &mut MatchingContext<E::Impl>,
4651 result: &mut ScopeRevalidationResult,
4652 ) {
4653 for condition_id in 1..self.scope_conditions.len() {
4660 let condition = &self.scope_conditions[condition_id];
4661 let matches = if condition.is_trivial {
4662 continue;
4665 } else {
4666 let result = scope_root_candidates(
4667 &self.scope_conditions,
4668 ScopeConditionId(condition_id as u16),
4669 element,
4670 false,
4672 &self.scope_subject_map,
4673 matching_context,
4674 );
4675 !result.candidates.is_empty()
4676 };
4677 result.scopes_matched.push(matches);
4678 }
4679 }
4680
4681 fn clear_cascade_data(&mut self) {
4683 self.normal_rules.clear();
4684 if let Some(ref mut slotted_rules) = self.slotted_rules {
4685 slotted_rules.clear();
4686 }
4687 if let Some(ref mut part_rules) = self.part_rules {
4688 part_rules.clear();
4689 }
4690 if let Some(ref mut host_rules) = self.featureless_host_rules {
4691 host_rules.clear();
4692 }
4693 self.animations.clear();
4694 self.custom_property_registrations.clear();
4695 self.layer_id.clear();
4696 self.layers.clear();
4697 self.layers.push(CascadeLayer::root());
4698 self.custom_media.clear();
4699 self.container_conditions.clear();
4700 self.container_conditions
4701 .push(ContainerConditionReference::none());
4702 self.scope_conditions.clear();
4703 self.scope_conditions.push(ScopeConditionReference::none());
4704 self.extra_data.clear();
4705 self.rules_source_order = 0;
4706 self.num_selectors = 0;
4707 self.num_declarations = 0;
4708 }
4709
4710 fn clear_invalidation_data(&mut self) {
4711 self.invalidation_map.clear();
4712 self.relative_selector_invalidation_map.clear();
4713 self.additional_relative_selector_invalidation_map.clear();
4714 self.attribute_dependencies.clear();
4715 self.nth_of_attribute_dependencies.clear();
4716 self.nth_of_custom_state_dependencies.clear();
4717 self.nth_of_class_dependencies.clear();
4718 self.state_dependencies = ElementState::empty();
4719 self.nth_of_state_dependencies = ElementState::empty();
4720 self.document_state_dependencies = DocumentState::empty();
4721 self.mapped_ids.clear();
4722 self.nth_of_mapped_ids.clear();
4723 self.selectors_for_cache_revalidation.clear();
4724 self.effective_media_query_results.clear();
4725 self.scope_subject_map.clear();
4726 }
4727}
4728
4729fn note_scope_selector_for_invalidation(
4730 quirks_mode: QuirksMode,
4731 scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4732 dependency_vector: &mut Vec<Dependency>,
4733 invalidation_map: &mut InvalidationMap,
4734 relative_selector_invalidation_map: &mut InvalidationMap,
4735 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4736 visitor: &mut StylistSelectorVisitor<'_>,
4737 scope_kind: ScopeDependencyInvalidationKind,
4738 s: &Selector<SelectorImpl>,
4739) -> Result<(), AllocErr> {
4740 let mut new_inner_dependencies = note_selector_for_invalidation(
4741 &s.clone(),
4742 quirks_mode,
4743 invalidation_map,
4744 relative_selector_invalidation_map,
4745 additional_relative_selector_invalidation_map,
4746 Some(&scope_dependencies),
4747 Some(scope_kind),
4748 )?;
4749 s.visit(visitor);
4750 new_inner_dependencies.as_mut().map(|dep| {
4751 dependency_vector.append(dep);
4752 });
4753 Ok(())
4754}
4755
4756fn build_scope_dependencies(
4757 quirks_mode: QuirksMode,
4758 mut cur_scope_inner_dependencies: Vec<Dependency>,
4759 mut visitor: StylistSelectorVisitor<'_>,
4760 cond: &ScopeBoundsWithHashes,
4761 mut invalidation_map: &mut InvalidationMap,
4762 mut relative_selector_invalidation_map: &mut InvalidationMap,
4763 mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4764) -> Result<Vec<Dependency>, AllocErr> {
4765 if cond.end.is_some() {
4766 let deps =
4767 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4768 let mut end_dependency_vector = Vec::new();
4769 for s in cond.end_selectors() {
4770 note_scope_selector_for_invalidation(
4771 quirks_mode,
4772 &deps,
4773 &mut end_dependency_vector,
4774 &mut invalidation_map,
4775 &mut relative_selector_invalidation_map,
4776 &mut additional_relative_selector_invalidation_map,
4777 &mut visitor,
4778 ScopeDependencyInvalidationKind::ScopeEnd,
4779 s,
4780 )?;
4781 }
4782 cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4783 }
4784 let inner_scope_dependencies =
4785 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4786
4787 Ok(if cond.start.is_some() {
4788 let mut dependency_vector = Vec::new();
4789 for s in cond.start_selectors() {
4790 note_scope_selector_for_invalidation(
4791 quirks_mode,
4792 &inner_scope_dependencies,
4793 &mut dependency_vector,
4794 &mut invalidation_map,
4795 &mut relative_selector_invalidation_map,
4796 &mut additional_relative_selector_invalidation_map,
4797 &mut visitor,
4798 ScopeDependencyInvalidationKind::ExplicitScope,
4799 s,
4800 )?;
4801 }
4802 dependency_vector
4803 } else {
4804 vec![Dependency::new(
4805 IMPLICIT_SCOPE.slice()[0].clone(),
4806 0,
4807 Some(inner_scope_dependencies),
4808 DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4809 )]
4810 })
4811}
4812
4813impl CascadeDataCacheEntry for CascadeData {
4814 fn rebuild<S>(
4815 device: &Device,
4816 quirks_mode: QuirksMode,
4817 collection: SheetCollectionFlusher<S>,
4818 guard: &SharedRwLockReadGuard,
4819 old: &Self,
4820 difference: &mut CascadeDataDifference,
4821 ) -> Result<Arc<Self>, AllocErr>
4822 where
4823 S: StylesheetInDocument + PartialEq + 'static,
4824 {
4825 debug_assert!(collection.dirty(), "We surely need to do something?");
4826 let mut updatable_entry = match collection.data_validity() {
4828 DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4829 DataValidity::FullyInvalid => Self::new(),
4830 };
4831 updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4832 Ok(Arc::new(updatable_entry))
4833 }
4834
4835 #[cfg(feature = "gecko")]
4836 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4837 self.normal_rules.add_size_of(ops, sizes);
4838 if let Some(ref slotted_rules) = self.slotted_rules {
4839 slotted_rules.add_size_of(ops, sizes);
4840 }
4841 if let Some(ref part_rules) = self.part_rules {
4842 part_rules.add_size_of(ops, sizes);
4843 }
4844 if let Some(ref host_rules) = self.featureless_host_rules {
4845 host_rules.add_size_of(ops, sizes);
4846 }
4847 sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4848 sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4849 sizes.mOther += self.animations.size_of(ops);
4850 sizes.mOther += self.effective_media_query_results.size_of(ops);
4851 sizes.mOther += self.extra_data.size_of(ops);
4852 }
4853}
4854
4855impl Default for CascadeData {
4856 fn default() -> Self {
4857 CascadeData::new()
4858 }
4859}
4860
4861#[derive(Clone, Debug, MallocSizeOf)]
4864pub struct Rule {
4865 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4870 pub selector: Selector<SelectorImpl>,
4871
4872 pub hashes: AncestorHashes,
4874
4875 pub source_order: u32,
4879
4880 pub layer_id: LayerId,
4882
4883 pub container_condition_id: ContainerConditionId,
4885
4886 pub cascade_flags: RuleCascadeFlags,
4888
4889 pub scope_condition_id: ScopeConditionId,
4891
4892 #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4894 pub style_source: StyleSource,
4895}
4896
4897impl SelectorMapEntry for Rule {
4898 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4899 self.selector.iter()
4900 }
4901}
4902
4903impl Rule {
4904 pub fn specificity(&self) -> u32 {
4906 self.selector.specificity()
4907 }
4908
4909 pub fn to_applicable_declaration_block(
4912 &self,
4913 level: CascadeLevel,
4914 cascade_data: &CascadeData,
4915 scope_proximity: ScopeProximity,
4916 ) -> ApplicableDeclarationBlock {
4917 ApplicableDeclarationBlock::new(
4918 self.style_source.clone(),
4919 self.source_order,
4920 level,
4921 self.specificity(),
4922 cascade_data.layer_order_for(self.layer_id),
4923 scope_proximity,
4924 self.cascade_flags,
4925 )
4926 }
4927
4928 pub fn new(
4930 selector: Selector<SelectorImpl>,
4931 hashes: AncestorHashes,
4932 style_source: StyleSource,
4933 source_order: u32,
4934 layer_id: LayerId,
4935 container_condition_id: ContainerConditionId,
4936 cascade_flags: RuleCascadeFlags,
4937 scope_condition_id: ScopeConditionId,
4938 ) -> Self {
4939 Self {
4940 selector,
4941 hashes,
4942 style_source,
4943 source_order,
4944 layer_id,
4945 container_condition_id,
4946 cascade_flags,
4947 scope_condition_id,
4948 }
4949 }
4950}
4951
4952size_of_test!(Rule, 40);
4957
4958pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4960 let mut needs_revalidation = false;
4961 let mut mapped_ids = Default::default();
4962 let mut nth_of_mapped_ids = Default::default();
4963 let mut attribute_dependencies = Default::default();
4964 let mut nth_of_class_dependencies = Default::default();
4965 let mut nth_of_attribute_dependencies = Default::default();
4966 let mut nth_of_custom_state_dependencies = Default::default();
4967 let mut state_dependencies = ElementState::empty();
4968 let mut nth_of_state_dependencies = ElementState::empty();
4969 let mut document_state_dependencies = DocumentState::empty();
4970 let mut visitor = StylistSelectorVisitor {
4971 passed_rightmost_selector: false,
4972 needs_revalidation: &mut needs_revalidation,
4973 in_selector_list_of: SelectorListKind::default(),
4974 mapped_ids: &mut mapped_ids,
4975 nth_of_mapped_ids: &mut nth_of_mapped_ids,
4976 attribute_dependencies: &mut attribute_dependencies,
4977 nth_of_class_dependencies: &mut nth_of_class_dependencies,
4978 nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4979 nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4980 state_dependencies: &mut state_dependencies,
4981 nth_of_state_dependencies: &mut nth_of_state_dependencies,
4982 document_state_dependencies: &mut document_state_dependencies,
4983 };
4984 s.visit(&mut visitor);
4985 needs_revalidation
4986}