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