1use crate::AllocErr;
8use crate::ArcSlice;
9use crate::FxHashMap;
10use crate::applicable_declarations::{
11 ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
12};
13use crate::computed_value_flags::ComputedValueFlags;
14use crate::context::{CascadeInputs, QuirksMode, TreeCountingCaches};
15use crate::custom_properties::ComputedCustomProperties;
16use crate::custom_properties::{SpecifiedValue, parse_name};
17use crate::derives::*;
18use crate::device::Device;
19use crate::dom::TElement;
20#[cfg(feature = "gecko")]
21use crate::dom::TShadowRoot;
22#[cfg(feature = "gecko")]
23use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
24use crate::invalidation::element::invalidation_map::{
25 AdditionalRelativeSelectorInvalidationMap, Dependency, DependencyInvalidationKind,
26 InvalidationMap, ScopeDependencyInvalidationKind, note_selector_for_invalidation,
27};
28use crate::invalidation::media_queries::{
29 EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
30};
31use crate::invalidation::stylesheets::{RuleChangeKind, StylesheetInvalidationSet};
32#[cfg(feature = "gecko")]
33use crate::properties::StyleBuilder;
34use crate::properties::{
35 self, AnimationDeclarations, CascadeMode, ComputedValues, FirstLineReparenting,
36 PropertyDeclarationBlock, PropertyIdRef,
37};
38use crate::properties_and_values::registry::{
39 PropertyRegistration, ScriptRegistry as CustomPropertyScriptRegistry,
40};
41use crate::properties_and_values::rule::{
42 Descriptors as PropertyDescriptors, Inherits, PropertyRegistrationError, PropertyRuleName,
43};
44use crate::properties_and_values::syntax::Descriptor;
45use crate::rule_cache::{RuleCache, RuleCacheConditions};
46use crate::rule_collector::RuleCollector;
47use crate::rule_tree::{
48 CascadeLevel, CascadeOrigin, RuleCascadeFlags, RuleTree, StrongRuleNode, StyleSource,
49};
50use crate::selector_map::{
51 BucketMatches, PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry,
52};
53use crate::selector_parser::{NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl};
54use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
55use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
56use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
57use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
58use crate::stylesheets::UrlExtraData;
59use crate::stylesheets::container_rule::{ContainerAttributeDependencyKind, ContainerCondition};
60use crate::stylesheets::import_rule::ImportLayer;
61use crate::stylesheets::keyframes_rule::KeyframesAnimation;
62use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
63use crate::stylesheets::scope_rule::{
64 ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget, collect_scope_roots,
65 element_is_outside_of_scope, scope_selector_list_is_trivial,
66};
67use crate::stylesheets::{
68 CounterStyleRule, CssRule, CssRuleRef, EffectiveRulesIterator, FontFaceRule,
69 FontFeatureValuesRule, FontPaletteValuesRule, Origin, OriginSet, PagePseudoClassFlags,
70 PageRule, PerOrigin, PerOriginIter, PositionTryRule, StylesheetContents, StylesheetInDocument,
71 ViewTransitionRule,
72};
73use crate::stylesheets::{CustomMediaEvaluator, CustomMediaMap};
74#[cfg(feature = "gecko")]
75use crate::values::specified::position::PositionTryFallbacksItem;
76use crate::values::specified::position::PositionTryFallbacksTryTactic;
77use crate::values::{AtomIdent, Parser, SourceLocation, computed};
78use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
79use dom::{DocumentState, ElementState};
80#[cfg(feature = "gecko")]
81use malloc_size_of::MallocUnconditionalShallowSizeOf;
82use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
83use selectors::attr::{CaseSensitivity, NamespaceConstraint};
84use selectors::bloom::BloomFilter;
85use selectors::matching::{
86 MatchingContext, MatchingMode, NeedsSelectorFlags, SelectorCaches, SubjectOrPseudoElement,
87 matches_complex_selector, matches_selector, selector_may_match,
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 hashbrown::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, Default)]
678enum ScopeMatchesShadowHost {
679 #[default]
680 NotApplicable,
681 No,
682 Yes,
683}
684
685impl ScopeMatchesShadowHost {
686 fn nest_for_scope(&mut self, matches_shadow_host: bool) {
687 match *self {
688 Self::NotApplicable => {
689 *self = if matches_shadow_host {
691 Self::Yes
692 } else {
693 Self::No
694 };
695 },
696 Self::Yes if !matches_shadow_host => {
697 *self = Self::No;
699 },
700 _ => (),
701 }
702 }
703}
704
705#[derive(Copy, Clone)]
712enum NestedDeclarationsContext {
713 Style,
714 Scope,
715}
716
717struct ContainingScopeRuleState {
719 id: ScopeConditionId,
720 inner_dependencies: Vec<Dependency>,
721 matches_shadow_host: ScopeMatchesShadowHost,
722}
723
724impl Default for ContainingScopeRuleState {
725 fn default() -> Self {
726 Self {
727 id: ScopeConditionId::none(),
728 inner_dependencies: Vec::new(),
729 matches_shadow_host: Default::default(),
730 }
731 }
732}
733
734impl ContainingScopeRuleState {
735 fn save(&self) -> SavedContainingScopeRuleState {
736 SavedContainingScopeRuleState {
737 id: self.id,
738 matches_shadow_host: self.matches_shadow_host,
739 inner_dependencies_len: self.inner_dependencies.len(),
740 }
741 }
742
743 fn restore(
744 &mut self,
745 saved: &SavedContainingScopeRuleState,
746 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
747 debug_assert!(self.inner_dependencies.len() >= saved.inner_dependencies_len);
748
749 if self.id == saved.id {
750 return None;
751 }
752
753 let scope_id = self.id;
754 let inner_deps = self
755 .inner_dependencies
756 .drain(saved.inner_dependencies_len..)
757 .collect();
758
759 self.id = saved.id;
760 self.matches_shadow_host = saved.matches_shadow_host;
761
762 Some((inner_deps, scope_id))
763 }
764}
765
766struct SavedContainingScopeRuleState {
767 id: ScopeConditionId,
768 matches_shadow_host: ScopeMatchesShadowHost,
769 inner_dependencies_len: usize,
770}
771
772struct ContainingRuleState {
775 layer_name: LayerName,
776 layer_id: LayerId,
777 container_condition_id: ContainerConditionId,
778 cascade_flags: RuleCascadeFlags,
779 containing_scope_rule_state: ContainingScopeRuleState,
780 ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
781 nested_declarations_context: NestedDeclarationsContext,
782}
783
784impl Default for ContainingRuleState {
785 fn default() -> Self {
786 Self {
787 layer_name: LayerName::new_empty(),
788 layer_id: LayerId::root(),
789 container_condition_id: ContainerConditionId::none(),
790 cascade_flags: RuleCascadeFlags::empty(),
791 ancestor_selector_lists: Default::default(),
792 containing_scope_rule_state: Default::default(),
793 nested_declarations_context: NestedDeclarationsContext::Style,
794 }
795 }
796}
797
798struct SavedContainingRuleState {
799 ancestor_selector_lists_len: usize,
800 layer_name_len: usize,
801 layer_id: LayerId,
802 container_condition_id: ContainerConditionId,
803 cascade_flags: RuleCascadeFlags,
804 saved_containing_scope_rule_state: SavedContainingScopeRuleState,
805 nested_declarations_context: NestedDeclarationsContext,
806}
807
808impl ContainingRuleState {
809 fn save(&self) -> SavedContainingRuleState {
810 SavedContainingRuleState {
811 ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
812 layer_name_len: self.layer_name.0.len(),
813 layer_id: self.layer_id,
814 container_condition_id: self.container_condition_id,
815 cascade_flags: self.cascade_flags,
816 saved_containing_scope_rule_state: self.containing_scope_rule_state.save(),
817 nested_declarations_context: self.nested_declarations_context,
818 }
819 }
820
821 fn restore(
822 &mut self,
823 saved: &SavedContainingRuleState,
824 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
825 debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
826 debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
827
828 self.ancestor_selector_lists
829 .truncate(saved.ancestor_selector_lists_len);
830 self.layer_name.0.truncate(saved.layer_name_len);
831 self.layer_id = saved.layer_id;
832 self.container_condition_id = saved.container_condition_id;
833 self.cascade_flags = saved.cascade_flags;
834 self.nested_declarations_context = saved.nested_declarations_context;
835
836 self.containing_scope_rule_state
837 .restore(&saved.saved_containing_scope_rule_state)
838 }
839
840 fn scope_is_effective(&self) -> bool {
841 self.containing_scope_rule_state.id != ScopeConditionId::none()
842 }
843
844 fn cascade_flags(&self) -> RuleCascadeFlags {
845 self.cascade_flags
846 }
847}
848
849type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
850
851impl Stylist {
852 #[inline]
856 pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
857 Self {
858 device,
859 quirks_mode,
860 stylesheets: StylistStylesheetSet::new(),
861 author_data_cache: CascadeDataCache::new(),
862 cascade_data: Default::default(),
863 author_styles_enabled: AuthorStylesEnabled::Yes,
864 rule_tree: RuleTree::new(),
865 script_custom_properties: Default::default(),
866 initial_values_for_custom_properties: Default::default(),
867 initial_values_for_custom_properties_flags: Default::default(),
868 num_rebuilds: 0,
869 }
870 }
871
872 #[inline]
874 pub fn cascade_data(&self) -> &DocumentCascadeData {
875 &self.cascade_data
876 }
877
878 #[inline]
880 pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
881 self.author_styles_enabled
882 }
883
884 #[inline]
886 pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
887 self.cascade_data.iter_origins()
888 }
889
890 pub fn remove_unique_author_data_cache_entries(&mut self) {
893 self.author_data_cache.take_unused();
894 }
895
896 pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyDescriptors {
899 if let Some(registration) = self.custom_property_script_registry().get(name) {
900 return ®istration.descriptors;
901 }
902 for (data, _) in self.iter_origins() {
903 if let Some(registration) = data.custom_property_registrations.get(name) {
904 return ®istration.descriptors;
905 }
906 }
907 PropertyDescriptors::unregistered()
908 }
909
910 pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
912 &self.initial_values_for_custom_properties
913 }
914
915 pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
917 self.initial_values_for_custom_properties_flags
918 }
919
920 pub fn rebuild_initial_values_for_custom_properties(&mut self) {
923 let mut initial_values = ComputedCustomProperties::default();
924 let initial_values_flags;
925 {
926 let mut seen_names = PrecomputedHashSet::default();
927 let mut rule_cache_conditions = RuleCacheConditions::default();
928 let mut tree_counting_caches = TreeCountingCaches::default();
929 let context = computed::Context::new_for_initial_at_property_value(
930 self,
931 &mut rule_cache_conditions,
932 &mut tree_counting_caches,
933 );
934
935 for (k, v) in self.custom_property_script_registry().properties().iter() {
936 seen_names.insert(k.clone());
937 let Ok(value) = v.compute_initial_value(&context) else {
938 continue;
939 };
940 let map = if v.descriptors.inherits() {
941 &mut initial_values.inherited
942 } else {
943 &mut initial_values.non_inherited
944 };
945 map.insert(k, value);
946 }
947 for (data, _) in self.iter_origins() {
948 for (k, v) in data.custom_property_registrations.iter() {
949 if seen_names.insert(k.clone()) {
950 let last_value = &v.last().unwrap().0;
951 let Ok(value) = last_value.compute_initial_value(&context) else {
952 continue;
953 };
954 let map = if last_value.descriptors.inherits() {
955 &mut initial_values.inherited
956 } else {
957 &mut initial_values.non_inherited
958 };
959 map.insert(k, value);
960 }
961 }
962 }
963 initial_values_flags = context.builder.flags();
964 }
965 self.initial_values_for_custom_properties_flags = initial_values_flags;
966 self.initial_values_for_custom_properties = initial_values;
967 }
968
969 pub fn rebuild_author_data<S>(
971 &mut self,
972 old_data: &CascadeData,
973 collection: SheetCollectionFlusher<S>,
974 guard: &SharedRwLockReadGuard,
975 difference: &mut CascadeDataDifference,
976 ) -> Result<Option<Arc<CascadeData>>, AllocErr>
977 where
978 S: StylesheetInDocument + PartialEq + 'static,
979 {
980 self.author_data_cache.lookup(
981 &self.device,
982 self.quirks_mode,
983 collection,
984 guard,
985 old_data,
986 difference,
987 )
988 }
989
990 #[inline]
992 pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
993 ExtraStyleDataIterator(self.cascade_data.iter_origins())
994 }
995
996 #[inline]
998 pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
999 ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
1000 }
1001
1002 pub fn num_selectors(&self) -> usize {
1004 self.cascade_data
1005 .iter_origins()
1006 .map(|(d, _)| d.num_selectors)
1007 .sum()
1008 }
1009
1010 pub fn num_declarations(&self) -> usize {
1012 self.cascade_data
1013 .iter_origins()
1014 .map(|(d, _)| d.num_declarations)
1015 .sum()
1016 }
1017
1018 pub fn num_rebuilds(&self) -> usize {
1020 self.num_rebuilds
1021 }
1022
1023 pub fn num_revalidation_selectors(&self) -> usize {
1025 self.cascade_data
1026 .iter_origins()
1027 .map(|(data, _)| data.selectors_for_cache_revalidation.len())
1028 .sum()
1029 }
1030
1031 pub fn num_invalidations(&self) -> usize {
1033 self.cascade_data
1034 .iter_origins()
1035 .map(|(data, _)| {
1036 data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
1037 })
1038 .sum()
1039 }
1040
1041 pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
1044 self.cascade_data
1045 .iter_origins()
1046 .any(|(d, _)| d.document_state_dependencies.intersects(state))
1047 }
1048
1049 pub fn flush(&mut self, guards: &StylesheetGuards) -> StylesheetInvalidationSet {
1052 if !self.stylesheets.has_changed() {
1053 return Default::default();
1054 }
1055
1056 self.num_rebuilds += 1;
1057
1058 let cascade_data = &self.cascade_data;
1059 let (flusher, mut invalidations) = self.stylesheets.flush(&self.device, guards, |origin| {
1060 &cascade_data.borrow_for_origin(origin).custom_media
1061 });
1062
1063 self.cascade_data
1064 .rebuild(
1065 &self.device,
1066 self.quirks_mode,
1067 flusher,
1068 guards,
1069 &mut invalidations.cascade_data_difference,
1070 )
1071 .unwrap_or_else(|_| {
1072 warn!("OOM in Stylist::flush");
1073 });
1074
1075 self.rebuild_initial_values_for_custom_properties();
1076 invalidations
1077 }
1078
1079 pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
1085 self.stylesheets.force_dirty(origins)
1086 }
1087
1088 pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
1090 self.author_styles_enabled = enabled;
1091 }
1092
1093 pub fn stylesheets_have_changed(&self) -> bool {
1095 self.stylesheets.has_changed()
1096 }
1097
1098 pub fn insert_stylesheet_before(
1100 &mut self,
1101 sheet: StylistSheet,
1102 before_sheet: StylistSheet,
1103 guard: &SharedRwLockReadGuard,
1104 ) {
1105 self.stylesheets
1106 .insert_stylesheet_before(sheet, before_sheet, guard)
1107 }
1108
1109 pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1111 self.stylesheets.append_stylesheet(sheet, guard)
1112 }
1113
1114 pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1116 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1117 self.stylesheets
1118 .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
1119 }
1120
1121 pub fn rule_changed(
1123 &mut self,
1124 sheet: &StylistSheet,
1125 rule: &CssRule,
1126 guard: &SharedRwLockReadGuard,
1127 change_kind: RuleChangeKind,
1128 ancestors: &[CssRuleRef],
1129 ) {
1130 let custom_media = self.cascade_data.custom_media_for_sheet(sheet, guard);
1131 self.stylesheets.rule_changed(
1132 Some(&self.device),
1133 custom_media,
1134 sheet,
1135 rule,
1136 guard,
1137 change_kind,
1138 ancestors,
1139 )
1140 }
1141
1142 #[inline]
1144 pub fn sheet_count(&self, origin: Origin) -> usize {
1145 self.stylesheets.sheet_count(origin)
1146 }
1147
1148 #[inline]
1150 pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
1151 self.stylesheets.get(origin, index)
1152 }
1153
1154 pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
1157 where
1158 E: TElement,
1159 F: FnMut(&CascadeData) -> bool,
1160 {
1161 if f(&self.cascade_data.user_agent.cascade_data) {
1162 return true;
1163 }
1164
1165 let mut maybe = false;
1166
1167 let doc_author_rules_apply =
1168 element.each_applicable_non_document_style_rule_data(|data, _| {
1169 maybe = maybe || f(data);
1170 });
1171
1172 if maybe || f(&self.cascade_data.user) {
1173 return true;
1174 }
1175
1176 doc_author_rules_apply && f(&self.cascade_data.author)
1177 }
1178
1179 pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1181 where
1182 E: TElement + 'a,
1183 F: FnMut(&'a CascadeData, Option<E>),
1184 {
1185 f(&self.cascade_data.user_agent.cascade_data, None);
1186 element.each_applicable_non_document_style_rule_data(|data, scope| {
1187 f(data, Some(scope));
1188 });
1189 f(&self.cascade_data.user, None);
1190 f(&self.cascade_data.author, None);
1191 }
1192
1193 pub fn precomputed_values_for_pseudo<E>(
1196 &self,
1197 guards: &StylesheetGuards,
1198 pseudo: &PseudoElement,
1199 parent: Option<&ComputedValues>,
1200 ) -> Arc<ComputedValues>
1201 where
1202 E: TElement,
1203 {
1204 debug_assert!(pseudo.is_precomputed());
1205
1206 let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1207
1208 self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1209 }
1210
1211 pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1217 &self,
1218 guards: &StylesheetGuards,
1219 pseudo: &PseudoElement,
1220 parent: Option<&ComputedValues>,
1221 rules: StrongRuleNode,
1222 ) -> Arc<ComputedValues>
1223 where
1224 E: TElement,
1225 {
1226 self.compute_pseudo_element_style_with_inputs::<E>(
1227 CascadeInputs {
1228 rules: Some(rules),
1229 visited_rules: None,
1230 flags: Default::default(),
1231 included_cascade_flags: RuleCascadeFlags::empty(),
1232 },
1233 pseudo,
1234 guards,
1235 parent,
1236 None,
1237 )
1238 }
1239
1240 pub fn rule_node_for_precomputed_pseudo(
1246 &self,
1247 guards: &StylesheetGuards,
1248 pseudo: &PseudoElement,
1249 mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1250 ) -> StrongRuleNode {
1251 let mut declarations_with_extra;
1252 let declarations = match self
1253 .cascade_data
1254 .user_agent
1255 .precomputed_pseudo_element_decls
1256 .get(pseudo)
1257 {
1258 Some(declarations) => {
1259 if !extra_declarations.is_empty() {
1260 declarations_with_extra = declarations.clone();
1261 declarations_with_extra.append(&mut extra_declarations);
1262 &*declarations_with_extra
1263 } else {
1264 &**declarations
1265 }
1266 },
1267 None => &[],
1268 };
1269
1270 self.rule_tree.insert_ordered_rules_with_important(
1271 declarations.iter().map(|a| a.clone().for_rule_tree()),
1272 guards,
1273 )
1274 }
1275
1276 #[cfg(feature = "servo")]
1281 pub fn style_for_anonymous<E>(
1282 &self,
1283 guards: &StylesheetGuards,
1284 pseudo: &PseudoElement,
1285 parent_style: &ComputedValues,
1286 ) -> Arc<ComputedValues>
1287 where
1288 E: TElement,
1289 {
1290 self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1291 }
1292
1293 pub fn lazily_compute_pseudo_element_style<E>(
1301 &self,
1302 guards: &StylesheetGuards,
1303 element: E,
1304 pseudo: &PseudoElement,
1305 rule_inclusion: RuleInclusion,
1306 originating_element_style: &ComputedValues,
1307 is_probe: bool,
1308 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1309 ) -> Option<Arc<ComputedValues>>
1310 where
1311 E: TElement,
1312 {
1313 let cascade_inputs = self.lazy_pseudo_rules(
1314 guards,
1315 element,
1316 originating_element_style,
1317 pseudo,
1318 is_probe,
1319 rule_inclusion,
1320 matching_fn,
1321 )?;
1322
1323 Some(self.compute_pseudo_element_style_with_inputs(
1324 cascade_inputs,
1325 pseudo,
1326 guards,
1327 Some(originating_element_style),
1328 Some(element),
1329 ))
1330 }
1331
1332 pub fn compute_pseudo_element_style_with_inputs<E>(
1337 &self,
1338 inputs: CascadeInputs,
1339 pseudo: &PseudoElement,
1340 guards: &StylesheetGuards,
1341 parent_style: Option<&ComputedValues>,
1342 element: Option<E>,
1343 ) -> Arc<ComputedValues>
1344 where
1345 E: TElement,
1346 {
1347 self.cascade_style_and_visited(
1360 element,
1361 Some(pseudo),
1362 &inputs,
1363 guards,
1364 parent_style,
1365 parent_style,
1366 FirstLineReparenting::No,
1367 &PositionTryFallbacksTryTactic::default(),
1368 None,
1369 &mut RuleCacheConditions::default(),
1370 &mut TreeCountingCaches::default(),
1371 )
1372 }
1373
1374 #[cfg(feature = "gecko")]
1376 pub fn resolve_position_try<E>(
1377 &self,
1378 style: &ComputedValues,
1379 guards: &StylesheetGuards,
1380 scope: CascadeLevel,
1381 element: E,
1382 fallback_item: &PositionTryFallbacksItem,
1383 ) -> Option<Arc<ComputedValues>>
1384 where
1385 E: TElement,
1386 {
1387 let name_and_try_tactic = match *fallback_item {
1388 PositionTryFallbacksItem::PositionArea(area) => {
1389 let mut builder =
1393 StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
1394 builder.rules = style.rules.clone();
1395 builder.mutate_position().set_position_area(area);
1396 return Some(builder.build());
1397 },
1398 PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
1399 name_and_try_tactic
1400 },
1401 };
1402
1403 let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
1404 Some(self.lookup_position_try(&name_and_try_tactic.ident.0, scope, element)?)
1405 } else {
1406 None
1407 };
1408 let fallback_block = fallback_rule
1409 .as_ref()
1410 .map(|r| &r.read_with(guards.author).block);
1411 let pseudo = style
1412 .pseudo()
1413 .or_else(|| element.implemented_pseudo_element());
1414 let inputs = {
1415 let mut inputs = CascadeInputs::new_from_style(style);
1416 inputs.visited_rules = None;
1418 let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
1419 let mut important_rules_changed = false;
1420 if let Some(fallback_block) = fallback_block {
1421 let new_rules = self.rule_tree.update_rule_at_level(
1422 CascadeLevel::new(CascadeOrigin::PositionFallback),
1423 LayerOrder::root(),
1424 Some(fallback_block.borrow_arc()),
1425 rules,
1426 guards,
1427 &mut important_rules_changed,
1428 );
1429 if new_rules.is_some() {
1430 inputs.rules = new_rules;
1431 } else {
1432 }
1436 }
1437 inputs
1438 };
1439 crate::style_resolver::with_default_parent_styles(
1440 element,
1441 |parent_style, layout_parent_style| {
1442 Some(self.cascade_style_and_visited(
1443 Some(element),
1444 pseudo.as_ref(),
1445 &inputs,
1446 guards,
1447 parent_style,
1448 layout_parent_style,
1449 FirstLineReparenting::No,
1450 &name_and_try_tactic.try_tactic,
1451 None,
1452 &mut RuleCacheConditions::default(),
1453 &mut TreeCountingCaches::default(),
1454 ))
1455 },
1456 )
1457 }
1458
1459 pub fn cascade_style_and_visited<E>(
1472 &self,
1473 element: Option<E>,
1474 pseudo: Option<&PseudoElement>,
1475 inputs: &CascadeInputs,
1476 guards: &StylesheetGuards,
1477 parent_style: Option<&ComputedValues>,
1478 layout_parent_style: Option<&ComputedValues>,
1479 first_line_reparenting: FirstLineReparenting,
1480 try_tactic: &PositionTryFallbacksTryTactic,
1481 rule_cache: Option<&RuleCache>,
1482 rule_cache_conditions: &mut RuleCacheConditions,
1483 tree_counting_caches: &mut TreeCountingCaches,
1484 ) -> Arc<ComputedValues>
1485 where
1486 E: TElement,
1487 {
1488 debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1489
1490 let visited_rules = match inputs.visited_rules.as_ref() {
1493 Some(rules) => Some(rules),
1494 None => {
1495 if parent_style.and_then(|s| s.visited_style()).is_some() {
1496 Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1497 } else {
1498 None
1499 }
1500 },
1501 };
1502
1503 let mut implemented_pseudo = None;
1504 properties::cascade::<E>(
1511 self,
1512 pseudo.or_else(|| {
1513 implemented_pseudo = element.unwrap().implemented_pseudo_element();
1514 implemented_pseudo.as_ref()
1515 }),
1516 inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1517 guards,
1518 parent_style,
1519 layout_parent_style,
1520 first_line_reparenting,
1521 try_tactic,
1522 visited_rules,
1523 inputs.flags,
1524 inputs.included_cascade_flags,
1525 rule_cache,
1526 rule_cache_conditions,
1527 element,
1528 tree_counting_caches,
1529 )
1530 }
1531
1532 fn lazy_pseudo_rules<E>(
1537 &self,
1538 guards: &StylesheetGuards,
1539 element: E,
1540 originating_element_style: &ComputedValues,
1541 pseudo: &PseudoElement,
1542 is_probe: bool,
1543 rule_inclusion: RuleInclusion,
1544 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1545 ) -> Option<CascadeInputs>
1546 where
1547 E: TElement,
1548 {
1549 debug_assert!(pseudo.is_lazy());
1550
1551 let mut selector_caches = SelectorCaches::default();
1552 let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1555 NeedsSelectorFlags::No
1556 } else {
1557 NeedsSelectorFlags::Yes
1558 };
1559
1560 let mut declarations = ApplicableDeclarationList::new();
1561 let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1562 MatchingMode::ForStatelessPseudoElement,
1563 None,
1564 &mut selector_caches,
1565 self.quirks_mode,
1566 needs_selector_flags,
1567 MatchingForInvalidation::No,
1568 );
1569
1570 matching_context.pseudo_element_matching_fn = matching_fn;
1571 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1572
1573 self.push_applicable_declarations(
1574 element,
1575 Some(pseudo),
1576 None,
1577 None,
1578 Default::default(),
1579 rule_inclusion,
1580 &mut declarations,
1581 &mut matching_context,
1582 );
1583
1584 if declarations.is_empty() && is_probe {
1585 return None;
1586 }
1587
1588 let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1589
1590 let mut visited_rules = None;
1591 if originating_element_style.visited_style().is_some() {
1592 let mut declarations = ApplicableDeclarationList::new();
1593 let mut selector_caches = SelectorCaches::default();
1594
1595 let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1596 MatchingMode::ForStatelessPseudoElement,
1597 None,
1598 &mut selector_caches,
1599 VisitedHandlingMode::RelevantLinkVisited,
1600 self.quirks_mode,
1601 needs_selector_flags,
1602 MatchingForInvalidation::No,
1603 );
1604 matching_context.pseudo_element_matching_fn = matching_fn;
1605 matching_context.extra_data.originating_element_style = Some(originating_element_style);
1606
1607 self.push_applicable_declarations(
1608 element,
1609 Some(pseudo),
1610 None,
1611 None,
1612 Default::default(),
1613 rule_inclusion,
1614 &mut declarations,
1615 &mut matching_context,
1616 );
1617 if !declarations.is_empty() {
1618 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1619 declarations.drain(..).map(|a| a.for_rule_tree()),
1620 guards,
1621 );
1622 if rule_node != *self.rule_tree.root() {
1623 visited_rules = Some(rule_node);
1624 }
1625 }
1626 }
1627
1628 Some(CascadeInputs {
1629 rules: Some(rules),
1630 visited_rules,
1631 flags: matching_context.extra_data.cascade_input_flags,
1632 included_cascade_flags: RuleCascadeFlags::empty(),
1633 })
1634 }
1635
1636 pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1647 self.device = device;
1648 self.media_features_change_changed_style(guards, &self.device)
1649 }
1650
1651 pub fn media_features_change_changed_style(
1655 &self,
1656 guards: &StylesheetGuards,
1657 device: &Device,
1658 ) -> OriginSet {
1659 debug!("Stylist::media_features_change_changed_style {:?}", device);
1660
1661 let mut origins = OriginSet::empty();
1662 let stylesheets = self.stylesheets.iter();
1663
1664 for (stylesheet, origin) in stylesheets {
1665 if origins.contains(origin.into()) {
1666 continue;
1667 }
1668
1669 let guard = guards.for_origin(origin);
1670 let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1671
1672 let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1673 stylesheet,
1674 guard,
1675 device,
1676 self.quirks_mode,
1677 );
1678
1679 if affected_changed {
1680 origins |= origin;
1681 }
1682 }
1683
1684 origins
1685 }
1686
1687 pub fn quirks_mode(&self) -> QuirksMode {
1689 self.quirks_mode
1690 }
1691
1692 pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1694 if self.quirks_mode == quirks_mode {
1695 return;
1696 }
1697 self.quirks_mode = quirks_mode;
1698 self.force_stylesheet_origins_dirty(OriginSet::all());
1699 }
1700
1701 pub fn push_applicable_declarations<E>(
1703 &self,
1704 element: E,
1705 pseudo_element: Option<&PseudoElement>,
1706 style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1707 smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1708 animation_declarations: AnimationDeclarations,
1709 rule_inclusion: RuleInclusion,
1710 applicable_declarations: &mut ApplicableDeclarationList,
1711 context: &mut MatchingContext<E::Impl>,
1712 ) where
1713 E: TElement,
1714 {
1715 let mut cur = element;
1716 let mut pseudos = SmallVec::<[_; 2]>::new();
1717 if let Some(pseudo) = pseudo_element {
1718 pseudos.push(pseudo.clone());
1719 }
1720 while let Some(p) = cur.implemented_pseudo_element() {
1721 pseudos.push(p);
1722 let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
1723 break;
1724 };
1725 cur = parent_pseudo;
1726 }
1727 RuleCollector::new(
1728 self,
1729 element,
1730 cur,
1731 &pseudos,
1732 style_attribute,
1733 smil_override,
1734 animation_declarations,
1735 rule_inclusion,
1736 applicable_declarations,
1737 context,
1738 )
1739 .collect_all();
1740 }
1741
1742 #[inline]
1745 pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1746 where
1747 E: TElement,
1748 {
1749 match self.quirks_mode().classes_and_ids_case_sensitivity() {
1752 CaseSensitivity::AsciiCaseInsensitive => return true,
1753 CaseSensitivity::CaseSensitive => {},
1754 }
1755
1756 self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1757 }
1758
1759 #[inline]
1767 fn lookup_element_dependent_at_rule<'a, T, F, E>(
1768 &'a self,
1769 element: E,
1770 find_in: F,
1771 ) -> Option<&'a T>
1772 where
1773 E: TElement + 'a,
1774 F: Fn(&'a CascadeData) -> Option<&'a T>,
1775 {
1776 macro_rules! try_find_in {
1777 ($data:expr) => {
1778 if let Some(thing) = find_in(&$data) {
1779 return Some(thing);
1780 }
1781 };
1782 }
1783
1784 let mut result = None;
1785 let doc_rules_apply =
1786 element.each_applicable_non_document_style_rule_data(|data, _host| {
1787 if result.is_none() {
1788 result = find_in(data);
1789 }
1790 });
1791
1792 if result.is_some() {
1793 return result;
1794 }
1795
1796 if doc_rules_apply {
1797 try_find_in!(self.cascade_data.author);
1798 }
1799 try_find_in!(self.cascade_data.user);
1800 try_find_in!(self.cascade_data.user_agent.cascade_data);
1801
1802 None
1803 }
1804
1805 #[inline]
1807 pub fn lookup_keyframes<'a, E>(
1808 &'a self,
1809 name: &Atom,
1810 element: E,
1811 ) -> Option<&'a KeyframesAnimation>
1812 where
1813 E: TElement + 'a,
1814 {
1815 self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1816 }
1817
1818 #[inline]
1821 pub fn last_view_transition_rule(&self) -> Option<&Arc<ViewTransitionRule>> {
1822 self.iter_extra_data_origins()
1824 .flat_map(|(d, _)| d.view_transitions.iter())
1825 .last()
1826 .map(|(rule, _)| rule)
1827 }
1828
1829 #[inline]
1831 #[cfg(feature = "gecko")]
1832 fn lookup_position_try<'a, E>(
1833 &'a self,
1834 name: &Atom,
1835 scope: CascadeLevel,
1836 element: E,
1837 ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1838 where
1839 E: TElement + 'a,
1840 {
1841 let mut shadow_root = scope.get_shadow_root_for_scoped(element);
1842 while let Some(r) = shadow_root {
1845 if let Some(rule) = r
1846 .style_data()
1847 .and_then(|data| data.extra_data.position_try_rules.get(name))
1848 {
1849 return Some(rule);
1850 }
1851 shadow_root = r.host().containing_shadow();
1853 }
1854
1855 for (data, _) in self.iter_extra_data_origins() {
1856 if let Some(r) = data.position_try_rules.get(name) {
1857 return Some(r);
1858 }
1859 }
1860 None
1861 }
1862
1863 pub fn match_revalidation_selectors<E>(
1866 &self,
1867 element: E,
1868 bloom: Option<&BloomFilter>,
1869 selector_caches: &mut SelectorCaches,
1870 needs_selector_flags: NeedsSelectorFlags,
1871 ) -> RevalidationResult
1872 where
1873 E: TElement,
1874 {
1875 let mut matching_context = MatchingContext::new_for_revalidation(
1876 bloom,
1877 selector_caches,
1878 self.quirks_mode,
1879 needs_selector_flags,
1880 );
1881
1882 let mut result = RevalidationResult::default();
1888 let mut relevant_attributes = &mut result.relevant_attributes;
1889 let selectors_matched = &mut result.selectors_matched;
1890
1891 let matches_document_rules =
1892 element.each_applicable_non_document_style_rule_data(|data, host| {
1893 matching_context.with_shadow_host(Some(host), |matching_context| {
1894 data.selectors_for_cache_revalidation.lookup(
1895 element,
1896 self.quirks_mode,
1897 Some(&mut relevant_attributes),
1898 |selector_and_hashes| {
1899 selectors_matched.push(matches_selector(
1900 &selector_and_hashes.selector,
1901 selector_and_hashes.selector_offset,
1902 Some(&selector_and_hashes.hashes),
1903 element,
1904 matching_context,
1905 ));
1906 true
1907 },
1908 );
1909 })
1910 });
1911
1912 for (data, origin) in self.cascade_data.iter_origins() {
1913 if origin == Origin::Author && !matches_document_rules {
1914 continue;
1915 }
1916
1917 data.selectors_for_cache_revalidation.lookup(
1918 element,
1919 self.quirks_mode,
1920 Some(&mut relevant_attributes),
1921 |selector_and_hashes| {
1922 selectors_matched.push(matches_selector(
1923 &selector_and_hashes.selector,
1924 selector_and_hashes.selector_offset,
1925 Some(&selector_and_hashes.hashes),
1926 element,
1927 &mut matching_context,
1928 ));
1929 true
1930 },
1931 );
1932 }
1933
1934 result
1935 }
1936
1937 pub fn revalidate_scopes<E: TElement>(
1939 &self,
1940 element: &E,
1941 selector_caches: &mut SelectorCaches,
1942 needs_selector_flags: NeedsSelectorFlags,
1943 ) -> ScopeRevalidationResult {
1944 let mut matching_context = MatchingContext::new(
1945 MatchingMode::Normal,
1946 None,
1947 selector_caches,
1948 self.quirks_mode,
1949 needs_selector_flags,
1950 MatchingForInvalidation::No,
1951 );
1952
1953 let mut result = ScopeRevalidationResult::default();
1954 let matches_document_rules =
1955 element.each_applicable_non_document_style_rule_data(|data, host| {
1956 matching_context.with_shadow_host(Some(host), |matching_context| {
1957 data.revalidate_scopes(element, matching_context, &mut result);
1958 })
1959 });
1960
1961 for (data, origin) in self.cascade_data.iter_origins() {
1962 if origin == Origin::Author && !matches_document_rules {
1963 continue;
1964 }
1965
1966 data.revalidate_scopes(element, &mut matching_context, &mut result);
1967 }
1968
1969 result
1970 }
1971
1972 pub fn compute_for_declarations<E>(
1980 &self,
1981 guards: &StylesheetGuards,
1982 parent_style: &ComputedValues,
1983 declarations: Arc<Locked<PropertyDeclarationBlock>>,
1984 ) -> Arc<ComputedValues>
1985 where
1986 E: TElement,
1987 {
1988 let block = declarations.read_with(guards.author);
1989
1990 properties::apply_declarations::<E, _>(
1997 self,
1998 None,
1999 self.rule_tree.root(),
2000 guards,
2001 block.declaration_importance_iter().map(|(declaration, _)| {
2002 (
2003 declaration,
2004 CascadePriority::new(
2005 CascadeLevel::same_tree_author_normal(),
2006 LayerOrder::root(),
2007 RuleCascadeFlags::empty(),
2008 ),
2009 )
2010 }),
2011 Some(parent_style),
2012 Some(parent_style),
2013 FirstLineReparenting::No,
2014 &PositionTryFallbacksTryTactic::default(),
2015 CascadeMode::Unvisited {
2016 visited_rules: None,
2017 },
2018 Default::default(),
2019 RuleCascadeFlags::empty(),
2020 None,
2021 &mut Default::default(),
2022 None,
2023 &mut TreeCountingCaches::default(),
2024 )
2025 }
2026
2027 #[inline]
2029 pub fn device(&self) -> &Device {
2030 &self.device
2031 }
2032
2033 #[inline]
2035 pub fn device_mut(&mut self) -> &mut Device {
2036 &mut self.device
2037 }
2038
2039 #[inline]
2041 pub fn rule_tree(&self) -> &RuleTree {
2042 &self.rule_tree
2043 }
2044
2045 #[inline]
2047 pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
2048 &self.script_custom_properties
2049 }
2050
2051 #[inline]
2053 pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2054 &mut self.script_custom_properties
2055 }
2056
2057 #[cfg(feature = "gecko")]
2059 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2060 self.cascade_data.add_size_of(ops, sizes);
2061 self.author_data_cache.add_size_of(ops, sizes);
2062 sizes.mRuleTree += self.rule_tree.size_of(ops);
2063
2064 }
2066
2067 pub fn shutdown() {
2069 let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2070 }
2071}
2072
2073#[allow(missing_docs)]
2074#[repr(u8)]
2075pub enum RegisterCustomPropertyResult {
2076 SuccessfullyRegistered,
2077 InvalidName,
2078 AlreadyRegistered,
2079 InvalidSyntax,
2080 NoInitialValue,
2081 InvalidInitialValue,
2082 InitialValueNotComputationallyIndependent,
2083}
2084
2085impl Stylist {
2086 pub fn register_custom_property(
2088 &mut self,
2089 url_data: &UrlExtraData,
2090 name: &str,
2091 syntax: &str,
2092 inherits: bool,
2093 initial_value: Option<&str>,
2094 ) -> RegisterCustomPropertyResult {
2095 use RegisterCustomPropertyResult::*;
2096
2097 let Ok(name) = parse_name(name).map(Atom::from) else {
2099 return InvalidName;
2100 };
2101
2102 if self.custom_property_script_registry().get(&name).is_some() {
2105 return AlreadyRegistered;
2106 }
2107 let Ok(syntax) = Descriptor::from_str(syntax, false) else {
2110 return InvalidSyntax;
2111 };
2112
2113 let initial_value = match initial_value {
2114 Some(value) => {
2115 let parsed = Parser::new(value)
2116 .parse_entirely(|input| {
2117 input.skip_whitespace();
2118 SpecifiedValue::parse(input, None, url_data).map(Arc::new)
2119 })
2120 .ok();
2121 if parsed.is_none() {
2122 return InvalidInitialValue;
2123 }
2124 parsed
2125 },
2126 None => None,
2127 };
2128
2129 if let Err(error) = PropertyRegistration::validate_initial_value(
2130 PropertyIdRef::from(&name),
2131 &syntax,
2132 initial_value.as_deref(),
2133 ) {
2134 return match error {
2135 PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
2136 InitialValueNotComputationallyIndependent
2137 },
2138 PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
2139 PropertyRegistrationError::NoInitialValue => NoInitialValue,
2140 };
2141 }
2142
2143 let property_registration = PropertyRegistration {
2144 name: PropertyRuleName(name),
2145 descriptors: PropertyDescriptors {
2146 syntax: Some(syntax),
2147 inherits: Some(if inherits {
2148 Inherits::True
2149 } else {
2150 Inherits::False
2151 }),
2152 initial_value,
2153 },
2154 url_data: url_data.clone(),
2155 source_location: SourceLocation { line: 0, column: 0 },
2156 };
2157 self.custom_property_script_registry_mut()
2158 .register(property_registration);
2159 self.rebuild_initial_values_for_custom_properties();
2160
2161 SuccessfullyRegistered
2162 }
2163}
2164
2165#[derive(Clone, Debug, Deref, MallocSizeOf)]
2167pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2168impl<T> Default for LayerOrderedVec<T> {
2169 fn default() -> Self {
2170 Self(Default::default())
2171 }
2172}
2173
2174#[derive(Clone, Debug, Deref, MallocSizeOf)]
2176pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2177impl<T> Default for LayerOrderedMap<T> {
2178 fn default() -> Self {
2179 Self(Default::default())
2180 }
2181}
2182
2183impl<T: 'static> LayerOrderedVec<T> {
2184 fn clear(&mut self) {
2185 self.0.clear();
2186 }
2187 fn push(&mut self, v: T, id: LayerId) {
2188 self.0.push((v, id));
2189 }
2190 fn sort(&mut self, layers: &[CascadeLayer]) {
2191 self.0.sort_by_key(|(_, id)| layers[id.0 as usize].order)
2192 }
2193}
2194
2195impl<T: 'static> LayerOrderedMap<T> {
2196 fn shrink_if_needed(&mut self) {
2197 self.0.shrink_if_needed();
2198 }
2199 fn clear(&mut self) {
2200 self.0.clear();
2201 }
2202 fn try_insert(&mut self, name: &Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2203 self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2204 }
2205 fn try_insert_with(
2206 &mut self,
2207 name: &Atom,
2208 v: T,
2209 id: LayerId,
2210 cmp: impl Fn(&T, &T) -> Ordering,
2211 ) -> Result<(), AllocErr> {
2212 self.0.try_reserve(1)?;
2213 let vec = self.0.entry_ref(name).or_default();
2214 if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut()
2215 && *last_id == id
2216 {
2217 if cmp(val, &v) != Ordering::Greater {
2218 *val = v;
2219 }
2220 return Ok(());
2221 }
2222 vec.push((v, id));
2223 Ok(())
2224 }
2225 fn sort(&mut self, layers: &[CascadeLayer]) {
2226 self.sort_with(layers, |_, _| Ordering::Equal)
2227 }
2228 fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2229 for (_, v) in self.0.iter_mut() {
2230 v.sort_by(|(v1, id1), (v2, id2)| {
2231 let order1 = layers[id1.0 as usize].order;
2232 let order2 = layers[id2.0 as usize].order;
2233 order1.cmp(&order2).then_with(|| cmp(v1, v2))
2234 })
2235 }
2236 }
2237 pub fn get(&self, name: &Atom) -> Option<&T> {
2239 let vec = self.0.get(name)?;
2240 Some(&vec.last()?.0)
2241 }
2242}
2243
2244#[derive(Clone, Debug, MallocSizeOf)]
2248pub struct PageRuleData {
2249 pub layer: LayerId,
2251 #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2253 pub rule: Arc<Locked<PageRule>>,
2254}
2255
2256#[derive(Clone, Debug, Default, MallocSizeOf)]
2258pub struct PageRuleMap {
2259 pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2261}
2262
2263impl PageRuleMap {
2264 #[inline]
2265 fn clear(&mut self) {
2266 self.rules.clear();
2267 }
2268
2269 pub fn match_and_append_rules(
2273 &self,
2274 matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2275 origin: Origin,
2276 guards: &StylesheetGuards,
2277 cascade_data: &DocumentCascadeData,
2278 name: &Option<Atom>,
2279 pseudos: PagePseudoClassFlags,
2280 ) {
2281 let level = match origin {
2282 Origin::UserAgent => CascadeLevel::new(CascadeOrigin::UA),
2283 Origin::User => CascadeLevel::new(CascadeOrigin::User),
2284 Origin::Author => CascadeLevel::same_tree_author_normal(),
2285 };
2286 let cascade_data = cascade_data.borrow_for_origin(origin);
2287 let start = matched_rules.len();
2288
2289 self.match_and_add_rules(
2290 matched_rules,
2291 level,
2292 guards,
2293 cascade_data,
2294 &atom!(""),
2295 pseudos,
2296 );
2297 if let Some(name) = name {
2298 self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2299 }
2300
2301 matched_rules[start..].sort_by_key(|block| block.sort_key());
2304 }
2305
2306 fn match_and_add_rules(
2307 &self,
2308 extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2309 level: CascadeLevel,
2310 guards: &StylesheetGuards,
2311 cascade_data: &CascadeData,
2312 name: &Atom,
2313 pseudos: PagePseudoClassFlags,
2314 ) {
2315 let rules = match self.rules.get(name) {
2316 Some(rules) => rules,
2317 None => return,
2318 };
2319 for data in rules.iter() {
2320 let rule = data.rule.read_with(level.guard(guards));
2321 let specificity = match rule.match_specificity(pseudos) {
2322 Some(specificity) => specificity,
2323 None => continue,
2324 };
2325 let block = rule.block.clone();
2326 extra_declarations.push(ApplicableDeclarationBlock::new(
2327 StyleSource::from_declarations(block),
2328 0,
2329 level,
2330 specificity,
2331 cascade_data.layer_order_for(data.layer),
2332 ScopeProximity::infinity(), RuleCascadeFlags::empty(),
2334 ));
2335 }
2336 }
2337}
2338
2339impl MallocShallowSizeOf for PageRuleMap {
2340 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2341 self.rules.shallow_size_of(ops)
2342 }
2343}
2344
2345type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2346
2347#[derive(Clone, Debug, Default)]
2350pub struct ExtraStyleData {
2351 pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2353
2354 pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2356
2357 pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2359
2360 pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2362
2363 pub position_try_rules: PositionTryMap,
2365
2366 pub pages: PageRuleMap,
2368
2369 pub view_transitions: LayerOrderedVec<Arc<ViewTransitionRule>>,
2371}
2372
2373impl ExtraStyleData {
2374 fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2376 self.font_faces.push(rule.clone(), layer);
2377 }
2378
2379 fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2381 self.font_feature_values.push(rule.clone(), layer);
2382 }
2383
2384 fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2386 self.font_palette_values.push(rule.clone(), layer);
2387 }
2388
2389 fn add_counter_style(
2391 &mut self,
2392 guard: &SharedRwLockReadGuard,
2393 rule: &Arc<Locked<CounterStyleRule>>,
2394 layer: LayerId,
2395 ) -> Result<(), AllocErr> {
2396 let name = &rule.read_with(guard).name().0;
2397 self.counter_styles.try_insert(name, rule.clone(), layer)
2398 }
2399
2400 fn add_position_try(
2402 &mut self,
2403 name: Atom,
2404 rule: Arc<Locked<PositionTryRule>>,
2405 layer: LayerId,
2406 ) -> Result<(), AllocErr> {
2407 self.position_try_rules.try_insert(&name, rule, layer)
2408 }
2409
2410 fn add_page(
2412 &mut self,
2413 guard: &SharedRwLockReadGuard,
2414 rule: &Arc<Locked<PageRule>>,
2415 layer: LayerId,
2416 ) -> Result<(), AllocErr> {
2417 let page_rule = rule.read_with(guard);
2418 let mut add_rule = |name: &Atom| {
2419 let vec = self.pages.rules.entry_ref(name).or_default();
2420 vec.push(PageRuleData {
2421 layer,
2422 rule: rule.clone(),
2423 });
2424 };
2425 if page_rule.selectors.0.is_empty() {
2426 add_rule(&atom!(""));
2427 } else {
2428 for selector in page_rule.selectors.as_slice() {
2429 add_rule(&selector.name.0);
2430 }
2431 }
2432 Ok(())
2433 }
2434
2435 fn add_view_transition(&mut self, rule: &Arc<ViewTransitionRule>, layer: LayerId) {
2436 self.view_transitions.push(rule.clone(), layer)
2437 }
2438
2439 fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2440 self.font_faces.sort(layers);
2441 self.font_feature_values.sort(layers);
2442 self.font_palette_values.sort(layers);
2443 self.counter_styles.sort(layers);
2444 self.position_try_rules.sort(layers);
2445 self.view_transitions.sort(layers);
2446 }
2447
2448 fn clear(&mut self) {
2449 self.font_faces.clear();
2450 self.font_feature_values.clear();
2451 self.font_palette_values.clear();
2452 self.counter_styles.clear();
2453 self.position_try_rules.clear();
2454 self.pages.clear();
2455 }
2456}
2457
2458fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2461 if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2462 Ordering::Equal
2463 } else if v2.vendor_prefix.is_some() {
2464 Ordering::Greater
2465 } else {
2466 Ordering::Less
2467 }
2468}
2469
2470pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2472
2473impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2474 type Item = (&'a ExtraStyleData, Origin);
2475
2476 fn next(&mut self) -> Option<Self::Item> {
2477 self.0.next().map(|d| (&d.0.extra_data, d.1))
2478 }
2479}
2480
2481impl MallocSizeOf for ExtraStyleData {
2482 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2484 let mut n = 0;
2485 n += self.font_faces.shallow_size_of(ops);
2486 n += self.font_feature_values.shallow_size_of(ops);
2487 n += self.font_palette_values.shallow_size_of(ops);
2488 n += self.counter_styles.shallow_size_of(ops);
2489 n += self.position_try_rules.shallow_size_of(ops);
2490 n += self.pages.shallow_size_of(ops);
2491 n
2492 }
2493}
2494
2495#[derive(Clone, Debug, MallocSizeOf)]
2497struct RevalidationSelectorAndHashes {
2498 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
2499 selector: Selector<SelectorImpl>,
2500 selector_offset: usize,
2501 hashes: AncestorHashes,
2502}
2503
2504impl RevalidationSelectorAndHashes {
2505 fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2506 let selector_offset = {
2507 let mut index = 0;
2511 let mut iter = selector.iter();
2512
2513 for _ in &mut iter {
2518 index += 1; }
2520
2521 match iter.next_sequence() {
2522 Some(Combinator::PseudoElement) => index + 1, _ => 0,
2524 }
2525 };
2526
2527 RevalidationSelectorAndHashes {
2528 selector,
2529 selector_offset,
2530 hashes,
2531 }
2532 }
2533}
2534
2535impl SelectorMapEntry for RevalidationSelectorAndHashes {
2536 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2537 self.selector.iter_from(self.selector_offset)
2538 }
2539}
2540
2541struct StylistSelectorVisitor<'a> {
2544 passed_rightmost_selector: bool,
2547
2548 needs_revalidation: &'a mut bool,
2550
2551 non_link_visited_dependency: &'a mut bool,
2554
2555 in_selector_list_of: SelectorListKind,
2558
2559 mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2561
2562 nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2565
2566 attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2568
2569 nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2572
2573 nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2577
2578 nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2582
2583 state_dependencies: &'a mut ElementState,
2585
2586 nth_of_state_dependencies: &'a mut ElementState,
2589
2590 document_state_dependencies: &'a mut DocumentState,
2592}
2593
2594fn component_needs_revalidation(c: &Component<SelectorImpl>) -> bool {
2595 match *c {
2596 Component::AttributeInNoNamespaceExists { .. }
2597 | Component::AttributeInNoNamespace { .. }
2598 | Component::AttributeOther(_)
2599 | Component::Empty
2600 | Component::Nth(_)
2601 | Component::NthOf(_)
2602 | Component::Has(_) => true,
2603 Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2604 _ => false,
2605 }
2606}
2607
2608impl<'a> StylistSelectorVisitor<'a> {
2609 fn visit_nested_selector(
2610 &mut self,
2611 in_selector_list_of: SelectorListKind,
2612 selector: &Selector<SelectorImpl>,
2613 ) {
2614 let old_passed_rightmost_selector = self.passed_rightmost_selector;
2615 let old_in_selector_list_of = self.in_selector_list_of;
2616
2617 self.in_selector_list_of = in_selector_list_of;
2619 let _ret = selector.visit(self);
2620 debug_assert!(_ret, "We never return false");
2621
2622 self.passed_rightmost_selector = old_passed_rightmost_selector;
2623 self.in_selector_list_of = old_in_selector_list_of;
2624 }
2625}
2626
2627impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2628 type Impl = SelectorImpl;
2629
2630 fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2631 *self.needs_revalidation =
2632 *self.needs_revalidation || combinator.is_some_and(|c| c.is_sibling());
2633
2634 self.passed_rightmost_selector = self.passed_rightmost_selector
2638 || !matches!(combinator, None | Some(Combinator::PseudoElement));
2639
2640 true
2641 }
2642
2643 fn visit_selector_list(
2644 &mut self,
2645 list_kind: SelectorListKind,
2646 list: &[Selector<Self::Impl>],
2647 ) -> bool {
2648 let in_selector_list_of = self.in_selector_list_of | list_kind;
2649 for selector in list {
2650 self.visit_nested_selector(in_selector_list_of, selector);
2651 }
2652 true
2653 }
2654
2655 fn visit_relative_selector_list(
2656 &mut self,
2657 list: &[selectors::parser::RelativeSelector<Self::Impl>],
2658 ) -> bool {
2659 let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2660 for selector in list {
2661 self.visit_nested_selector(in_selector_list_of, &selector.selector);
2662 }
2663 true
2664 }
2665
2666 fn visit_attribute_selector(
2667 &mut self,
2668 _ns: &NamespaceConstraint<&Namespace>,
2669 name: &LocalName,
2670 lower_name: &LocalName,
2671 ) -> bool {
2672 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2673 self.nth_of_attribute_dependencies.insert(name.clone());
2674 if name != lower_name {
2675 self.nth_of_attribute_dependencies
2676 .insert(lower_name.clone());
2677 }
2678 }
2679
2680 self.attribute_dependencies.insert(name.clone());
2681 if name != lower_name {
2682 self.attribute_dependencies.insert(lower_name.clone());
2683 }
2684
2685 true
2686 }
2687
2688 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2689 *self.needs_revalidation = *self.needs_revalidation || component_needs_revalidation(s);
2690
2691 match *s {
2692 Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2693 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2699 self.nth_of_custom_state_dependencies.insert(name.0.clone());
2700 }
2701 },
2702 Component::NonTSPseudoClass(ref p) => {
2703 self.state_dependencies.insert(p.state_flag());
2704 self.document_state_dependencies
2705 .insert(p.document_state_flag());
2706
2707 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2708 self.nth_of_state_dependencies.insert(p.state_flag());
2709 }
2710
2711 if self.passed_rightmost_selector
2712 && matches!(*p, NonTSPseudoClass::Link | NonTSPseudoClass::Visited)
2713 {
2714 *self.non_link_visited_dependency = true;
2715 }
2716 },
2717 Component::ID(ref id) => {
2718 self.mapped_ids.insert(id.0.clone());
2719 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2720 self.nth_of_mapped_ids.insert(id.0.clone());
2721 }
2722 },
2723 Component::Class(ref class)
2724 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2725 {
2726 self.nth_of_class_dependencies.insert(class.0.clone());
2727 },
2728 _ => {},
2729 }
2730
2731 true
2732 }
2733}
2734
2735#[derive(Clone, Debug, Default, MallocSizeOf)]
2737struct GenericElementAndPseudoRules<Map> {
2738 element_map: Map,
2740
2741 pseudos_map: PerPseudoElementMap<Self>,
2748}
2749
2750impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2751 #[inline(always)]
2752 fn for_insertion(&mut self, pseudo_elements: &[&PseudoElement]) -> &mut Map {
2753 let mut current = self;
2754 for &pseudo_element in pseudo_elements {
2755 debug_assert!(
2756 !pseudo_element.is_precomputed()
2757 && !pseudo_element.is_unknown_webkit_pseudo_element(),
2758 "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2759 and unknown webkit pseudos should be discarded before getting here"
2760 );
2761
2762 current = current
2763 .pseudos_map
2764 .get_or_insert_with(pseudo_element, Default::default);
2765 }
2766
2767 &mut current.element_map
2768 }
2769
2770 #[inline]
2771 fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2772 let mut current = self;
2773 for pseudo in pseudo_elements {
2774 current = current.pseudos_map.get(pseudo)?;
2775 }
2776 Some(¤t.element_map)
2777 }
2778
2779 #[cfg(feature = "gecko")]
2781 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2782 sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2783
2784 for elem in self.pseudos_map.iter() {
2785 sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2786 }
2787 }
2788}
2789
2790type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2791type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2792type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2793
2794impl ElementAndPseudoRules {
2795 fn clear(&mut self) {
2797 self.element_map.clear();
2798 self.pseudos_map.clear();
2799 }
2800
2801 fn shrink_if_needed(&mut self) {
2802 self.element_map.shrink_if_needed();
2803 for pseudo in self.pseudos_map.iter_mut() {
2804 pseudo.shrink_if_needed();
2805 }
2806 }
2807}
2808
2809impl PartElementAndPseudoRules {
2810 fn clear(&mut self) {
2812 self.element_map.clear();
2813 self.pseudos_map.clear();
2814 }
2815}
2816
2817#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2819pub struct LayerId(u16);
2820
2821impl LayerId {
2822 pub const fn root() -> Self {
2824 Self(0)
2825 }
2826}
2827
2828#[derive(Clone, Debug, MallocSizeOf)]
2829struct CascadeLayer {
2830 id: LayerId,
2831 order: LayerOrder,
2832 children: Vec<LayerId>,
2833}
2834
2835impl CascadeLayer {
2836 const fn root() -> Self {
2837 Self {
2838 id: LayerId::root(),
2839 order: LayerOrder::root(),
2840 children: vec![],
2841 }
2842 }
2843}
2844
2845#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2848pub struct ContainerConditionId(u16);
2849
2850impl ContainerConditionId {
2851 pub const fn none() -> Self {
2853 Self(0)
2854 }
2855}
2856
2857#[derive(Clone, Debug, MallocSizeOf)]
2858struct ContainerConditionReference {
2859 parent: ContainerConditionId,
2860 #[ignore_malloc_size_of = "Arc"]
2865 conditions: ArcSlice<ContainerCondition>,
2866}
2867
2868impl ContainerConditionReference {
2869 fn none() -> Self {
2871 Self {
2872 parent: ContainerConditionId::none(),
2873 conditions: ArcSlice::default(),
2874 }
2875 }
2876}
2877
2878#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2881pub struct ScopeConditionId(u16);
2882
2883impl ScopeConditionId {
2884 pub fn new(id: u16) -> Self {
2886 Self(id)
2887 }
2888
2889 pub const fn none() -> Self {
2891 Self(0)
2892 }
2893}
2894
2895#[derive(Clone, Debug, MallocSizeOf)]
2897pub struct ScopeConditionReference {
2898 parent: ScopeConditionId,
2900 condition: Option<ScopeBoundsWithHashes>,
2902 #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2905 implicit_scope_root: StylistImplicitScopeRoot,
2906 is_trivial: bool,
2908}
2909
2910impl ScopeConditionReference {
2911 pub fn new(
2913 parent: ScopeConditionId,
2914 condition: Option<ScopeBoundsWithHashes>,
2915 implicit_scope_root: ImplicitScopeRoot,
2916 is_trivial: bool,
2917 ) -> Self {
2918 Self {
2919 parent,
2920 condition,
2921 implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2922 is_trivial,
2923 }
2924 }
2925
2926 pub const fn none() -> Self {
2928 Self {
2929 parent: ScopeConditionId::none(),
2930 condition: None,
2931 implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2932 is_trivial: true,
2933 }
2934 }
2935}
2936
2937pub struct ScopeRootCandidates {
2939 pub candidates: Vec<ScopeRootCandidate>,
2941 pub is_trivial: bool,
2943}
2944
2945impl Default for ScopeRootCandidates {
2946 fn default() -> Self {
2947 Self {
2948 candidates: vec![],
2949 is_trivial: true,
2950 }
2951 }
2952}
2953
2954impl ScopeRootCandidates {
2955 fn empty(is_trivial: bool) -> Self {
2956 Self {
2957 candidates: vec![],
2958 is_trivial,
2959 }
2960 }
2961}
2962
2963#[derive(Clone, Debug, MallocSizeOf)]
2965pub struct ScopeBoundWithHashes {
2966 #[ignore_malloc_size_of = "Arc"]
2968 selectors: SelectorList<SelectorImpl>,
2969 hashes: SmallVec<[AncestorHashes; 1]>,
2970}
2971
2972impl ScopeBoundWithHashes {
2973 fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2974 let mut hashes = SmallVec::with_capacity(selectors.len());
2975 for selector in selectors.slice() {
2976 hashes.push(AncestorHashes::new(selector, quirks_mode));
2977 }
2978 Self { selectors, hashes }
2979 }
2980
2981 fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
2982 let hashes = selectors
2983 .slice()
2984 .iter()
2985 .map(|_| AncestorHashes {
2986 packed_hashes: [0, 0, 0],
2987 })
2988 .collect();
2989 Self { selectors, hashes }
2990 }
2991}
2992
2993#[derive(Clone, Debug, MallocSizeOf)]
2995pub struct ScopeBoundsWithHashes {
2996 start: Option<ScopeBoundWithHashes>,
2998 end: Option<ScopeBoundWithHashes>,
3000}
3001
3002impl ScopeBoundsWithHashes {
3003 fn new(
3005 quirks_mode: QuirksMode,
3006 start: Option<SelectorList<SelectorImpl>>,
3007 end: Option<SelectorList<SelectorImpl>>,
3008 ) -> Self {
3009 Self {
3010 start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3011 end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3012 }
3013 }
3014
3015 pub fn new_no_hash(
3017 start: Option<SelectorList<SelectorImpl>>,
3018 end: Option<SelectorList<SelectorImpl>>,
3019 ) -> Self {
3020 Self {
3021 start: start.map(ScopeBoundWithHashes::new_no_hash),
3022 end: end.map(ScopeBoundWithHashes::new_no_hash),
3023 }
3024 }
3025
3026 fn selectors_for(
3027 bound_with_hashes: Option<&ScopeBoundWithHashes>,
3028 ) -> impl Iterator<Item = &Selector<SelectorImpl>> {
3029 bound_with_hashes
3030 .map(|b| b.selectors.slice().iter())
3031 .into_iter()
3032 .flatten()
3033 }
3034
3035 fn start_selectors(&self) -> impl Iterator<Item = &Selector<SelectorImpl>> {
3036 Self::selectors_for(self.start.as_ref())
3037 }
3038
3039 fn end_selectors(&self) -> impl Iterator<Item = &Selector<SelectorImpl>> {
3040 Self::selectors_for(self.end.as_ref())
3041 }
3042
3043 fn is_trivial(&self) -> bool {
3044 fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
3045 bound.as_ref().map_or(default, |bound| {
3046 scope_selector_list_is_trivial(&bound.selectors)
3047 })
3048 }
3049
3050 scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
3052 }
3053}
3054
3055pub fn scope_root_candidates<E>(
3057 scope_conditions: &[ScopeConditionReference],
3058 id: ScopeConditionId,
3059 element: &E,
3060 override_matches_shadow_host_for_part: bool,
3061 scope_subject_map: &ScopeSubjectMap,
3062 context: &mut MatchingContext<SelectorImpl>,
3063) -> ScopeRootCandidates
3064where
3065 E: TElement,
3066{
3067 let condition_ref = &scope_conditions[id.0 as usize];
3068 let bounds = match condition_ref.condition {
3069 None => return ScopeRootCandidates::default(),
3070 Some(ref c) => c,
3071 };
3072 if id.0 <= condition_ref.parent.0 {
3073 debug_assert!(false, "@scope bookkeeping is corrupt.");
3074 return ScopeRootCandidates::default();
3075 }
3076 let outer_result = scope_root_candidates(
3080 scope_conditions,
3081 condition_ref.parent,
3082 element,
3083 override_matches_shadow_host_for_part,
3084 scope_subject_map,
3085 context,
3086 );
3087
3088 let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
3089 let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
3090 if !is_outermost_scope && outer_result.candidates.is_empty() {
3091 return ScopeRootCandidates::empty(is_trivial);
3092 }
3093
3094 let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
3095 if let Some(filter) = context.bloom_filter {
3096 if !start
3101 .hashes
3102 .iter()
3103 .any(|entry| selector_may_match(entry, filter))
3104 {
3105 return ScopeRootCandidates::empty(is_trivial);
3106 }
3107 }
3108 (
3109 ScopeTarget::Selector(&start.selectors),
3110 scope_start_matches_shadow_host(&start.selectors),
3111 )
3112 } else {
3113 let implicit_root = condition_ref.implicit_scope_root;
3114 match implicit_root {
3115 StylistImplicitScopeRoot::Normal(r) => (
3116 ScopeTarget::Implicit(r.element(context.current_host)),
3117 r.matches_shadow_host(),
3118 ),
3119 StylistImplicitScopeRoot::Cached(index) => {
3120 let host = context
3121 .current_host
3122 .expect("Cached implicit scope for light DOM implicit scope");
3123 match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
3124 None => return ScopeRootCandidates::empty(is_trivial),
3125 Some(root) => (
3126 ScopeTarget::Implicit(root.element(context.current_host)),
3127 root.matches_shadow_host(),
3128 ),
3129 }
3130 },
3131 }
3132 };
3133 let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
3136
3137 let potential_scope_roots = if is_outermost_scope {
3138 collect_scope_roots(
3139 *element,
3140 None,
3141 context,
3142 &root_target,
3143 matches_shadow_host,
3144 scope_subject_map,
3145 )
3146 } else {
3147 let mut result = vec![];
3148 for activation in outer_result.candidates {
3149 let mut this_result = collect_scope_roots(
3150 *element,
3151 Some(activation.root),
3152 context,
3153 &root_target,
3154 matches_shadow_host,
3155 scope_subject_map,
3156 );
3157 result.append(&mut this_result);
3158 }
3159 result
3160 };
3161
3162 if potential_scope_roots.is_empty() {
3163 return ScopeRootCandidates::empty(is_trivial);
3164 }
3165
3166 let candidates = if let Some(end) = bounds.end.as_ref() {
3167 let mut result = vec![];
3168 for scope_root in potential_scope_roots {
3170 if end
3171 .selectors
3172 .slice()
3173 .iter()
3174 .zip(end.hashes.iter())
3175 .all(|(selector, hashes)| {
3176 if let Some(filter) = context.bloom_filter
3178 && !selector_may_match(hashes, filter)
3179 {
3180 return true;
3182 }
3183
3184 !element_is_outside_of_scope(
3185 selector,
3186 *element,
3187 scope_root.root,
3188 context,
3189 matches_shadow_host,
3190 )
3191 })
3192 {
3193 result.push(scope_root);
3194 }
3195 }
3196 result
3197 } else {
3198 potential_scope_roots
3199 };
3200
3201 ScopeRootCandidates {
3202 candidates,
3203 is_trivial,
3204 }
3205}
3206
3207#[derive(Copy, Clone, Debug, MallocSizeOf)]
3210enum StylistImplicitScopeRoot {
3211 Normal(ImplicitScopeRoot),
3212 Cached(usize),
3213}
3214unsafe impl Sync for StylistImplicitScopeRoot {}
3216
3217impl StylistImplicitScopeRoot {
3218 const fn default_const() -> Self {
3219 Self::Normal(ImplicitScopeRoot::DocumentElement)
3221 }
3222}
3223
3224impl Default for StylistImplicitScopeRoot {
3225 fn default() -> Self {
3226 Self::default_const()
3227 }
3228}
3229
3230#[derive(Debug, Clone, MallocSizeOf)]
3236pub struct CascadeData {
3237 normal_rules: ElementAndPseudoRules,
3240
3241 featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3245
3246 slotted_rules: Option<Box<ElementAndPseudoRules>>,
3254
3255 part_rules: Option<Box<PartElementAndPseudoRules>>,
3260
3261 invalidation_map: InvalidationMap,
3263
3264 relative_selector_invalidation_map: InvalidationMap,
3266
3267 additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3268
3269 attribute_dependencies: PrecomputedHashSet<LocalName>,
3274
3275 nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3279
3280 nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3284
3285 nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3289
3290 state_dependencies: ElementState,
3294
3295 non_link_visited_dependency: bool,
3298
3299 nth_of_state_dependencies: ElementState,
3302
3303 document_state_dependencies: DocumentState,
3307
3308 mapped_ids: PrecomputedHashSet<Atom>,
3313
3314 nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3318
3319 #[ignore_malloc_size_of = "Arc"]
3323 selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3324
3325 animations: LayerOrderedMap<KeyframesAnimation>,
3328
3329 #[ignore_malloc_size_of = "Arc"]
3332 custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3333
3334 custom_media: CustomMediaMap,
3336
3337 layer_id: FxHashMap<LayerName, LayerId>,
3339
3340 layers: SmallVec<[CascadeLayer; 1]>,
3342
3343 container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3345
3346 attr_function_dependencies: PrecomputedHashMap<LocalName, ContainerAttributeDependencyKind>,
3350
3351 scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3353
3354 scope_subject_map: ScopeSubjectMap,
3356
3357 effective_media_query_results: EffectiveMediaQueryResults,
3359
3360 extra_data: ExtraStyleData,
3362
3363 rules_source_order: u32,
3366
3367 num_selectors: usize,
3369
3370 num_declarations: usize,
3372}
3373
3374static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3375 let list = SelectorList::implicit_scope();
3379 list.mark_as_intentionally_leaked();
3380 list
3381});
3382
3383fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3384 start
3387 .slice()
3388 .iter()
3389 .any(|s| s.matches_featureless_host(true).may_match())
3390}
3391
3392pub fn replace_parent_selector_with_implicit_scope(
3394 selectors: &SelectorList<SelectorImpl>,
3395) -> SelectorList<SelectorImpl> {
3396 selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3397}
3398
3399impl CascadeData {
3400 pub fn new() -> Self {
3402 Self {
3403 normal_rules: ElementAndPseudoRules::default(),
3404 featureless_host_rules: None,
3405 slotted_rules: None,
3406 part_rules: None,
3407 invalidation_map: InvalidationMap::new(),
3408 relative_selector_invalidation_map: InvalidationMap::new(),
3409 additional_relative_selector_invalidation_map:
3410 AdditionalRelativeSelectorInvalidationMap::new(),
3411 nth_of_mapped_ids: PrecomputedHashSet::default(),
3412 nth_of_class_dependencies: PrecomputedHashSet::default(),
3413 nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3414 nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3415 nth_of_state_dependencies: ElementState::empty(),
3416 attribute_dependencies: PrecomputedHashSet::default(),
3417 state_dependencies: ElementState::empty(),
3418 non_link_visited_dependency: false,
3419 document_state_dependencies: DocumentState::empty(),
3420 mapped_ids: PrecomputedHashSet::default(),
3421 selectors_for_cache_revalidation: SelectorMap::new(),
3422 animations: Default::default(),
3423 custom_property_registrations: Default::default(),
3424 custom_media: Default::default(),
3425 layer_id: Default::default(),
3426 layers: smallvec::smallvec![CascadeLayer::root()],
3427 container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3428 attr_function_dependencies: PrecomputedHashMap::default(),
3429 scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3430 scope_subject_map: Default::default(),
3431 extra_data: ExtraStyleData::default(),
3432 effective_media_query_results: EffectiveMediaQueryResults::new(),
3433 rules_source_order: 0,
3434 num_selectors: 0,
3435 num_declarations: 0,
3436 }
3437 }
3438
3439 pub fn rebuild<'a, S>(
3441 &mut self,
3442 device: &Device,
3443 quirks_mode: QuirksMode,
3444 collection: SheetCollectionFlusher<S>,
3445 guard: &SharedRwLockReadGuard,
3446 difference: &mut CascadeDataDifference,
3447 ) -> Result<(), AllocErr>
3448 where
3449 S: StylesheetInDocument + PartialEq + 'static,
3450 {
3451 if !collection.dirty() {
3452 return Ok(());
3453 }
3454
3455 let validity = collection.data_validity();
3456
3457 let mut old_position_try_data = LayerOrderedMap::default();
3458 if validity != DataValidity::Valid {
3459 old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3460 self.clear_cascade_data();
3461 if validity == DataValidity::FullyInvalid {
3462 self.clear_invalidation_data();
3463 }
3464 }
3465
3466 let mut result = Ok(());
3467
3468 collection.each(|index, stylesheet, rebuild_kind| {
3469 result = self.add_stylesheet(
3470 device,
3471 quirks_mode,
3472 stylesheet,
3473 index,
3474 guard,
3475 rebuild_kind,
3476 None,
3477 if validity == DataValidity::Valid {
3478 Some(difference)
3479 } else {
3480 None
3481 },
3482 );
3483 result.is_ok()
3484 });
3485
3486 self.did_finish_rebuild();
3487
3488 if validity != DataValidity::Valid {
3491 difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3492 }
3493
3494 result
3495 }
3496
3497 pub fn custom_media_map(&self) -> &CustomMediaMap {
3499 &self.custom_media
3500 }
3501
3502 pub fn invalidation_map(&self) -> &InvalidationMap {
3504 &self.invalidation_map
3505 }
3506
3507 pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3509 &self.relative_selector_invalidation_map
3510 }
3511
3512 pub fn relative_invalidation_map_attributes(
3514 &self,
3515 ) -> &AdditionalRelativeSelectorInvalidationMap {
3516 &self.additional_relative_selector_invalidation_map
3517 }
3518
3519 #[inline]
3522 pub fn has_state_dependency(&self, state: ElementState) -> bool {
3523 self.state_dependencies.intersects(state)
3524 }
3525
3526 #[inline]
3529 pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3530 self.nth_of_custom_state_dependencies.contains(state)
3531 }
3532
3533 #[inline]
3536 pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3537 self.nth_of_state_dependencies.intersects(state)
3538 }
3539
3540 #[inline]
3543 pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3544 self.attribute_dependencies.contains(local_name)
3545 }
3546
3547 pub fn has_non_link_visited_dependency(&self) -> bool {
3551 self.non_link_visited_dependency
3552 }
3553
3554 #[inline]
3560 pub fn might_have_attribute_dependency_in_container(
3561 &self,
3562 local_name: &LocalName,
3563 ) -> ContainerAttributeDependencyKind {
3564 self.attr_function_dependencies
3565 .get(local_name)
3566 .copied()
3567 .unwrap_or(ContainerAttributeDependencyKind::None)
3568 }
3569
3570 #[inline]
3573 pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3574 self.nth_of_mapped_ids.contains(id)
3575 }
3576
3577 #[inline]
3580 pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3581 self.nth_of_class_dependencies.contains(class)
3582 }
3583
3584 #[inline]
3587 pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3588 self.nth_of_attribute_dependencies.contains(local_name)
3589 }
3590
3591 #[inline]
3593 pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3594 self.normal_rules.rules(pseudo_elements)
3595 }
3596
3597 #[inline]
3599 pub fn featureless_host_rules(
3600 &self,
3601 pseudo_elements: &[PseudoElement],
3602 ) -> Option<&SelectorMap<Rule>> {
3603 self.featureless_host_rules
3604 .as_ref()
3605 .and_then(|d| d.rules(pseudo_elements))
3606 }
3607
3608 pub fn any_featureless_host_rules(&self) -> bool {
3610 self.featureless_host_rules.is_some()
3611 }
3612
3613 #[inline]
3615 pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3616 self.slotted_rules
3617 .as_ref()
3618 .and_then(|d| d.rules(pseudo_elements))
3619 }
3620
3621 pub fn any_slotted_rule(&self) -> bool {
3623 self.slotted_rules.is_some()
3624 }
3625
3626 #[inline]
3628 pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3629 self.part_rules
3630 .as_ref()
3631 .and_then(|d| d.rules(pseudo_elements))
3632 }
3633
3634 pub fn any_part_rule(&self) -> bool {
3636 self.part_rules.is_some()
3637 }
3638
3639 #[inline]
3640 fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3641 self.layers[id.0 as usize].order
3642 }
3643
3644 pub(crate) fn container_condition_matches<E>(
3645 &self,
3646 mut id: ContainerConditionId,
3647 stylist: &Stylist,
3648 element: E,
3649 context: &mut MatchingContext<E::Impl>,
3650 ) -> bool
3651 where
3652 E: TElement,
3653 {
3654 loop {
3655 let condition_ref = &self.container_conditions[id.0 as usize];
3656 if condition_ref.conditions.is_empty() {
3657 return true;
3658 }
3659 let matches = condition_ref.conditions.iter().any(|condition| {
3660 condition
3661 .matches(
3662 stylist,
3663 element,
3664 context.extra_data.originating_element_style,
3665 &mut context.extra_data.cascade_input_flags,
3666 )
3667 .to_bool(false)
3668 });
3669 if !matches {
3670 return false;
3671 }
3672 id = condition_ref.parent;
3673 }
3674 }
3675
3676 pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3677 &self,
3678 rule: &Rule,
3679 element: E,
3680 context: &mut MatchingContext<E::Impl>,
3681 ) -> ScopeProximity {
3682 context
3683 .extra_data
3684 .cascade_input_flags
3685 .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3686
3687 let result = scope_root_candidates(
3691 &self.scope_conditions,
3692 rule.scope_condition_id,
3693 &element,
3694 rule.selector.is_part(),
3695 &self.scope_subject_map,
3696 context,
3697 );
3698 for candidate in result.candidates {
3699 if context.nest_for_scope(Some(candidate.root), |context| {
3700 rule.matches_selector(element, context)
3701 }) {
3702 return candidate.proximity;
3703 }
3704 }
3705 ScopeProximity::infinity()
3706 }
3707
3708 fn did_finish_rebuild(&mut self) {
3709 self.shrink_maps_if_needed();
3710 self.compute_layer_order();
3711 }
3712
3713 fn shrink_maps_if_needed(&mut self) {
3714 self.normal_rules.shrink_if_needed();
3715 if let Some(ref mut host_rules) = self.featureless_host_rules {
3716 host_rules.shrink_if_needed();
3717 }
3718 if let Some(ref mut slotted_rules) = self.slotted_rules {
3719 slotted_rules.shrink_if_needed();
3720 }
3721 self.animations.shrink_if_needed();
3722 self.custom_property_registrations.shrink_if_needed();
3723 self.invalidation_map.shrink_if_needed();
3724 self.relative_selector_invalidation_map.shrink_if_needed();
3725 self.additional_relative_selector_invalidation_map
3726 .shrink_if_needed();
3727 self.attribute_dependencies.shrink_if_needed();
3728 self.nth_of_attribute_dependencies.shrink_if_needed();
3729 self.nth_of_custom_state_dependencies.shrink_if_needed();
3730 self.nth_of_class_dependencies.shrink_if_needed();
3731 self.nth_of_mapped_ids.shrink_if_needed();
3732 self.mapped_ids.shrink_if_needed();
3733 self.layer_id.shrink_if_needed();
3734 self.selectors_for_cache_revalidation.shrink_if_needed();
3735 self.scope_subject_map.shrink_if_needed();
3736 }
3737
3738 fn compute_layer_order(&mut self) {
3739 debug_assert_ne!(
3740 self.layers.len(),
3741 0,
3742 "There should be at least the root layer!"
3743 );
3744 if self.layers.len() == 1 {
3745 return; }
3747 let (first, remaining) = self.layers.split_at_mut(1);
3748 let root = &mut first[0];
3749 let mut order = LayerOrder::first();
3750 compute_layer_order_for_subtree(root, remaining, &mut order);
3751
3752 fn compute_layer_order_for_subtree(
3755 parent: &mut CascadeLayer,
3756 remaining_layers: &mut [CascadeLayer],
3757 order: &mut LayerOrder,
3758 ) {
3759 for child in parent.children.iter() {
3760 debug_assert!(
3761 parent.id < *child,
3762 "Children are always registered after parents"
3763 );
3764 let child_index = (child.0 - parent.id.0 - 1) as usize;
3765 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3766 let child = &mut first[child_index];
3767 compute_layer_order_for_subtree(child, remaining, order);
3768 }
3769
3770 if parent.id != LayerId::root() {
3771 parent.order = *order;
3772 order.inc();
3773 }
3774 }
3775 self.extra_data.sort_by_layer(&self.layers);
3776 self.animations
3777 .sort_with(&self.layers, compare_keyframes_in_same_layer);
3778 self.custom_property_registrations.sort(&self.layers)
3779 }
3780
3781 fn collect_applicable_media_query_results_into<S>(
3790 device: &Device,
3791 stylesheet: &S,
3792 guard: &SharedRwLockReadGuard,
3793 results: &mut Vec<MediaListKey>,
3794 contents_list: &mut StyleSheetContentList,
3795 custom_media_map: &mut CustomMediaMap,
3796 ) where
3797 S: StylesheetInDocument + 'static,
3798 {
3799 if !stylesheet.enabled() {
3800 return;
3801 }
3802 if !stylesheet.is_effective_for_device(device, custom_media_map, guard) {
3803 return;
3804 }
3805
3806 debug!(" + {:?}", stylesheet);
3807 let contents = stylesheet.contents(guard);
3808 results.push(contents.to_media_list_key());
3809
3810 contents_list.push(StylesheetContentsPtr(unsafe {
3812 Arc::from_raw_addrefed(contents)
3813 }));
3814
3815 let mut iter = stylesheet
3816 .contents(guard)
3817 .effective_rules(device, custom_media_map, guard);
3818 while let Some(rule) = iter.next() {
3819 match *rule {
3820 CssRule::CustomMedia(ref custom_media) => {
3821 iter.custom_media()
3822 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3823 },
3824 CssRule::Import(ref lock) => {
3825 let import_rule = lock.read_with(guard);
3826 debug!(" + {:?}", import_rule.stylesheet.media(guard));
3827 results.push(import_rule.to_media_list_key());
3828 },
3829 CssRule::Media(ref media_rule) => {
3830 debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3831 results.push(media_rule.to_media_list_key());
3832 },
3833 _ => {},
3834 }
3835 }
3836 }
3837
3838 fn add_styles(
3839 &mut self,
3840 selectors: &SelectorList<SelectorImpl>,
3841 declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3842 ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3843 containing_rule_state: &ContainingRuleState,
3844 mut replaced_selectors: Option<&mut ReplacedSelectors>,
3845 guard: &SharedRwLockReadGuard,
3846 rebuild_kind: SheetRebuildKind,
3847 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3848 quirks_mode: QuirksMode,
3849 mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3850 ) -> Result<(), AllocErr> {
3851 self.num_declarations += declarations.read_with(guard).len();
3852 for selector in selectors.slice() {
3853 self.num_selectors += 1;
3854
3855 let pseudo_elements = selector.pseudo_elements();
3856 let inner_pseudo_element = pseudo_elements.first();
3857 if let Some(pseudo) = inner_pseudo_element {
3858 if pseudo.is_precomputed() {
3859 debug_assert!(selector.is_universal());
3860 debug_assert!(ancestor_selectors.is_none());
3861 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3862 debug_assert!(!containing_rule_state.scope_is_effective());
3864 precomputed_pseudo_element_decls
3865 .as_mut()
3866 .expect("Expected precomputed declarations for the UA level")
3867 .get_or_insert_with(pseudo, Vec::new)
3868 .push(ApplicableDeclarationBlock::new(
3869 StyleSource::from_declarations(declarations.clone()),
3870 self.rules_source_order,
3871 CascadeLevel::new(CascadeOrigin::UA),
3872 selector.specificity(),
3873 LayerOrder::root(),
3874 ScopeProximity::infinity(),
3875 RuleCascadeFlags::empty(),
3876 ));
3877 continue;
3878 }
3879 if pseudo_elements
3880 .iter()
3881 .any(|p| p.is_unknown_webkit_pseudo_element())
3882 {
3883 continue;
3884 }
3885 }
3886
3887 debug_assert!(
3888 !pseudo_elements
3889 .iter()
3890 .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element())
3891 );
3892
3893 let selector = match ancestor_selectors {
3894 Some(s) => selector.replace_parent_selector(s),
3895 None => selector.clone(),
3896 };
3897
3898 let hashes = AncestorHashes::new(&selector, quirks_mode);
3899
3900 let rule = Rule::new(
3901 selector,
3902 hashes,
3903 StyleSource::from_declarations(declarations.clone()),
3904 self.rules_source_order,
3905 containing_rule_state.layer_id,
3906 containing_rule_state.container_condition_id,
3907 containing_rule_state.cascade_flags(),
3908 containing_rule_state.containing_scope_rule_state.id,
3909 );
3910
3911 if let Some(ref mut replaced_selectors) = replaced_selectors {
3912 replaced_selectors.push(rule.selector.clone())
3913 }
3914
3915 if rebuild_kind.should_rebuild_invalidation() {
3916 let mut scope_dependencies = note_selector_for_invalidation(
3917 &rule.selector,
3918 quirks_mode,
3919 &mut self.invalidation_map,
3920 &mut self.relative_selector_invalidation_map,
3921 &mut self.additional_relative_selector_invalidation_map,
3922 None,
3923 None,
3924 )?;
3925 let mut needs_revalidation = false;
3926 let mut visitor = StylistSelectorVisitor {
3927 passed_rightmost_selector: false,
3928 needs_revalidation: &mut needs_revalidation,
3929 non_link_visited_dependency: &mut self.non_link_visited_dependency,
3930 in_selector_list_of: SelectorListKind::default(),
3931 mapped_ids: &mut self.mapped_ids,
3932 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3933 attribute_dependencies: &mut self.attribute_dependencies,
3934 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3935 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3936 nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3937 state_dependencies: &mut self.state_dependencies,
3938 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3939 document_state_dependencies: &mut self.document_state_dependencies,
3940 };
3941 rule.selector.visit(&mut visitor);
3942
3943 if needs_revalidation {
3944 self.selectors_for_cache_revalidation.insert(
3945 RevalidationSelectorAndHashes::new(
3946 rule.selector.clone(),
3947 rule.hashes.clone(),
3948 ),
3949 quirks_mode,
3950 )?;
3951 }
3952
3953 if let (Some(inner_scope_deps), Some(scope_deps)) = (
3954 scope_dependencies.as_mut(),
3955 collected_scope_dependencies.as_mut(),
3956 ) {
3957 scope_deps.append(inner_scope_deps)
3958 }
3959 }
3960
3961 if let Some(parts) = rule.selector.parts() {
3965 let map = self
3972 .part_rules
3973 .get_or_insert_with(Box::default)
3974 .for_insertion(&pseudo_elements);
3975 map.try_reserve(1)?;
3976 let vec = map.entry_ref(&parts.last().unwrap().0).or_default();
3977 vec.try_reserve(1)?;
3978 vec.push(rule);
3979 } else {
3980 let scope_matches_shadow_host = containing_rule_state
3981 .containing_scope_rule_state
3982 .matches_shadow_host
3983 == ScopeMatchesShadowHost::Yes;
3984 let matches_featureless_host_only = match rule
3985 .selector
3986 .matches_featureless_host(scope_matches_shadow_host)
3987 {
3988 MatchesFeaturelessHost::Only => true,
3989 MatchesFeaturelessHost::Yes => {
3990 self.featureless_host_rules
3992 .get_or_insert_with(Box::default)
3993 .for_insertion(&pseudo_elements)
3994 .insert(rule.clone(), quirks_mode)?;
3995 false
3996 },
3997 MatchesFeaturelessHost::Never => false,
3998 };
3999
4000 let rules = if matches_featureless_host_only {
4007 self.featureless_host_rules.get_or_insert_with(Box::default)
4008 } else if rule.selector.is_slotted() {
4009 self.slotted_rules.get_or_insert_with(Box::default)
4010 } else {
4011 &mut self.normal_rules
4012 }
4013 .for_insertion(&pseudo_elements);
4014 rules.insert(rule, quirks_mode)?;
4015 }
4016 }
4017 self.rules_source_order += 1;
4018 Ok(())
4019 }
4020
4021 fn add_rule_list<S>(
4022 &mut self,
4023 rules: std::slice::Iter<CssRule>,
4024 device: &Device,
4025 quirks_mode: QuirksMode,
4026 stylesheet: &S,
4027 sheet_index: usize,
4028 guard: &SharedRwLockReadGuard,
4029 rebuild_kind: SheetRebuildKind,
4030 containing_rule_state: &mut ContainingRuleState,
4031 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4032 mut difference: Option<&mut CascadeDataDifference>,
4033 ) -> Result<(), AllocErr>
4034 where
4035 S: StylesheetInDocument + 'static,
4036 {
4037 for rule in rules {
4038 let mut handled = true;
4041 let mut list_for_nested_rules = None;
4042 match *rule {
4043 CssRule::Style(ref locked) => {
4044 let style_rule = locked.read_with(guard);
4045 let has_nested_rules = style_rule.rules.is_some();
4046 let mut replaced_selectors = ReplacedSelectors::new();
4047 let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
4048 let collect_replaced_selectors =
4049 has_nested_rules && ancestor_selectors.is_some();
4050 let mut inner_dependencies: Option<Vec<Dependency>> =
4051 containing_rule_state.scope_is_effective().then(Vec::new);
4052 self.add_styles(
4053 &style_rule.selectors,
4054 &style_rule.block,
4055 ancestor_selectors,
4056 containing_rule_state,
4057 if collect_replaced_selectors {
4058 Some(&mut replaced_selectors)
4059 } else {
4060 None
4061 },
4062 guard,
4063 rebuild_kind,
4064 precomputed_pseudo_element_decls.as_deref_mut(),
4065 quirks_mode,
4066 inner_dependencies.as_mut(),
4067 )?;
4068 if let Some(mut scope_dependencies) = inner_dependencies {
4069 containing_rule_state
4070 .containing_scope_rule_state
4071 .inner_dependencies
4072 .append(&mut scope_dependencies);
4073 }
4074 if has_nested_rules {
4075 handled = false;
4076 list_for_nested_rules = Some(if collect_replaced_selectors {
4077 SelectorList::from_iter(replaced_selectors.drain(..))
4078 } else {
4079 style_rule.selectors.clone()
4080 });
4081 }
4082 },
4083 CssRule::NestedDeclarations(ref rule) => {
4084 if let Some(ancestor_selectors) =
4085 containing_rule_state.ancestor_selector_lists.last()
4086 {
4087 let decls = &rule.read_with(guard).block;
4088 let selectors = match containing_rule_state.nested_declarations_context {
4089 NestedDeclarationsContext::Style => ancestor_selectors,
4090 NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
4091 };
4092 let mut inner_dependencies: Option<Vec<Dependency>> =
4093 containing_rule_state.scope_is_effective().then(Vec::new);
4094 self.add_styles(
4095 selectors,
4096 decls,
4097 None,
4098 containing_rule_state,
4099 None,
4100 guard,
4101 SheetRebuildKind::CascadeOnly,
4104 precomputed_pseudo_element_decls.as_deref_mut(),
4105 quirks_mode,
4106 inner_dependencies.as_mut(),
4107 )?;
4108 if let Some(mut scope_dependencies) = inner_dependencies {
4109 containing_rule_state
4110 .containing_scope_rule_state
4111 .inner_dependencies
4112 .append(&mut scope_dependencies);
4113 }
4114 }
4115 },
4116 CssRule::Keyframes(ref keyframes_rule) => {
4117 debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
4118 let keyframes_rule = keyframes_rule.read_with(guard);
4119 let name = keyframes_rule.name.as_atom();
4120 let animation = KeyframesAnimation::from_keyframes(
4121 &keyframes_rule.keyframes,
4122 keyframes_rule.vendor_prefix.clone(),
4123 guard,
4124 );
4125 self.animations.try_insert_with(
4126 name,
4127 animation,
4128 containing_rule_state.layer_id,
4129 compare_keyframes_in_same_layer,
4130 )?;
4131 },
4132 CssRule::Property(ref registration) => {
4133 self.custom_property_registrations.try_insert(
4134 ®istration.name.0,
4135 Arc::clone(registration),
4136 containing_rule_state.layer_id,
4137 )?;
4138 },
4139 CssRule::FontFace(ref rule) => {
4140 self.extra_data
4151 .add_font_face(rule, containing_rule_state.layer_id);
4152 },
4153 CssRule::FontFeatureValues(ref rule) => {
4154 self.extra_data
4155 .add_font_feature_values(rule, containing_rule_state.layer_id);
4156 },
4157 CssRule::FontPaletteValues(ref rule) => {
4158 self.extra_data
4159 .add_font_palette_values(rule, containing_rule_state.layer_id);
4160 },
4161 CssRule::CounterStyle(ref rule) => {
4162 self.extra_data.add_counter_style(
4163 guard,
4164 rule,
4165 containing_rule_state.layer_id,
4166 )?;
4167 },
4168 CssRule::PositionTry(ref rule) => {
4169 let name = rule.read_with(guard).name.0.clone();
4170 if let Some(ref mut difference) = difference {
4171 difference.changed_position_try_names.insert(name.clone());
4172 }
4173 self.extra_data.add_position_try(
4174 name,
4175 rule.clone(),
4176 containing_rule_state.layer_id,
4177 )?;
4178 },
4179 CssRule::Page(ref rule) => {
4180 self.extra_data
4181 .add_page(guard, rule, containing_rule_state.layer_id)?;
4182 handled = false;
4183 },
4184 CssRule::ViewTransition(ref rule) => {
4185 self.extra_data
4186 .add_view_transition(rule, containing_rule_state.layer_id);
4187 },
4188 _ => {
4189 handled = false;
4190 },
4191 }
4192
4193 if handled {
4194 if cfg!(debug_assertions) {
4197 let mut effective = false;
4198 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4199 rule,
4200 device,
4201 quirks_mode,
4202 &self.custom_media,
4203 guard,
4204 &mut effective,
4205 );
4206 debug_assert!(children.is_empty());
4207 debug_assert!(effective);
4208 }
4209 continue;
4210 }
4211
4212 let mut effective = false;
4213 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4214 rule,
4215 device,
4216 quirks_mode,
4217 &self.custom_media,
4218 guard,
4219 &mut effective,
4220 );
4221 if !effective {
4222 continue;
4223 }
4224
4225 fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4226 if let Some(id) = data.layer_id.get(layer) {
4230 return *id;
4231 }
4232 let id = LayerId(data.layers.len() as u16);
4233
4234 let parent_layer_id = if layer.layer_names().len() > 1 {
4235 let mut parent = layer.clone();
4236 parent.0.pop();
4237
4238 *data
4239 .layer_id
4240 .get_mut(&parent)
4241 .expect("Parent layers should be registered before child layers")
4242 } else {
4243 LayerId::root()
4244 };
4245
4246 data.layers[parent_layer_id.0 as usize].children.push(id);
4247 data.layers.push(CascadeLayer {
4248 id,
4249 order: LayerOrder::first(),
4252 children: vec![],
4253 });
4254
4255 data.layer_id.insert(layer.clone(), id);
4256
4257 id
4258 }
4259
4260 fn maybe_register_layers(
4261 data: &mut CascadeData,
4262 name: Option<&LayerName>,
4263 containing_rule_state: &mut ContainingRuleState,
4264 ) {
4265 let anon_name;
4266 let name = match name {
4267 Some(name) => name,
4268 None => {
4269 anon_name = LayerName::new_anonymous();
4270 &anon_name
4271 },
4272 };
4273 for name in name.layer_names() {
4274 containing_rule_state.layer_name.0.push(name.clone());
4275 containing_rule_state.layer_id =
4276 maybe_register_layer(data, &containing_rule_state.layer_name);
4277 }
4278 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4279 }
4280
4281 let saved_containing_rule_state = containing_rule_state.save();
4282 match *rule {
4283 CssRule::Import(ref lock) => {
4284 let import_rule = lock.read_with(guard);
4285 if rebuild_kind.should_rebuild_invalidation() {
4286 self.effective_media_query_results
4287 .saw_effective(import_rule);
4288 }
4289 match import_rule.layer {
4290 ImportLayer::Named(ref name) => {
4291 maybe_register_layers(self, Some(name), containing_rule_state)
4292 },
4293 ImportLayer::Anonymous => {
4294 maybe_register_layers(self, None, containing_rule_state)
4295 },
4296 ImportLayer::None => {},
4297 }
4298 },
4299 CssRule::Media(ref media_rule) => {
4300 if rebuild_kind.should_rebuild_invalidation() {
4301 self.effective_media_query_results
4302 .saw_effective(&**media_rule);
4303 }
4304 },
4305 CssRule::LayerBlock(ref rule) => {
4306 maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4307 },
4308 CssRule::CustomMedia(ref custom_media) => {
4309 self.custom_media
4310 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4311 },
4312 CssRule::LayerStatement(ref rule) => {
4313 for name in &*rule.names {
4314 maybe_register_layers(self, Some(name), containing_rule_state);
4315 containing_rule_state.restore(&saved_containing_rule_state);
4317 }
4318 },
4319 CssRule::Style(..) => {
4320 containing_rule_state.nested_declarations_context =
4321 NestedDeclarationsContext::Style;
4322 if let Some(s) = list_for_nested_rules {
4323 containing_rule_state.ancestor_selector_lists.push(s);
4324 }
4325 },
4326 CssRule::Container(ref rule) => {
4327 let id = ContainerConditionId(self.container_conditions.len() as u16);
4328 let condition = ContainerConditionReference {
4329 parent: containing_rule_state.container_condition_id,
4330 conditions: rule.conditions.0.clone(),
4331 };
4332 self.container_conditions.push(condition);
4333 containing_rule_state.container_condition_id = id;
4334
4335 if rebuild_kind.should_rebuild_invalidation() {
4336 for condition in rule.conditions.0.iter() {
4337 condition.insert_attribute_references_in_dependency_map(
4338 &mut self.attr_function_dependencies,
4339 &mut self.attribute_dependencies,
4340 );
4341 }
4342 }
4343 },
4344 CssRule::StartingStyle(..) => {
4345 containing_rule_state
4346 .cascade_flags
4347 .insert(RuleCascadeFlags::STARTING_STYLE);
4348 },
4349 CssRule::AppearanceBase(..) => {
4350 containing_rule_state
4351 .cascade_flags
4352 .insert(RuleCascadeFlags::APPEARANCE_BASE);
4353 },
4354 CssRule::Scope(ref rule) if self.scope_conditions.len() <= u16::MAX.into() => {
4355 containing_rule_state.nested_declarations_context =
4356 NestedDeclarationsContext::Scope;
4357 let id = ScopeConditionId(self.scope_conditions.len() as u16);
4358 let mut matches_shadow_host = false;
4359 let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4360 matches_shadow_host = scope_start_matches_shadow_host(start);
4361 StylistImplicitScopeRoot::default()
4363 } else {
4364 if let Some(root) = stylesheet.implicit_scope_root() {
4367 matches_shadow_host = root.matches_shadow_host();
4368 match root {
4369 ImplicitScopeRoot::InLightTree(_)
4370 | ImplicitScopeRoot::Constructed
4371 | ImplicitScopeRoot::DocumentElement => {
4372 StylistImplicitScopeRoot::Normal(root)
4373 },
4374 ImplicitScopeRoot::ShadowHost(_)
4375 | ImplicitScopeRoot::InShadowTree(_) => {
4376 StylistImplicitScopeRoot::Cached(sheet_index)
4383 },
4384 }
4385 } else {
4386 StylistImplicitScopeRoot::default()
4388 }
4389 };
4390
4391 let replaced =
4392 {
4393 let start = rule.bounds.start.as_ref().map(|selector| {
4394 match containing_rule_state.ancestor_selector_lists.last() {
4395 Some(s) => selector.replace_parent_selector(s),
4396 None => selector.clone(),
4397 }
4398 });
4399 let implicit_scope_selector = &*IMPLICIT_SCOPE;
4400 let end = rule.bounds.end.as_ref().map(|selector| {
4401 selector.replace_parent_selector(implicit_scope_selector)
4402 });
4403 containing_rule_state
4404 .ancestor_selector_lists
4405 .push(implicit_scope_selector.clone());
4406 ScopeBoundsWithHashes::new(quirks_mode, start, end)
4407 };
4408
4409 if let Some(selectors) = replaced.start.as_ref() {
4410 self.scope_subject_map
4411 .add_bound_start(&selectors.selectors, quirks_mode);
4412 }
4413
4414 let is_trivial = replaced.is_trivial();
4415 self.scope_conditions.push(ScopeConditionReference {
4416 parent: containing_rule_state.containing_scope_rule_state.id,
4417 condition: Some(replaced),
4418 implicit_scope_root,
4419 is_trivial,
4420 });
4421
4422 containing_rule_state
4423 .containing_scope_rule_state
4424 .matches_shadow_host
4425 .nest_for_scope(matches_shadow_host);
4426 containing_rule_state.containing_scope_rule_state.id = id;
4427 containing_rule_state
4428 .containing_scope_rule_state
4429 .inner_dependencies
4430 .reserve(children.iter().len());
4431 },
4432 _ => {},
4434 }
4435
4436 if !children.is_empty() {
4437 self.add_rule_list(
4438 children.iter(),
4439 device,
4440 quirks_mode,
4441 stylesheet,
4442 sheet_index,
4443 guard,
4444 rebuild_kind,
4445 containing_rule_state,
4446 precomputed_pseudo_element_decls.as_deref_mut(),
4447 difference.as_deref_mut(),
4448 )?;
4449 }
4450
4451 if let Some(scope_restore_data) =
4452 containing_rule_state.restore(&saved_containing_rule_state)
4453 {
4454 let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4455 let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4456 if let Some(cond) = cur_scope.condition.as_ref() {
4457 let mut _unused = false;
4458 let visitor = StylistSelectorVisitor {
4459 passed_rightmost_selector: true,
4460 needs_revalidation: &mut _unused,
4461 non_link_visited_dependency: &mut self.non_link_visited_dependency,
4462 in_selector_list_of: SelectorListKind::default(),
4463 mapped_ids: &mut self.mapped_ids,
4464 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4465 attribute_dependencies: &mut self.attribute_dependencies,
4466 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4467 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4468 nth_of_custom_state_dependencies: &mut self
4469 .nth_of_custom_state_dependencies,
4470 state_dependencies: &mut self.state_dependencies,
4471 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4472 document_state_dependencies: &mut self.document_state_dependencies,
4473 };
4474
4475 let dependency_vector = build_scope_dependencies(
4476 quirks_mode,
4477 cur_scope_inner_dependencies,
4478 visitor,
4479 cond,
4480 &mut self.invalidation_map,
4481 &mut self.relative_selector_invalidation_map,
4482 &mut self.additional_relative_selector_invalidation_map,
4483 )?;
4484
4485 containing_rule_state
4486 .containing_scope_rule_state
4487 .inner_dependencies
4488 .extend(dependency_vector);
4489 }
4490 }
4491 }
4492
4493 Ok(())
4494 }
4495
4496 fn add_stylesheet<S>(
4498 &mut self,
4499 device: &Device,
4500 quirks_mode: QuirksMode,
4501 stylesheet: &S,
4502 sheet_index: usize,
4503 guard: &SharedRwLockReadGuard,
4504 rebuild_kind: SheetRebuildKind,
4505 precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4506 difference: Option<&mut CascadeDataDifference>,
4507 ) -> Result<(), AllocErr>
4508 where
4509 S: StylesheetInDocument + 'static,
4510 {
4511 if !stylesheet.enabled() {
4512 return Ok(());
4513 }
4514
4515 if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4516 return Ok(());
4517 }
4518
4519 let contents = stylesheet.contents(guard);
4520 if rebuild_kind.should_rebuild_invalidation() {
4521 self.effective_media_query_results.saw_effective(contents);
4522 }
4523
4524 let mut state = ContainingRuleState::default();
4525 self.add_rule_list(
4526 contents.rules(guard).iter(),
4527 device,
4528 quirks_mode,
4529 stylesheet,
4530 sheet_index,
4531 guard,
4532 rebuild_kind,
4533 &mut state,
4534 precomputed_pseudo_element_decls,
4535 difference,
4536 )?;
4537
4538 Ok(())
4539 }
4540
4541 pub fn media_feature_affected_matches<S>(
4544 &self,
4545 stylesheet: &S,
4546 guard: &SharedRwLockReadGuard,
4547 device: &Device,
4548 quirks_mode: QuirksMode,
4549 ) -> bool
4550 where
4551 S: StylesheetInDocument + 'static,
4552 {
4553 use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4554
4555 let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4556
4557 let contents = stylesheet.contents(guard);
4558 let effective_then = self.effective_media_query_results.was_effective(contents);
4559
4560 if effective_now != effective_then {
4561 debug!(
4562 " > Stylesheet {:?} changed -> {}, {}",
4563 stylesheet.media(guard),
4564 effective_then,
4565 effective_now
4566 );
4567 return false;
4568 }
4569
4570 if !effective_now {
4571 return true;
4572 }
4573
4574 let custom_media = CustomMediaMap::default();
4576 let mut iter =
4577 contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4578 while let Some(rule) = iter.next() {
4579 match *rule {
4580 CssRule::Style(..)
4581 | CssRule::NestedDeclarations(..)
4582 | CssRule::Namespace(..)
4583 | CssRule::FontFace(..)
4584 | CssRule::Container(..)
4585 | CssRule::CounterStyle(..)
4586 | CssRule::Supports(..)
4587 | CssRule::Keyframes(..)
4588 | CssRule::Margin(..)
4589 | CssRule::Page(..)
4590 | CssRule::Property(..)
4591 | CssRule::Document(..)
4592 | CssRule::LayerBlock(..)
4593 | CssRule::LayerStatement(..)
4594 | CssRule::FontPaletteValues(..)
4595 | CssRule::FontFeatureValues(..)
4596 | CssRule::Scope(..)
4597 | CssRule::StartingStyle(..)
4598 | CssRule::AppearanceBase(..)
4599 | CssRule::CustomMedia(..)
4600 | CssRule::PositionTry(..)
4601 | CssRule::ViewTransition(..) => {
4602 continue;
4605 },
4606 CssRule::Import(ref lock) => {
4607 let import_rule = lock.read_with(guard);
4608 let effective_now = match import_rule.stylesheet.media(guard) {
4609 Some(m) => m.evaluate(
4610 device,
4611 quirks_mode,
4612 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4613 ),
4614 None => true,
4615 };
4616 let effective_then = self
4617 .effective_media_query_results
4618 .was_effective(import_rule);
4619 if effective_now != effective_then {
4620 debug!(
4621 " > @import rule {:?} changed {} -> {}",
4622 import_rule.stylesheet.media(guard),
4623 effective_then,
4624 effective_now
4625 );
4626 return false;
4627 }
4628
4629 if !effective_now {
4630 iter.skip_children();
4631 }
4632 },
4633 CssRule::Media(ref media_rule) => {
4634 let mq = media_rule.media_queries.read_with(guard);
4635 let effective_now = mq.evaluate(
4636 device,
4637 quirks_mode,
4638 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4639 );
4640 let effective_then = self
4641 .effective_media_query_results
4642 .was_effective(&**media_rule);
4643
4644 if effective_now != effective_then {
4645 debug!(
4646 " > @media rule {:?} changed {} -> {}",
4647 mq, effective_then, effective_now
4648 );
4649 return false;
4650 }
4651
4652 if !effective_now {
4653 iter.skip_children();
4654 }
4655 },
4656 }
4657 }
4658
4659 true
4660 }
4661
4662 pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4664 &self.custom_property_registrations
4665 }
4666
4667 fn revalidate_scopes<E: TElement>(
4668 &self,
4669 element: &E,
4670 matching_context: &mut MatchingContext<E::Impl>,
4671 result: &mut ScopeRevalidationResult,
4672 ) {
4673 for condition_id in 1..self.scope_conditions.len() {
4680 let condition = &self.scope_conditions[condition_id];
4681 let matches = if condition.is_trivial {
4682 continue;
4685 } else {
4686 let result = scope_root_candidates(
4687 &self.scope_conditions,
4688 ScopeConditionId(condition_id as u16),
4689 element,
4690 false,
4692 &self.scope_subject_map,
4693 matching_context,
4694 );
4695 !result.candidates.is_empty()
4696 };
4697 result.scopes_matched.push(matches);
4698 }
4699 }
4700
4701 fn clear_cascade_data(&mut self) {
4703 self.normal_rules.clear();
4704 if let Some(ref mut slotted_rules) = self.slotted_rules {
4705 slotted_rules.clear();
4706 }
4707 if let Some(ref mut part_rules) = self.part_rules {
4708 part_rules.clear();
4709 }
4710 if let Some(ref mut host_rules) = self.featureless_host_rules {
4711 host_rules.clear();
4712 }
4713 self.animations.clear();
4714 self.custom_property_registrations.clear();
4715 self.layer_id.clear();
4716 self.layers.clear();
4717 self.layers.push(CascadeLayer::root());
4718 self.custom_media.clear();
4719 self.container_conditions.clear();
4720 self.container_conditions
4721 .push(ContainerConditionReference::none());
4722 self.scope_conditions.clear();
4723 self.scope_conditions.push(ScopeConditionReference::none());
4724 self.extra_data.clear();
4725 self.rules_source_order = 0;
4726 self.num_selectors = 0;
4727 self.num_declarations = 0;
4728 }
4729
4730 fn clear_invalidation_data(&mut self) {
4731 self.invalidation_map.clear();
4732 self.relative_selector_invalidation_map.clear();
4733 self.additional_relative_selector_invalidation_map.clear();
4734 self.attribute_dependencies.clear();
4735 self.attr_function_dependencies.clear();
4736 self.nth_of_attribute_dependencies.clear();
4737 self.nth_of_custom_state_dependencies.clear();
4738 self.nth_of_class_dependencies.clear();
4739 self.state_dependencies = ElementState::empty();
4740 self.nth_of_state_dependencies = ElementState::empty();
4741 self.non_link_visited_dependency = false;
4742 self.document_state_dependencies = DocumentState::empty();
4743 self.mapped_ids.clear();
4744 self.nth_of_mapped_ids.clear();
4745 self.selectors_for_cache_revalidation.clear();
4746 self.effective_media_query_results.clear();
4747 self.scope_subject_map.clear();
4748 }
4749}
4750
4751fn note_scope_selector_for_invalidation(
4752 quirks_mode: QuirksMode,
4753 scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4754 dependency_vector: &mut Vec<Dependency>,
4755 invalidation_map: &mut InvalidationMap,
4756 relative_selector_invalidation_map: &mut InvalidationMap,
4757 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4758 visitor: &mut StylistSelectorVisitor<'_>,
4759 scope_kind: ScopeDependencyInvalidationKind,
4760 s: &Selector<SelectorImpl>,
4761) -> Result<(), AllocErr> {
4762 let mut new_inner_dependencies = note_selector_for_invalidation(
4763 &s.clone(),
4764 quirks_mode,
4765 invalidation_map,
4766 relative_selector_invalidation_map,
4767 additional_relative_selector_invalidation_map,
4768 Some(scope_dependencies),
4769 Some(scope_kind),
4770 )?;
4771 s.visit(visitor);
4772 if let Some(dep) = new_inner_dependencies.as_mut() {
4773 dependency_vector.append(dep);
4774 }
4775 Ok(())
4776}
4777
4778fn build_scope_dependencies(
4779 quirks_mode: QuirksMode,
4780 mut cur_scope_inner_dependencies: Vec<Dependency>,
4781 mut visitor: StylistSelectorVisitor<'_>,
4782 cond: &ScopeBoundsWithHashes,
4783 invalidation_map: &mut InvalidationMap,
4784 relative_selector_invalidation_map: &mut InvalidationMap,
4785 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4786) -> Result<Vec<Dependency>, AllocErr> {
4787 if cond.end.is_some() {
4788 let deps =
4789 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4790 let mut end_dependency_vector = Vec::new();
4791 for s in cond.end_selectors() {
4792 note_scope_selector_for_invalidation(
4793 quirks_mode,
4794 &deps,
4795 &mut end_dependency_vector,
4796 invalidation_map,
4797 relative_selector_invalidation_map,
4798 additional_relative_selector_invalidation_map,
4799 &mut visitor,
4800 ScopeDependencyInvalidationKind::ScopeEnd,
4801 s,
4802 )?;
4803 }
4804 cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4805 }
4806 let inner_scope_dependencies =
4807 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4808
4809 Ok(if cond.start.is_some() {
4810 let mut dependency_vector = Vec::new();
4811 for s in cond.start_selectors() {
4812 note_scope_selector_for_invalidation(
4813 quirks_mode,
4814 &inner_scope_dependencies,
4815 &mut dependency_vector,
4816 invalidation_map,
4817 relative_selector_invalidation_map,
4818 additional_relative_selector_invalidation_map,
4819 &mut visitor,
4820 ScopeDependencyInvalidationKind::ExplicitScope,
4821 s,
4822 )?;
4823 }
4824 dependency_vector
4825 } else {
4826 vec![Dependency::new(
4827 IMPLICIT_SCOPE.slice()[0].clone(),
4828 0,
4829 Some(inner_scope_dependencies),
4830 DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4831 )]
4832 })
4833}
4834
4835impl CascadeDataCacheEntry for CascadeData {
4836 fn rebuild<S>(
4837 device: &Device,
4838 quirks_mode: QuirksMode,
4839 collection: SheetCollectionFlusher<S>,
4840 guard: &SharedRwLockReadGuard,
4841 old: &Self,
4842 difference: &mut CascadeDataDifference,
4843 ) -> Result<Arc<Self>, AllocErr>
4844 where
4845 S: StylesheetInDocument + PartialEq + 'static,
4846 {
4847 debug_assert!(collection.dirty(), "We surely need to do something?");
4848 let mut updatable_entry = match collection.data_validity() {
4850 DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4851 DataValidity::FullyInvalid => Self::new(),
4852 };
4853 updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4854 Ok(Arc::new(updatable_entry))
4855 }
4856
4857 #[cfg(feature = "gecko")]
4858 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4859 self.normal_rules.add_size_of(ops, sizes);
4860 if let Some(ref slotted_rules) = self.slotted_rules {
4861 slotted_rules.add_size_of(ops, sizes);
4862 }
4863 if let Some(ref part_rules) = self.part_rules {
4864 part_rules.add_size_of(ops, sizes);
4865 }
4866 if let Some(ref host_rules) = self.featureless_host_rules {
4867 host_rules.add_size_of(ops, sizes);
4868 }
4869 sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4870 sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4871 sizes.mOther += self.animations.size_of(ops);
4872 sizes.mOther += self.effective_media_query_results.size_of(ops);
4873 sizes.mOther += self.extra_data.size_of(ops);
4874 }
4875}
4876
4877impl Default for CascadeData {
4878 fn default() -> Self {
4879 CascadeData::new()
4880 }
4881}
4882
4883#[derive(Clone, Debug, MallocSizeOf)]
4886pub struct Rule {
4887 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4892 pub selector: Selector<SelectorImpl>,
4893
4894 pub hashes: AncestorHashes,
4896
4897 pub source_order: u32,
4901
4902 pub layer_id: LayerId,
4904
4905 pub container_condition_id: ContainerConditionId,
4907
4908 pub cascade_flags: RuleCascadeFlags,
4910
4911 pub scope_condition_id: ScopeConditionId,
4913
4914 pub bucket_matches: BucketMatches,
4916
4917 #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4919 pub style_source: StyleSource,
4920}
4921
4922impl SelectorMapEntry for Rule {
4923 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4924 self.selector.iter()
4925 }
4926
4927 fn set_bucket_matches(&mut self, bucket_matches: BucketMatches) {
4928 self.bucket_matches = bucket_matches;
4929 }
4930}
4931
4932impl Rule {
4933 pub fn specificity(&self) -> u32 {
4935 self.selector.specificity()
4936 }
4937
4938 pub fn to_applicable_declaration_block(
4941 &self,
4942 level: CascadeLevel,
4943 cascade_data: &CascadeData,
4944 scope_proximity: ScopeProximity,
4945 ) -> ApplicableDeclarationBlock {
4946 ApplicableDeclarationBlock::new(
4947 self.style_source.clone(),
4948 self.source_order,
4949 level,
4950 self.specificity(),
4951 cascade_data.layer_order_for(self.layer_id),
4952 scope_proximity,
4953 self.cascade_flags,
4954 )
4955 }
4956
4957 pub fn new(
4959 selector: Selector<SelectorImpl>,
4960 hashes: AncestorHashes,
4961 style_source: StyleSource,
4962 source_order: u32,
4963 layer_id: LayerId,
4964 container_condition_id: ContainerConditionId,
4965 cascade_flags: RuleCascadeFlags,
4966 scope_condition_id: ScopeConditionId,
4967 ) -> Self {
4968 Self {
4969 selector,
4970 hashes,
4971 style_source,
4972 source_order,
4973 layer_id,
4974 container_condition_id,
4975 cascade_flags,
4976 scope_condition_id,
4977 bucket_matches: BucketMatches::Unknown,
4978 }
4979 }
4980
4981 fn iter_past_subject<'a, E: TElement>(
4982 selector: &'a Selector<SelectorImpl>,
4983 mut element: E,
4984 context: &mut MatchingContext<E::Impl>,
4985 ) -> (E, SelectorIter<'a, SelectorImpl>) {
4986 let mut offset = 0;
4987 let mut skipped_pseudo = false;
4988 let mut iter = selector.iter();
4991 loop {
4992 for _ in &mut iter {
4993 offset += 1;
4994 }
4995 if iter.next_sequence() != Some(Combinator::PseudoElement) {
4996 break;
4997 }
4998 if skipped_pseudo || context.matching_mode() != MatchingMode::ForStatelessPseudoElement
4999 {
5000 element = element.pseudo_element_originating_element().unwrap();
5001 }
5002 skipped_pseudo = true;
5003 offset += 1;
5004 }
5005 (element, selector.iter_from(offset))
5006 }
5007
5008 #[inline(always)]
5010 pub fn matches_selector<E: TElement>(
5011 &self,
5012 mut element: E,
5013 context: &mut MatchingContext<E::Impl>,
5014 ) -> bool {
5015 if context
5016 .bloom_filter
5017 .is_some_and(|f| !selector_may_match(&self.hashes, f))
5018 {
5019 return false;
5020 }
5021 if self.bucket_matches == BucketMatches::Full {
5022 return true;
5023 }
5024 let mut iter = self.selector.iter();
5025 let mut subject = SubjectOrPseudoElement::Yes;
5026 if self.bucket_matches == BucketMatches::Subject {
5027 (element, iter) = Self::iter_past_subject(&self.selector, element, context);
5028 subject = SubjectOrPseudoElement::No;
5029 }
5030 matches_complex_selector(iter, element, context, subject).to_bool(true)
5031 }
5032}
5033
5034size_of_test!(Rule, 40);
5039
5040pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
5042 let mut needs_revalidation = false;
5043 let mut mapped_ids = Default::default();
5044 let mut nth_of_mapped_ids = Default::default();
5045 let mut attribute_dependencies = Default::default();
5046 let mut nth_of_class_dependencies = Default::default();
5047 let mut nth_of_attribute_dependencies = Default::default();
5048 let mut nth_of_custom_state_dependencies = Default::default();
5049 let mut state_dependencies = ElementState::empty();
5050 let mut nth_of_state_dependencies = ElementState::empty();
5051 let mut document_state_dependencies = DocumentState::empty();
5052 let mut non_link_visited_dependency = false;
5053 let mut visitor = StylistSelectorVisitor {
5054 passed_rightmost_selector: false,
5055 needs_revalidation: &mut needs_revalidation,
5056 non_link_visited_dependency: &mut non_link_visited_dependency,
5057 in_selector_list_of: SelectorListKind::default(),
5058 mapped_ids: &mut mapped_ids,
5059 nth_of_mapped_ids: &mut nth_of_mapped_ids,
5060 attribute_dependencies: &mut attribute_dependencies,
5061 nth_of_class_dependencies: &mut nth_of_class_dependencies,
5062 nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
5063 nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
5064 state_dependencies: &mut state_dependencies,
5065 nth_of_state_dependencies: &mut nth_of_state_dependencies,
5066 document_state_dependencies: &mut document_state_dependencies,
5067 };
5068 s.visit(&mut visitor);
5069 needs_revalidation
5070}