1use crate::applicable_declarations::{
8 ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority, ScopeProximity,
9};
10use crate::computed_value_flags::ComputedValueFlags;
11use crate::context::{CascadeInputs, QuirksMode};
12use crate::custom_properties::ComputedCustomProperties;
13use crate::custom_properties::{parse_name, SpecifiedValue};
14use crate::derives::*;
15use crate::device::Device;
16use crate::dom::TElement;
17#[cfg(feature = "gecko")]
18use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
19use crate::invalidation::element::invalidation_map::{
20 note_selector_for_invalidation, AdditionalRelativeSelectorInvalidationMap, Dependency,
21 DependencyInvalidationKind, InvalidationMap, ScopeDependencyInvalidationKind,
22};
23use crate::invalidation::media_queries::{
24 EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
25};
26use crate::invalidation::stylesheets::{RuleChangeKind, StylesheetInvalidationSet};
27#[cfg(feature = "gecko")]
28use crate::properties::StyleBuilder;
29use crate::properties::{
30 self, AnimationDeclarations, CascadeMode, ComputedValues, FirstLineReparenting,
31 PropertyDeclarationBlock,
32};
33use crate::properties_and_values::registry::{
34 PropertyRegistration, ScriptRegistry as CustomPropertyScriptRegistry,
35};
36use crate::properties_and_values::rule::{
37 Descriptors as PropertyDescriptors, Inherits, PropertyRegistrationError, PropertyRuleName,
38};
39use crate::properties_and_values::syntax::Descriptor;
40use crate::rule_cache::{RuleCache, RuleCacheConditions};
41use crate::rule_collector::RuleCollector;
42use crate::rule_tree::{
43 CascadeLevel, CascadeOrigin, RuleCascadeFlags, RuleTree, StrongRuleNode, StyleSource,
44};
45use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
46use crate::selector_parser::{NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl};
47use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
48use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
49use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
50use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
51use crate::stylesheets::container_rule::ContainerCondition;
52use crate::stylesheets::import_rule::ImportLayer;
53use crate::stylesheets::keyframes_rule::KeyframesAnimation;
54use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
55use crate::stylesheets::scope_rule::{
56 collect_scope_roots, element_is_outside_of_scope, scope_selector_list_is_trivial,
57 ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget,
58};
59use crate::stylesheets::UrlExtraData;
60use crate::stylesheets::{
61 CounterStyleRule, CssRule, CssRuleRef, EffectiveRulesIterator, FontFaceRule,
62 FontFeatureValuesRule, FontPaletteValuesRule, Origin, OriginSet, PagePseudoClassFlags,
63 PageRule, PerOrigin, PerOriginIter, PositionTryRule, StylesheetContents, StylesheetInDocument,
64 ViewTransitionRule,
65};
66use crate::stylesheets::{CustomMediaEvaluator, CustomMediaMap};
67#[cfg(feature = "gecko")]
68use crate::values::specified::position::PositionTryFallbacksItem;
69use crate::values::specified::position::PositionTryFallbacksTryTactic;
70use crate::values::{computed, AtomIdent, Parser, SourceLocation};
71use crate::AllocErr;
72use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
73use crate::ArcSlice;
74use cssparser::ParserInput;
75use dom::{DocumentState, ElementState};
76#[cfg(feature = "gecko")]
77use malloc_size_of::MallocUnconditionalShallowSizeOf;
78use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
79use rustc_hash::FxHashMap;
80use selectors::attr::{CaseSensitivity, NamespaceConstraint};
81use selectors::bloom::BloomFilter;
82use selectors::matching::{
83 matches_selector, selector_may_match, MatchingContext, MatchingMode, NeedsSelectorFlags,
84 SelectorCaches,
85};
86use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
87use selectors::parser::{
88 AncestorHashes, Combinator, Component, MatchesFeaturelessHost, Selector, SelectorIter,
89 SelectorList,
90};
91use selectors::visitor::{SelectorListKind, SelectorVisitor};
92use servo_arc::{Arc, ArcBorrow, ThinArc};
93use smallvec::SmallVec;
94use std::cmp::Ordering;
95use std::hash::{Hash, Hasher};
96use std::mem;
97use std::sync::{LazyLock, Mutex};
98
99#[cfg(feature = "servo")]
101pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
102
103#[cfg(feature = "gecko")]
105pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
106
107#[derive(Debug, Clone)]
108struct StylesheetContentsPtr(Arc<StylesheetContents>);
109
110impl PartialEq for StylesheetContentsPtr {
111 #[inline]
112 fn eq(&self, other: &Self) -> bool {
113 Arc::ptr_eq(&self.0, &other.0)
114 }
115}
116
117impl Eq for StylesheetContentsPtr {}
118
119impl Hash for StylesheetContentsPtr {
120 fn hash<H: Hasher>(&self, state: &mut H) {
121 let contents: &StylesheetContents = &*self.0;
122 (contents as *const StylesheetContents).hash(state)
123 }
124}
125
126type StyleSheetContentList = Vec<StylesheetContentsPtr>;
127
128#[derive(Default, Debug, MallocSizeOf)]
130pub struct CascadeDataDifference {
131 pub changed_position_try_names: PrecomputedHashSet<Atom>,
133}
134
135impl CascadeDataDifference {
136 pub fn merge_with(&mut self, other: Self) {
138 self.changed_position_try_names
139 .extend(other.changed_position_try_names.into_iter())
140 }
141
142 pub fn is_empty(&self) -> bool {
144 self.changed_position_try_names.is_empty()
145 }
146
147 fn update(&mut self, old_data: &PositionTryMap, new_data: &PositionTryMap) {
148 let mut any_different_key = false;
149 let different_len = old_data.len() != new_data.len();
150 for (name, rules) in old_data.iter() {
151 let changed = match new_data.get(name) {
152 Some(new_rule) => !Arc::ptr_eq(&rules.last().unwrap().0, new_rule),
153 None => {
154 any_different_key = true;
155 true
156 },
157 };
158 if changed {
159 self.changed_position_try_names.insert(name.clone());
160 }
161 }
162
163 if any_different_key || different_len {
164 for name in new_data.keys() {
165 if !old_data.contains_key(name) {
167 self.changed_position_try_names.insert(name.clone());
168 }
169 }
170 }
171 }
172}
173
174#[derive(Debug, Hash, Default, PartialEq, Eq)]
176struct CascadeDataCacheKey {
177 media_query_results: Vec<MediaListKey>,
178 contents: StyleSheetContentList,
179}
180
181unsafe impl Send for CascadeDataCacheKey {}
182unsafe impl Sync for CascadeDataCacheKey {}
183
184trait CascadeDataCacheEntry: Sized {
185 fn rebuild<S>(
188 device: &Device,
189 quirks_mode: QuirksMode,
190 collection: SheetCollectionFlusher<S>,
191 guard: &SharedRwLockReadGuard,
192 old_entry: &Self,
193 difference: &mut CascadeDataDifference,
194 ) -> Result<Arc<Self>, AllocErr>
195 where
196 S: StylesheetInDocument + PartialEq + 'static;
197 #[cfg(feature = "gecko")]
199 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
200}
201
202struct CascadeDataCache<Entry> {
203 entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
204}
205
206impl<Entry> CascadeDataCache<Entry>
207where
208 Entry: CascadeDataCacheEntry,
209{
210 fn new() -> Self {
211 Self {
212 entries: Default::default(),
213 }
214 }
215
216 fn len(&self) -> usize {
217 self.entries.len()
218 }
219
220 fn lookup<'a, S>(
225 &'a mut self,
226 device: &Device,
227 quirks_mode: QuirksMode,
228 collection: SheetCollectionFlusher<S>,
229 guard: &SharedRwLockReadGuard,
230 old_entry: &Entry,
231 difference: &mut CascadeDataDifference,
232 ) -> Result<Option<Arc<Entry>>, AllocErr>
233 where
234 S: StylesheetInDocument + PartialEq + 'static,
235 {
236 use std::collections::hash_map::Entry as HashMapEntry;
237 debug!("StyleSheetCache::lookup({})", self.len());
238
239 if !collection.dirty() {
240 return Ok(None);
241 }
242
243 let mut key = CascadeDataCacheKey::default();
244 let mut custom_media_map = CustomMediaMap::default();
245 for sheet in collection.sheets() {
246 CascadeData::collect_applicable_media_query_results_into(
247 device,
248 sheet,
249 guard,
250 &mut key.media_query_results,
251 &mut key.contents,
252 &mut custom_media_map,
253 )
254 }
255
256 let new_entry;
257 match self.entries.entry(key) {
258 HashMapEntry::Vacant(e) => {
259 debug!("> Picking the slow path (not in the cache)");
260 new_entry = Entry::rebuild(
261 device,
262 quirks_mode,
263 collection,
264 guard,
265 old_entry,
266 difference,
267 )?;
268 e.insert(new_entry.clone());
269 },
270 HashMapEntry::Occupied(mut e) => {
271 if !std::ptr::eq(&**e.get(), old_entry) {
275 if log_enabled!(log::Level::Debug) {
276 debug!("cache hit for:");
277 for sheet in collection.sheets() {
278 debug!(" > {:?}", sheet);
279 }
280 }
281 collection.each(|_, _, _| true);
284 return Ok(Some(e.get().clone()));
285 }
286
287 debug!("> Picking the slow path due to same entry as old");
288 new_entry = Entry::rebuild(
289 device,
290 quirks_mode,
291 collection,
292 guard,
293 old_entry,
294 difference,
295 )?;
296 e.insert(new_entry.clone());
297 },
298 }
299
300 Ok(Some(new_entry))
301 }
302
303 fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
311 let mut unused = SmallVec::new();
312 self.entries.retain(|_key, value| {
313 if !value.is_unique() {
317 return true;
318 }
319 unused.push(value.clone());
320 false
321 });
322 unused
323 }
324
325 fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
326 mem::take(&mut self.entries)
327 }
328
329 #[cfg(feature = "gecko")]
330 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
331 sizes.mOther += self.entries.shallow_size_of(ops);
332 for (_key, arc) in self.entries.iter() {
333 sizes.mOther += arc.unconditional_shallow_size_of(ops);
336 arc.add_size_of(ops, sizes);
337 }
338 }
339}
340
341#[cfg(feature = "gecko")]
343pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
344 UA_CASCADE_DATA_CACHE
345 .lock()
346 .unwrap()
347 .add_size_of(ops, sizes);
348}
349
350static UA_CASCADE_DATA_CACHE: LazyLock<Mutex<UserAgentCascadeDataCache>> =
352 LazyLock::new(|| Mutex::new(UserAgentCascadeDataCache::new()));
353
354impl CascadeDataCacheEntry for UserAgentCascadeData {
355 fn rebuild<S>(
356 device: &Device,
357 quirks_mode: QuirksMode,
358 collection: SheetCollectionFlusher<S>,
359 guard: &SharedRwLockReadGuard,
360 old: &Self,
361 difference: &mut CascadeDataDifference,
362 ) -> Result<Arc<Self>, AllocErr>
363 where
364 S: StylesheetInDocument + PartialEq + 'static,
365 {
366 let mut new_data = servo_arc::UniqueArc::new(Self {
369 cascade_data: CascadeData::new(),
370 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
371 });
372
373 for (index, sheet) in collection.sheets().enumerate() {
374 let new_data = &mut *new_data;
375 new_data.cascade_data.add_stylesheet(
376 device,
377 quirks_mode,
378 sheet,
379 index,
380 guard,
381 SheetRebuildKind::Full,
382 Some(&mut new_data.precomputed_pseudo_element_decls),
383 None,
384 )?;
385 }
386
387 new_data.cascade_data.did_finish_rebuild();
388 difference.update(
389 &old.cascade_data.extra_data.position_try_rules,
390 &new_data.cascade_data.extra_data.position_try_rules,
391 );
392
393 Ok(new_data.shareable())
394 }
395
396 #[cfg(feature = "gecko")]
397 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
398 self.cascade_data.add_size_of(ops, sizes);
399 sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
400 }
401}
402
403type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
404
405type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
406
407#[derive(Default)]
408struct UserAgentCascadeData {
409 cascade_data: CascadeData,
410
411 precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
418}
419
420static EMPTY_UA_CASCADE_DATA: LazyLock<Arc<UserAgentCascadeData>> = LazyLock::new(|| {
422 let arc = Arc::new(UserAgentCascadeData::default());
423 arc.mark_as_intentionally_leaked();
424 arc
425});
426
427#[derive(MallocSizeOf)]
430pub struct DocumentCascadeData {
431 #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
432 user_agent: Arc<UserAgentCascadeData>,
433 user: CascadeData,
434 author: CascadeData,
435 per_origin: PerOrigin<()>,
436}
437
438impl Default for DocumentCascadeData {
439 fn default() -> Self {
440 Self {
441 user_agent: EMPTY_UA_CASCADE_DATA.clone(),
442 user: Default::default(),
443 author: Default::default(),
444 per_origin: Default::default(),
445 }
446 }
447}
448
449pub struct DocumentCascadeDataIter<'a> {
451 iter: PerOriginIter<'a, ()>,
452 cascade_data: &'a DocumentCascadeData,
453}
454
455impl<'a> Iterator for DocumentCascadeDataIter<'a> {
456 type Item = (&'a CascadeData, Origin);
457
458 fn next(&mut self) -> Option<Self::Item> {
459 let (_, origin) = self.iter.next()?;
460 Some((self.cascade_data.borrow_for_origin(origin), origin))
461 }
462}
463
464impl DocumentCascadeData {
465 #[inline]
467 pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
468 match origin {
469 Origin::UserAgent => &self.user_agent.cascade_data,
470 Origin::Author => &self.author,
471 Origin::User => &self.user,
472 }
473 }
474
475 fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
476 DocumentCascadeDataIter {
477 iter: self.per_origin.iter_origins(),
478 cascade_data: self,
479 }
480 }
481
482 fn iter_origins_rev(&self) -> DocumentCascadeDataIter<'_> {
483 DocumentCascadeDataIter {
484 iter: self.per_origin.iter_origins_rev(),
485 cascade_data: self,
486 }
487 }
488
489 fn custom_media_for_sheet(
490 &self,
491 s: &StylistSheet,
492 guard: &SharedRwLockReadGuard,
493 ) -> &CustomMediaMap {
494 let origin = s.contents(guard).origin;
495 &self.borrow_for_origin(origin).custom_media
496 }
497
498 fn rebuild<'a, S>(
502 &mut self,
503 device: &Device,
504 quirks_mode: QuirksMode,
505 mut flusher: DocumentStylesheetFlusher<'a, S>,
506 guards: &StylesheetGuards,
507 difference: &mut CascadeDataDifference,
508 ) -> Result<(), AllocErr>
509 where
510 S: StylesheetInDocument + PartialEq + 'static,
511 {
512 {
514 let origin_flusher = flusher.flush_origin(Origin::UserAgent);
515 if origin_flusher.dirty() {
518 let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
519 let new_data = ua_cache.lookup(
520 device,
521 quirks_mode,
522 origin_flusher,
523 guards.ua_or_user,
524 &self.user_agent,
525 difference,
526 )?;
527 if let Some(new_data) = new_data {
528 self.user_agent = new_data;
529 }
530 let _unused_entries = ua_cache.take_unused();
531 std::mem::drop(ua_cache);
533 }
534 }
535
536 self.user.rebuild(
538 device,
539 quirks_mode,
540 flusher.flush_origin(Origin::User),
541 guards.ua_or_user,
542 difference,
543 )?;
544
545 self.author.rebuild(
547 device,
548 quirks_mode,
549 flusher.flush_origin(Origin::Author),
550 guards.author,
551 difference,
552 )?;
553
554 Ok(())
555 }
556
557 #[cfg(feature = "gecko")]
559 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
560 self.user.add_size_of(ops, sizes);
561 self.author.add_size_of(ops, sizes);
562 }
563}
564
565#[allow(missing_docs)]
569#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
570pub enum AuthorStylesEnabled {
571 Yes,
572 No,
573}
574
575#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
578#[derive(Deref, DerefMut)]
579struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
580unsafe impl Sync for StylistStylesheetSet {}
582
583impl StylistStylesheetSet {
584 fn new() -> Self {
585 StylistStylesheetSet(DocumentStylesheetSet::new())
586 }
587}
588
589#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
597pub struct Stylist {
598 device: Device,
611
612 stylesheets: StylistStylesheetSet,
614
615 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "XXX: how to handle this?")]
617 author_data_cache: CascadeDataCache<CascadeData>,
618
619 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
621 quirks_mode: QuirksMode,
622
623 cascade_data: DocumentCascadeData,
627
628 author_styles_enabled: AuthorStylesEnabled,
630
631 rule_tree: RuleTree,
633
634 script_custom_properties: CustomPropertyScriptRegistry,
637
638 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
640 initial_values_for_custom_properties: ComputedCustomProperties,
641
642 initial_values_for_custom_properties_flags: ComputedValueFlags,
644
645 num_rebuilds: usize,
647}
648
649#[derive(Clone, Copy, PartialEq)]
651pub enum RuleInclusion {
652 All,
655 DefaultOnly,
658}
659
660#[cfg(feature = "gecko")]
661impl From<StyleRuleInclusion> for RuleInclusion {
662 fn from(value: StyleRuleInclusion) -> Self {
663 match value {
664 StyleRuleInclusion::All => RuleInclusion::All,
665 StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
666 }
667 }
668}
669
670#[derive(Clone, Copy, Eq, PartialEq)]
675enum ScopeMatchesShadowHost {
676 NotApplicable,
677 No,
678 Yes,
679}
680
681impl Default for ScopeMatchesShadowHost {
682 fn default() -> Self {
683 Self::NotApplicable
684 }
685}
686
687impl ScopeMatchesShadowHost {
688 fn nest_for_scope(&mut self, matches_shadow_host: bool) {
689 match *self {
690 Self::NotApplicable => {
691 *self = if matches_shadow_host {
693 Self::Yes
694 } else {
695 Self::No
696 };
697 },
698 Self::Yes if !matches_shadow_host => {
699 *self = Self::No;
701 },
702 _ => (),
703 }
704 }
705}
706
707#[derive(Copy, Clone)]
714enum NestedDeclarationsContext {
715 Style,
716 Scope,
717}
718
719struct ContainingScopeRuleState {
721 id: ScopeConditionId,
722 inner_dependencies: Vec<Dependency>,
723 matches_shadow_host: ScopeMatchesShadowHost,
724}
725
726impl Default for ContainingScopeRuleState {
727 fn default() -> Self {
728 Self {
729 id: ScopeConditionId::none(),
730 inner_dependencies: Vec::new(),
731 matches_shadow_host: Default::default(),
732 }
733 }
734}
735
736impl ContainingScopeRuleState {
737 fn save(&self) -> SavedContainingScopeRuleState {
738 SavedContainingScopeRuleState {
739 id: self.id,
740 matches_shadow_host: self.matches_shadow_host,
741 inner_dependencies_len: self.inner_dependencies.len(),
742 }
743 }
744
745 fn restore(
746 &mut self,
747 saved: &SavedContainingScopeRuleState,
748 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
749 debug_assert!(self.inner_dependencies.len() >= saved.inner_dependencies_len);
750
751 if self.id == saved.id {
752 return None;
753 }
754
755 let scope_id = self.id;
756 let inner_deps = self
757 .inner_dependencies
758 .drain(saved.inner_dependencies_len..)
759 .collect();
760
761 self.id = saved.id;
762 self.matches_shadow_host = saved.matches_shadow_host;
763
764 Some((inner_deps, scope_id))
765 }
766}
767
768struct SavedContainingScopeRuleState {
769 id: ScopeConditionId,
770 matches_shadow_host: ScopeMatchesShadowHost,
771 inner_dependencies_len: usize,
772}
773
774struct ContainingRuleState {
777 layer_name: LayerName,
778 layer_id: LayerId,
779 container_condition_id: ContainerConditionId,
780 cascade_flags: RuleCascadeFlags,
781 containing_scope_rule_state: ContainingScopeRuleState,
782 ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
783 nested_declarations_context: NestedDeclarationsContext,
784}
785
786impl Default for ContainingRuleState {
787 fn default() -> Self {
788 Self {
789 layer_name: LayerName::new_empty(),
790 layer_id: LayerId::root(),
791 container_condition_id: ContainerConditionId::none(),
792 cascade_flags: RuleCascadeFlags::empty(),
793 ancestor_selector_lists: Default::default(),
794 containing_scope_rule_state: Default::default(),
795 nested_declarations_context: NestedDeclarationsContext::Style,
796 }
797 }
798}
799
800struct SavedContainingRuleState {
801 ancestor_selector_lists_len: usize,
802 layer_name_len: usize,
803 layer_id: LayerId,
804 container_condition_id: ContainerConditionId,
805 cascade_flags: RuleCascadeFlags,
806 saved_containing_scope_rule_state: SavedContainingScopeRuleState,
807 nested_declarations_context: NestedDeclarationsContext,
808}
809
810impl ContainingRuleState {
811 fn save(&self) -> SavedContainingRuleState {
812 SavedContainingRuleState {
813 ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
814 layer_name_len: self.layer_name.0.len(),
815 layer_id: self.layer_id,
816 container_condition_id: self.container_condition_id,
817 cascade_flags: self.cascade_flags,
818 saved_containing_scope_rule_state: self.containing_scope_rule_state.save(),
819 nested_declarations_context: self.nested_declarations_context,
820 }
821 }
822
823 fn restore(
824 &mut self,
825 saved: &SavedContainingRuleState,
826 ) -> Option<(Vec<Dependency>, ScopeConditionId)> {
827 debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
828 debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
829
830 self.ancestor_selector_lists
831 .truncate(saved.ancestor_selector_lists_len);
832 self.layer_name.0.truncate(saved.layer_name_len);
833 self.layer_id = saved.layer_id;
834 self.container_condition_id = saved.container_condition_id;
835 self.cascade_flags = saved.cascade_flags;
836 self.nested_declarations_context = saved.nested_declarations_context;
837
838 self.containing_scope_rule_state
839 .restore(&saved.saved_containing_scope_rule_state)
840 }
841
842 fn scope_is_effective(&self) -> bool {
843 self.containing_scope_rule_state.id != ScopeConditionId::none()
844 }
845
846 fn cascade_flags(&self) -> RuleCascadeFlags {
847 self.cascade_flags
848 }
849}
850
851type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
852
853impl Stylist {
854 #[inline]
858 pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
859 Self {
860 device,
861 quirks_mode,
862 stylesheets: StylistStylesheetSet::new(),
863 author_data_cache: CascadeDataCache::new(),
864 cascade_data: Default::default(),
865 author_styles_enabled: AuthorStylesEnabled::Yes,
866 rule_tree: RuleTree::new(),
867 script_custom_properties: Default::default(),
868 initial_values_for_custom_properties: Default::default(),
869 initial_values_for_custom_properties_flags: Default::default(),
870 num_rebuilds: 0,
871 }
872 }
873
874 #[inline]
876 pub fn cascade_data(&self) -> &DocumentCascadeData {
877 &self.cascade_data
878 }
879
880 #[inline]
882 pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
883 self.author_styles_enabled
884 }
885
886 #[inline]
888 pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
889 self.cascade_data.iter_origins()
890 }
891
892 pub fn remove_unique_author_data_cache_entries(&mut self) {
895 self.author_data_cache.take_unused();
896 }
897
898 pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyDescriptors {
901 if let Some(registration) = self.custom_property_script_registry().get(name) {
902 return ®istration.descriptors;
903 }
904 for (data, _) in self.iter_origins() {
905 if let Some(registration) = data.custom_property_registrations.get(name) {
906 return ®istration.descriptors;
907 }
908 }
909 PropertyDescriptors::unregistered()
910 }
911
912 pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
914 &self.initial_values_for_custom_properties
915 }
916
917 pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
919 self.initial_values_for_custom_properties_flags
920 }
921
922 pub fn rebuild_initial_values_for_custom_properties(&mut self) {
925 let mut initial_values = ComputedCustomProperties::default();
926 let initial_values_flags;
927 {
928 let mut seen_names = PrecomputedHashSet::default();
929 let mut rule_cache_conditions = RuleCacheConditions::default();
930 let context = computed::Context::new_for_initial_at_property_value(
931 self,
932 &mut rule_cache_conditions,
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 (flusher, mut invalidations) = self.stylesheets.flush();
1059
1060 self.cascade_data
1061 .rebuild(
1062 &self.device,
1063 self.quirks_mode,
1064 flusher,
1065 guards,
1066 &mut invalidations.cascade_data_difference,
1067 )
1068 .unwrap_or_else(|_| {
1069 warn!("OOM in Stylist::flush");
1070 });
1071
1072 self.rebuild_initial_values_for_custom_properties();
1073 invalidations
1074 }
1075
1076 pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
1082 self.stylesheets.force_dirty(origins)
1083 }
1084
1085 pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
1087 self.author_styles_enabled = enabled;
1088 }
1089
1090 pub fn stylesheets_have_changed(&self) -> bool {
1092 self.stylesheets.has_changed()
1093 }
1094
1095 pub fn insert_stylesheet_before(
1097 &mut self,
1098 sheet: StylistSheet,
1099 before_sheet: StylistSheet,
1100 guard: &SharedRwLockReadGuard,
1101 ) {
1102 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1103 self.stylesheets.insert_stylesheet_before(
1104 Some(&self.device),
1105 custom_media,
1106 sheet,
1107 before_sheet,
1108 guard,
1109 )
1110 }
1111
1112 pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1114 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1115 self.stylesheets
1116 .append_stylesheet(Some(&self.device), custom_media, sheet, guard)
1117 }
1118
1119 pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
1121 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1122 self.stylesheets
1123 .remove_stylesheet(Some(&self.device), custom_media, sheet, guard)
1124 }
1125
1126 pub fn rule_changed(
1128 &mut self,
1129 sheet: &StylistSheet,
1130 rule: &CssRule,
1131 guard: &SharedRwLockReadGuard,
1132 change_kind: RuleChangeKind,
1133 ancestors: &[CssRuleRef],
1134 ) {
1135 let custom_media = self.cascade_data.custom_media_for_sheet(&sheet, guard);
1136 self.stylesheets.rule_changed(
1137 Some(&self.device),
1138 custom_media,
1139 sheet,
1140 rule,
1141 guard,
1142 change_kind,
1143 ancestors,
1144 )
1145 }
1146
1147 #[inline]
1149 pub fn sheet_count(&self, origin: Origin) -> usize {
1150 self.stylesheets.sheet_count(origin)
1151 }
1152
1153 #[inline]
1155 pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
1156 self.stylesheets.get(origin, index)
1157 }
1158
1159 pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
1162 where
1163 E: TElement,
1164 F: FnMut(&CascadeData) -> bool,
1165 {
1166 if f(&self.cascade_data.user_agent.cascade_data) {
1167 return true;
1168 }
1169
1170 let mut maybe = false;
1171
1172 let doc_author_rules_apply =
1173 element.each_applicable_non_document_style_rule_data(|data, _| {
1174 maybe = maybe || f(&*data);
1175 });
1176
1177 if maybe || f(&self.cascade_data.user) {
1178 return true;
1179 }
1180
1181 doc_author_rules_apply && f(&self.cascade_data.author)
1182 }
1183
1184 pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1186 where
1187 E: TElement + 'a,
1188 F: FnMut(&'a CascadeData, Option<E>),
1189 {
1190 f(&self.cascade_data.user_agent.cascade_data, None);
1191 element.each_applicable_non_document_style_rule_data(|data, scope| {
1192 f(data, Some(scope));
1193 });
1194 f(&self.cascade_data.user, None);
1195 f(&self.cascade_data.author, None);
1196 }
1197
1198 pub fn precomputed_values_for_pseudo<E>(
1201 &self,
1202 guards: &StylesheetGuards,
1203 pseudo: &PseudoElement,
1204 parent: Option<&ComputedValues>,
1205 ) -> Arc<ComputedValues>
1206 where
1207 E: TElement,
1208 {
1209 debug_assert!(pseudo.is_precomputed());
1210
1211 let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1212
1213 self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1214 }
1215
1216 pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1222 &self,
1223 guards: &StylesheetGuards,
1224 pseudo: &PseudoElement,
1225 parent: Option<&ComputedValues>,
1226 rules: StrongRuleNode,
1227 ) -> Arc<ComputedValues>
1228 where
1229 E: TElement,
1230 {
1231 self.compute_pseudo_element_style_with_inputs::<E>(
1232 CascadeInputs {
1233 rules: Some(rules),
1234 visited_rules: None,
1235 flags: Default::default(),
1236 included_cascade_flags: RuleCascadeFlags::empty(),
1237 },
1238 pseudo,
1239 guards,
1240 parent,
1241 None,
1242 )
1243 }
1244
1245 pub fn rule_node_for_precomputed_pseudo(
1251 &self,
1252 guards: &StylesheetGuards,
1253 pseudo: &PseudoElement,
1254 mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1255 ) -> StrongRuleNode {
1256 let mut declarations_with_extra;
1257 let declarations = match self
1258 .cascade_data
1259 .user_agent
1260 .precomputed_pseudo_element_decls
1261 .get(pseudo)
1262 {
1263 Some(declarations) => {
1264 if !extra_declarations.is_empty() {
1265 declarations_with_extra = declarations.clone();
1266 declarations_with_extra.append(&mut extra_declarations);
1267 &*declarations_with_extra
1268 } else {
1269 &**declarations
1270 }
1271 },
1272 None => &[],
1273 };
1274
1275 self.rule_tree.insert_ordered_rules_with_important(
1276 declarations.into_iter().map(|a| a.clone().for_rule_tree()),
1277 guards,
1278 )
1279 }
1280
1281 #[cfg(feature = "servo")]
1286 pub fn style_for_anonymous<E>(
1287 &self,
1288 guards: &StylesheetGuards,
1289 pseudo: &PseudoElement,
1290 parent_style: &ComputedValues,
1291 ) -> Arc<ComputedValues>
1292 where
1293 E: TElement,
1294 {
1295 self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1296 }
1297
1298 pub fn lazily_compute_pseudo_element_style<E>(
1306 &self,
1307 guards: &StylesheetGuards,
1308 element: E,
1309 pseudo: &PseudoElement,
1310 rule_inclusion: RuleInclusion,
1311 originating_element_style: &ComputedValues,
1312 is_probe: bool,
1313 matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1314 ) -> Option<Arc<ComputedValues>>
1315 where
1316 E: TElement,
1317 {
1318 let cascade_inputs = self.lazy_pseudo_rules(
1319 guards,
1320 element,
1321 originating_element_style,
1322 pseudo,
1323 is_probe,
1324 rule_inclusion,
1325 matching_fn,
1326 )?;
1327
1328 Some(self.compute_pseudo_element_style_with_inputs(
1329 cascade_inputs,
1330 pseudo,
1331 guards,
1332 Some(originating_element_style),
1333 Some(element),
1334 ))
1335 }
1336
1337 pub fn compute_pseudo_element_style_with_inputs<E>(
1342 &self,
1343 inputs: CascadeInputs,
1344 pseudo: &PseudoElement,
1345 guards: &StylesheetGuards,
1346 parent_style: Option<&ComputedValues>,
1347 element: Option<E>,
1348 ) -> Arc<ComputedValues>
1349 where
1350 E: TElement,
1351 {
1352 self.cascade_style_and_visited(
1365 element,
1366 Some(pseudo),
1367 inputs,
1368 guards,
1369 parent_style,
1370 parent_style,
1371 FirstLineReparenting::No,
1372 &PositionTryFallbacksTryTactic::default(),
1373 None,
1374 &mut RuleCacheConditions::default(),
1375 )
1376 }
1377
1378 #[cfg(feature = "gecko")]
1380 pub fn resolve_position_try<E>(
1381 &self,
1382 style: &ComputedValues,
1383 guards: &StylesheetGuards,
1384 element: E,
1385 fallback_item: &PositionTryFallbacksItem,
1386 ) -> Option<Arc<ComputedValues>>
1387 where
1388 E: TElement,
1389 {
1390 let name_and_try_tactic = match *fallback_item {
1391 PositionTryFallbacksItem::PositionArea(area) => {
1392 let mut builder =
1396 StyleBuilder::for_derived_style(&self.device, Some(self), style, None);
1397 builder.rules = style.rules.clone();
1398 builder.mutate_position().set_position_area(area);
1399 return Some(builder.build());
1400 },
1401 PositionTryFallbacksItem::IdentAndOrTactic(ref name_and_try_tactic) => {
1402 name_and_try_tactic
1403 },
1404 };
1405
1406 let fallback_rule = if !name_and_try_tactic.ident.is_empty() {
1407 Some(self.lookup_position_try(&name_and_try_tactic.ident.0, element)?)
1408 } else {
1409 None
1410 };
1411 let fallback_block = fallback_rule
1412 .as_ref()
1413 .map(|r| &r.read_with(guards.author).block);
1414 let pseudo = style
1415 .pseudo()
1416 .or_else(|| element.implemented_pseudo_element());
1417 let inputs = {
1418 let mut inputs = CascadeInputs::new_from_style(style);
1419 inputs.visited_rules = None;
1421 let rules = inputs.rules.as_ref().unwrap_or(self.rule_tree.root());
1422 let mut important_rules_changed = false;
1423 if let Some(fallback_block) = fallback_block {
1424 let new_rules = self.rule_tree.update_rule_at_level(
1425 CascadeLevel::new(CascadeOrigin::PositionFallback),
1426 LayerOrder::root(),
1427 Some(fallback_block.borrow_arc()),
1428 rules,
1429 guards,
1430 &mut important_rules_changed,
1431 );
1432 if new_rules.is_some() {
1433 inputs.rules = new_rules;
1434 } else {
1435 }
1439 }
1440 inputs
1441 };
1442 crate::style_resolver::with_default_parent_styles(
1443 element,
1444 |parent_style, layout_parent_style| {
1445 Some(self.cascade_style_and_visited(
1446 Some(element),
1447 pseudo.as_ref(),
1448 inputs,
1449 guards,
1450 parent_style,
1451 layout_parent_style,
1452 FirstLineReparenting::No,
1453 &name_and_try_tactic.try_tactic,
1454 None,
1455 &mut RuleCacheConditions::default(),
1456 ))
1457 },
1458 )
1459 }
1460
1461 pub fn cascade_style_and_visited<E>(
1474 &self,
1475 element: Option<E>,
1476 pseudo: Option<&PseudoElement>,
1477 inputs: CascadeInputs,
1478 guards: &StylesheetGuards,
1479 parent_style: Option<&ComputedValues>,
1480 layout_parent_style: Option<&ComputedValues>,
1481 first_line_reparenting: FirstLineReparenting,
1482 try_tactic: &PositionTryFallbacksTryTactic,
1483 rule_cache: Option<&RuleCache>,
1484 rule_cache_conditions: &mut RuleCacheConditions,
1485 ) -> Arc<ComputedValues>
1486 where
1487 E: TElement,
1488 {
1489 debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1490
1491 let visited_rules = match inputs.visited_rules.as_ref() {
1494 Some(rules) => Some(rules),
1495 None => {
1496 if parent_style.and_then(|s| s.visited_style()).is_some() {
1497 Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1498 } else {
1499 None
1500 }
1501 },
1502 };
1503
1504 let mut implemented_pseudo = None;
1505 properties::cascade::<E>(
1512 &self,
1513 pseudo.or_else(|| {
1514 implemented_pseudo = element.unwrap().implemented_pseudo_element();
1515 implemented_pseudo.as_ref()
1516 }),
1517 inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1518 guards,
1519 parent_style,
1520 layout_parent_style,
1521 first_line_reparenting,
1522 try_tactic,
1523 visited_rules,
1524 inputs.flags,
1525 inputs.included_cascade_flags,
1526 rule_cache,
1527 rule_cache_conditions,
1528 element,
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::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 pseudos,
1731 style_attribute,
1732 smil_override,
1733 animation_declarations,
1734 rule_inclusion,
1735 applicable_declarations,
1736 context,
1737 )
1738 .collect_all();
1739 }
1740
1741 #[inline]
1744 pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1745 where
1746 E: TElement,
1747 {
1748 match self.quirks_mode().classes_and_ids_case_sensitivity() {
1751 CaseSensitivity::AsciiCaseInsensitive => return true,
1752 CaseSensitivity::CaseSensitive => {},
1753 }
1754
1755 self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1756 }
1757
1758 #[inline]
1766 fn lookup_element_dependent_at_rule<'a, T, F, E>(
1767 &'a self,
1768 element: E,
1769 find_in: F,
1770 ) -> Option<&'a T>
1771 where
1772 E: TElement + 'a,
1773 F: Fn(&'a CascadeData) -> Option<&'a T>,
1774 {
1775 macro_rules! try_find_in {
1776 ($data:expr) => {
1777 if let Some(thing) = find_in(&$data) {
1778 return Some(thing);
1779 }
1780 };
1781 }
1782
1783 let mut result = None;
1784 let doc_rules_apply =
1785 element.each_applicable_non_document_style_rule_data(|data, _host| {
1786 if result.is_none() {
1787 result = find_in(data);
1788 }
1789 });
1790
1791 if result.is_some() {
1792 return result;
1793 }
1794
1795 if doc_rules_apply {
1796 try_find_in!(self.cascade_data.author);
1797 }
1798 try_find_in!(self.cascade_data.user);
1799 try_find_in!(self.cascade_data.user_agent.cascade_data);
1800
1801 None
1802 }
1803
1804 #[inline]
1806 pub fn lookup_keyframes<'a, E>(
1807 &'a self,
1808 name: &Atom,
1809 element: E,
1810 ) -> Option<&'a KeyframesAnimation>
1811 where
1812 E: TElement + 'a,
1813 {
1814 self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1815 }
1816
1817 #[inline]
1820 pub fn last_view_transition_rule(&self) -> Option<&Arc<ViewTransitionRule>> {
1821 self.iter_extra_data_origins()
1823 .flat_map(|(d, _)| d.view_transitions.iter())
1824 .last()
1825 .map(|(rule, _)| rule)
1826 }
1827
1828 #[inline]
1830 #[cfg(feature = "gecko")]
1831 fn lookup_position_try<'a, E>(
1832 &'a self,
1833 name: &Atom,
1834 element: E,
1835 ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1836 where
1837 E: TElement + 'a,
1838 {
1839 self.lookup_element_dependent_at_rule(element, |data| {
1840 data.extra_data.position_try_rules.get(name)
1841 })
1842 }
1843
1844 pub fn match_revalidation_selectors<E>(
1847 &self,
1848 element: E,
1849 bloom: Option<&BloomFilter>,
1850 selector_caches: &mut SelectorCaches,
1851 needs_selector_flags: NeedsSelectorFlags,
1852 ) -> RevalidationResult
1853 where
1854 E: TElement,
1855 {
1856 let mut matching_context = MatchingContext::new_for_revalidation(
1857 bloom,
1858 selector_caches,
1859 self.quirks_mode,
1860 needs_selector_flags,
1861 );
1862
1863 let mut result = RevalidationResult::default();
1869 let mut relevant_attributes = &mut result.relevant_attributes;
1870 let selectors_matched = &mut result.selectors_matched;
1871
1872 let matches_document_rules =
1873 element.each_applicable_non_document_style_rule_data(|data, host| {
1874 matching_context.with_shadow_host(Some(host), |matching_context| {
1875 data.selectors_for_cache_revalidation.lookup(
1876 element,
1877 self.quirks_mode,
1878 Some(&mut relevant_attributes),
1879 |selector_and_hashes| {
1880 selectors_matched.push(matches_selector(
1881 &selector_and_hashes.selector,
1882 selector_and_hashes.selector_offset,
1883 Some(&selector_and_hashes.hashes),
1884 &element,
1885 matching_context,
1886 ));
1887 true
1888 },
1889 );
1890 })
1891 });
1892
1893 for (data, origin) in self.cascade_data.iter_origins() {
1894 if origin == Origin::Author && !matches_document_rules {
1895 continue;
1896 }
1897
1898 data.selectors_for_cache_revalidation.lookup(
1899 element,
1900 self.quirks_mode,
1901 Some(&mut relevant_attributes),
1902 |selector_and_hashes| {
1903 selectors_matched.push(matches_selector(
1904 &selector_and_hashes.selector,
1905 selector_and_hashes.selector_offset,
1906 Some(&selector_and_hashes.hashes),
1907 &element,
1908 &mut matching_context,
1909 ));
1910 true
1911 },
1912 );
1913 }
1914
1915 result
1916 }
1917
1918 pub fn revalidate_scopes<E: TElement>(
1920 &self,
1921 element: &E,
1922 selector_caches: &mut SelectorCaches,
1923 needs_selector_flags: NeedsSelectorFlags,
1924 ) -> ScopeRevalidationResult {
1925 let mut matching_context = MatchingContext::new(
1926 MatchingMode::Normal,
1927 None,
1928 selector_caches,
1929 self.quirks_mode,
1930 needs_selector_flags,
1931 MatchingForInvalidation::No,
1932 );
1933
1934 let mut result = ScopeRevalidationResult::default();
1935 let matches_document_rules =
1936 element.each_applicable_non_document_style_rule_data(|data, host| {
1937 matching_context.with_shadow_host(Some(host), |matching_context| {
1938 data.revalidate_scopes(element, matching_context, &mut result);
1939 })
1940 });
1941
1942 for (data, origin) in self.cascade_data.iter_origins() {
1943 if origin == Origin::Author && !matches_document_rules {
1944 continue;
1945 }
1946
1947 data.revalidate_scopes(element, &mut matching_context, &mut result);
1948 }
1949
1950 result
1951 }
1952
1953 pub fn compute_for_declarations<E>(
1961 &self,
1962 guards: &StylesheetGuards,
1963 parent_style: &ComputedValues,
1964 declarations: Arc<Locked<PropertyDeclarationBlock>>,
1965 ) -> Arc<ComputedValues>
1966 where
1967 E: TElement,
1968 {
1969 let block = declarations.read_with(guards.author);
1970
1971 properties::apply_declarations::<E, _>(
1978 &self,
1979 None,
1980 self.rule_tree.root(),
1981 guards,
1982 block.declaration_importance_iter().map(|(declaration, _)| {
1983 (
1984 declaration,
1985 CascadePriority::new(
1986 CascadeLevel::same_tree_author_normal(),
1987 LayerOrder::root(),
1988 RuleCascadeFlags::empty(),
1989 ),
1990 )
1991 }),
1992 Some(parent_style),
1993 Some(parent_style),
1994 FirstLineReparenting::No,
1995 &PositionTryFallbacksTryTactic::default(),
1996 CascadeMode::Unvisited {
1997 visited_rules: None,
1998 },
1999 Default::default(),
2000 RuleCascadeFlags::empty(),
2001 None,
2002 &mut Default::default(),
2003 None,
2004 )
2005 }
2006
2007 #[inline]
2009 pub fn device(&self) -> &Device {
2010 &self.device
2011 }
2012
2013 #[inline]
2015 pub fn device_mut(&mut self) -> &mut Device {
2016 &mut self.device
2017 }
2018
2019 #[inline]
2021 pub fn rule_tree(&self) -> &RuleTree {
2022 &self.rule_tree
2023 }
2024
2025 #[inline]
2027 pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
2028 &self.script_custom_properties
2029 }
2030
2031 #[inline]
2033 pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
2034 &mut self.script_custom_properties
2035 }
2036
2037 #[cfg(feature = "gecko")]
2039 pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2040 self.cascade_data.add_size_of(ops, sizes);
2041 self.author_data_cache.add_size_of(ops, sizes);
2042 sizes.mRuleTree += self.rule_tree.size_of(ops);
2043
2044 }
2046
2047 pub fn shutdown() {
2049 let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
2050 }
2051}
2052
2053#[allow(missing_docs)]
2054#[repr(u8)]
2055pub enum RegisterCustomPropertyResult {
2056 SuccessfullyRegistered,
2057 InvalidName,
2058 AlreadyRegistered,
2059 InvalidSyntax,
2060 NoInitialValue,
2061 InvalidInitialValue,
2062 InitialValueNotComputationallyIndependent,
2063}
2064
2065impl Stylist {
2066 pub fn register_custom_property(
2068 &mut self,
2069 url_data: &UrlExtraData,
2070 name: &str,
2071 syntax: &str,
2072 inherits: bool,
2073 initial_value: Option<&str>,
2074 ) -> RegisterCustomPropertyResult {
2075 use RegisterCustomPropertyResult::*;
2076
2077 let Ok(name) = parse_name(name).map(Atom::from) else {
2079 return InvalidName;
2080 };
2081
2082 if self.custom_property_script_registry().get(&name).is_some() {
2085 return AlreadyRegistered;
2086 }
2087 let Ok(syntax) = Descriptor::from_str(syntax, false) else {
2090 return InvalidSyntax;
2091 };
2092
2093 let initial_value = match initial_value {
2094 Some(value) => {
2095 let mut input = ParserInput::new(value);
2096 let parsed = Parser::new(&mut input)
2097 .parse_entirely(|input| {
2098 input.skip_whitespace();
2099 SpecifiedValue::parse(input, None, url_data).map(Arc::new)
2100 })
2101 .ok();
2102 if parsed.is_none() {
2103 return InvalidInitialValue;
2104 }
2105 parsed
2106 },
2107 None => None,
2108 };
2109
2110 if let Err(error) =
2111 PropertyRegistration::validate_initial_value(&syntax, initial_value.as_deref())
2112 {
2113 return match error {
2114 PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
2115 InitialValueNotComputationallyIndependent
2116 },
2117 PropertyRegistrationError::InvalidInitialValue => InvalidInitialValue,
2118 PropertyRegistrationError::NoInitialValue => NoInitialValue,
2119 };
2120 }
2121
2122 let property_registration = PropertyRegistration {
2123 name: PropertyRuleName(name),
2124 descriptors: PropertyDescriptors {
2125 syntax: Some(syntax),
2126 inherits: Some(if inherits {
2127 Inherits::True
2128 } else {
2129 Inherits::False
2130 }),
2131 initial_value,
2132 },
2133 url_data: url_data.clone(),
2134 source_location: SourceLocation { line: 0, column: 0 },
2135 };
2136 self.custom_property_script_registry_mut()
2137 .register(property_registration);
2138 self.rebuild_initial_values_for_custom_properties();
2139
2140 SuccessfullyRegistered
2141 }
2142}
2143
2144#[derive(Clone, Debug, Deref, MallocSizeOf)]
2146pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
2147impl<T> Default for LayerOrderedVec<T> {
2148 fn default() -> Self {
2149 Self(Default::default())
2150 }
2151}
2152
2153#[derive(Clone, Debug, Deref, MallocSizeOf)]
2155pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
2156impl<T> Default for LayerOrderedMap<T> {
2157 fn default() -> Self {
2158 Self(Default::default())
2159 }
2160}
2161
2162impl<T: 'static> LayerOrderedVec<T> {
2163 fn clear(&mut self) {
2164 self.0.clear();
2165 }
2166 fn push(&mut self, v: T, id: LayerId) {
2167 self.0.push((v, id));
2168 }
2169 fn sort(&mut self, layers: &[CascadeLayer]) {
2170 self.0
2171 .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
2172 }
2173}
2174
2175impl<T: 'static> LayerOrderedMap<T> {
2176 fn shrink_if_needed(&mut self) {
2177 self.0.shrink_if_needed();
2178 }
2179 fn clear(&mut self) {
2180 self.0.clear();
2181 }
2182 fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
2183 self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
2184 }
2185 fn try_insert_with(
2186 &mut self,
2187 name: Atom,
2188 v: T,
2189 id: LayerId,
2190 cmp: impl Fn(&T, &T) -> Ordering,
2191 ) -> Result<(), AllocErr> {
2192 self.0.try_reserve(1)?;
2193 let vec = self.0.entry(name).or_default();
2194 if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
2195 if *last_id == id {
2196 if cmp(&val, &v) != Ordering::Greater {
2197 *val = v;
2198 }
2199 return Ok(());
2200 }
2201 }
2202 vec.push((v, id));
2203 Ok(())
2204 }
2205 fn sort(&mut self, layers: &[CascadeLayer]) {
2206 self.sort_with(layers, |_, _| Ordering::Equal)
2207 }
2208 fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
2209 for (_, v) in self.0.iter_mut() {
2210 v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
2211 let order1 = layers[id1.0 as usize].order;
2212 let order2 = layers[id2.0 as usize].order;
2213 order1.cmp(&order2).then_with(|| cmp(v1, v2))
2214 })
2215 }
2216 }
2217 pub fn get(&self, name: &Atom) -> Option<&T> {
2219 let vec = self.0.get(name)?;
2220 Some(&vec.last()?.0)
2221 }
2222}
2223
2224#[derive(Clone, Debug, MallocSizeOf)]
2228pub struct PageRuleData {
2229 pub layer: LayerId,
2231 #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
2233 pub rule: Arc<Locked<PageRule>>,
2234}
2235
2236#[derive(Clone, Debug, Default, MallocSizeOf)]
2238pub struct PageRuleMap {
2239 pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
2241}
2242
2243impl PageRuleMap {
2244 #[inline]
2245 fn clear(&mut self) {
2246 self.rules.clear();
2247 }
2248
2249 pub fn match_and_append_rules(
2253 &self,
2254 matched_rules: &mut Vec<ApplicableDeclarationBlock>,
2255 origin: Origin,
2256 guards: &StylesheetGuards,
2257 cascade_data: &DocumentCascadeData,
2258 name: &Option<Atom>,
2259 pseudos: PagePseudoClassFlags,
2260 ) {
2261 let level = match origin {
2262 Origin::UserAgent => CascadeLevel::new(CascadeOrigin::UA),
2263 Origin::User => CascadeLevel::new(CascadeOrigin::User),
2264 Origin::Author => CascadeLevel::same_tree_author_normal(),
2265 };
2266 let cascade_data = cascade_data.borrow_for_origin(origin);
2267 let start = matched_rules.len();
2268
2269 self.match_and_add_rules(
2270 matched_rules,
2271 level,
2272 guards,
2273 cascade_data,
2274 &atom!(""),
2275 pseudos,
2276 );
2277 if let Some(name) = name {
2278 self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
2279 }
2280
2281 matched_rules[start..].sort_by_key(|block| block.sort_key());
2284 }
2285
2286 fn match_and_add_rules(
2287 &self,
2288 extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
2289 level: CascadeLevel,
2290 guards: &StylesheetGuards,
2291 cascade_data: &CascadeData,
2292 name: &Atom,
2293 pseudos: PagePseudoClassFlags,
2294 ) {
2295 let rules = match self.rules.get(name) {
2296 Some(rules) => rules,
2297 None => return,
2298 };
2299 for data in rules.iter() {
2300 let rule = data.rule.read_with(level.guard(&guards));
2301 let specificity = match rule.match_specificity(pseudos) {
2302 Some(specificity) => specificity,
2303 None => continue,
2304 };
2305 let block = rule.block.clone();
2306 extra_declarations.push(ApplicableDeclarationBlock::new(
2307 StyleSource::from_declarations(block),
2308 0,
2309 level,
2310 specificity,
2311 cascade_data.layer_order_for(data.layer),
2312 ScopeProximity::infinity(), RuleCascadeFlags::empty(),
2314 ));
2315 }
2316 }
2317}
2318
2319impl MallocShallowSizeOf for PageRuleMap {
2320 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2321 self.rules.shallow_size_of(ops)
2322 }
2323}
2324
2325type PositionTryMap = LayerOrderedMap<Arc<Locked<PositionTryRule>>>;
2326
2327#[derive(Clone, Debug, Default)]
2330pub struct ExtraStyleData {
2331 pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
2333
2334 pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
2336
2337 pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
2339
2340 pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
2342
2343 pub position_try_rules: PositionTryMap,
2345
2346 pub pages: PageRuleMap,
2348
2349 pub view_transitions: LayerOrderedVec<Arc<ViewTransitionRule>>,
2351}
2352
2353impl ExtraStyleData {
2354 fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2356 self.font_faces.push(rule.clone(), layer);
2357 }
2358
2359 fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2361 self.font_feature_values.push(rule.clone(), layer);
2362 }
2363
2364 fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2366 self.font_palette_values.push(rule.clone(), layer);
2367 }
2368
2369 fn add_counter_style(
2371 &mut self,
2372 guard: &SharedRwLockReadGuard,
2373 rule: &Arc<Locked<CounterStyleRule>>,
2374 layer: LayerId,
2375 ) -> Result<(), AllocErr> {
2376 let name = rule.read_with(guard).name().0.clone();
2377 self.counter_styles.try_insert(name, rule.clone(), layer)
2378 }
2379
2380 fn add_position_try(
2382 &mut self,
2383 name: Atom,
2384 rule: Arc<Locked<PositionTryRule>>,
2385 layer: LayerId,
2386 ) -> Result<(), AllocErr> {
2387 self.position_try_rules.try_insert(name, rule, layer)
2388 }
2389
2390 fn add_page(
2392 &mut self,
2393 guard: &SharedRwLockReadGuard,
2394 rule: &Arc<Locked<PageRule>>,
2395 layer: LayerId,
2396 ) -> Result<(), AllocErr> {
2397 let page_rule = rule.read_with(guard);
2398 let mut add_rule = |name| {
2399 let vec = self.pages.rules.entry(name).or_default();
2400 vec.push(PageRuleData {
2401 layer,
2402 rule: rule.clone(),
2403 });
2404 };
2405 if page_rule.selectors.0.is_empty() {
2406 add_rule(atom!(""));
2407 } else {
2408 for selector in page_rule.selectors.as_slice() {
2409 add_rule(selector.name.0.clone());
2410 }
2411 }
2412 Ok(())
2413 }
2414
2415 fn add_view_transition(&mut self, rule: &Arc<ViewTransitionRule>, layer: LayerId) {
2416 self.view_transitions.push(rule.clone(), layer)
2417 }
2418
2419 fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2420 self.font_faces.sort(layers);
2421 self.font_feature_values.sort(layers);
2422 self.font_palette_values.sort(layers);
2423 self.counter_styles.sort(layers);
2424 self.position_try_rules.sort(layers);
2425 self.view_transitions.sort(layers);
2426 }
2427
2428 fn clear(&mut self) {
2429 self.font_faces.clear();
2430 self.font_feature_values.clear();
2431 self.font_palette_values.clear();
2432 self.counter_styles.clear();
2433 self.position_try_rules.clear();
2434 self.pages.clear();
2435 }
2436}
2437
2438fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2441 if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2442 Ordering::Equal
2443 } else if v2.vendor_prefix.is_some() {
2444 Ordering::Greater
2445 } else {
2446 Ordering::Less
2447 }
2448}
2449
2450pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2452
2453impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2454 type Item = (&'a ExtraStyleData, Origin);
2455
2456 fn next(&mut self) -> Option<Self::Item> {
2457 self.0.next().map(|d| (&d.0.extra_data, d.1))
2458 }
2459}
2460
2461impl MallocSizeOf for ExtraStyleData {
2462 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2464 let mut n = 0;
2465 n += self.font_faces.shallow_size_of(ops);
2466 n += self.font_feature_values.shallow_size_of(ops);
2467 n += self.font_palette_values.shallow_size_of(ops);
2468 n += self.counter_styles.shallow_size_of(ops);
2469 n += self.position_try_rules.shallow_size_of(ops);
2470 n += self.pages.shallow_size_of(ops);
2471 n
2472 }
2473}
2474
2475#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2477#[derive(Clone, Debug)]
2478struct RevalidationSelectorAndHashes {
2479 #[cfg_attr(
2480 feature = "gecko",
2481 ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2482 )]
2483 selector: Selector<SelectorImpl>,
2484 selector_offset: usize,
2485 hashes: AncestorHashes,
2486}
2487
2488impl RevalidationSelectorAndHashes {
2489 fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2490 let selector_offset = {
2491 let mut index = 0;
2495 let mut iter = selector.iter();
2496
2497 for _ in &mut iter {
2502 index += 1; }
2504
2505 match iter.next_sequence() {
2506 Some(Combinator::PseudoElement) => index + 1, _ => 0,
2508 }
2509 };
2510
2511 RevalidationSelectorAndHashes {
2512 selector,
2513 selector_offset,
2514 hashes,
2515 }
2516 }
2517}
2518
2519impl SelectorMapEntry for RevalidationSelectorAndHashes {
2520 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2521 self.selector.iter_from(self.selector_offset)
2522 }
2523}
2524
2525struct StylistSelectorVisitor<'a> {
2528 passed_rightmost_selector: bool,
2531
2532 needs_revalidation: &'a mut bool,
2534
2535 in_selector_list_of: SelectorListKind,
2538
2539 mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2542
2543 nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2546
2547 attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2549
2550 nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2553
2554 nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2558
2559 nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2563
2564 state_dependencies: &'a mut ElementState,
2566
2567 nth_of_state_dependencies: &'a mut ElementState,
2570
2571 document_state_dependencies: &'a mut DocumentState,
2573}
2574
2575fn component_needs_revalidation(
2576 c: &Component<SelectorImpl>,
2577 passed_rightmost_selector: bool,
2578) -> bool {
2579 match *c {
2580 Component::ID(_) => {
2581 passed_rightmost_selector
2587 },
2588 Component::AttributeInNoNamespaceExists { .. }
2589 | Component::AttributeInNoNamespace { .. }
2590 | Component::AttributeOther(_)
2591 | Component::Empty
2592 | Component::Nth(_)
2593 | Component::NthOf(_)
2594 | Component::Has(_) => true,
2595 Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2596 _ => false,
2597 }
2598}
2599
2600impl<'a> StylistSelectorVisitor<'a> {
2601 fn visit_nested_selector(
2602 &mut self,
2603 in_selector_list_of: SelectorListKind,
2604 selector: &Selector<SelectorImpl>,
2605 ) {
2606 let old_passed_rightmost_selector = self.passed_rightmost_selector;
2607 let old_in_selector_list_of = self.in_selector_list_of;
2608
2609 self.passed_rightmost_selector = false;
2610 self.in_selector_list_of = in_selector_list_of;
2611 let _ret = selector.visit(self);
2612 debug_assert!(_ret, "We never return false");
2613
2614 self.passed_rightmost_selector = old_passed_rightmost_selector;
2615 self.in_selector_list_of = old_in_selector_list_of;
2616 }
2617}
2618
2619impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2620 type Impl = SelectorImpl;
2621
2622 fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2623 *self.needs_revalidation =
2624 *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2625
2626 self.passed_rightmost_selector = self.passed_rightmost_selector
2630 || !matches!(combinator, None | Some(Combinator::PseudoElement));
2631
2632 true
2633 }
2634
2635 fn visit_selector_list(
2636 &mut self,
2637 list_kind: SelectorListKind,
2638 list: &[Selector<Self::Impl>],
2639 ) -> bool {
2640 let in_selector_list_of = self.in_selector_list_of | list_kind;
2641 for selector in list {
2642 self.visit_nested_selector(in_selector_list_of, selector);
2643 }
2644 true
2645 }
2646
2647 fn visit_relative_selector_list(
2648 &mut self,
2649 list: &[selectors::parser::RelativeSelector<Self::Impl>],
2650 ) -> bool {
2651 let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2652 for selector in list {
2653 self.visit_nested_selector(in_selector_list_of, &selector.selector);
2654 }
2655 true
2656 }
2657
2658 fn visit_attribute_selector(
2659 &mut self,
2660 _ns: &NamespaceConstraint<&Namespace>,
2661 name: &LocalName,
2662 lower_name: &LocalName,
2663 ) -> bool {
2664 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2665 self.nth_of_attribute_dependencies.insert(name.clone());
2666 if name != lower_name {
2667 self.nth_of_attribute_dependencies
2668 .insert(lower_name.clone());
2669 }
2670 }
2671
2672 self.attribute_dependencies.insert(name.clone());
2673 if name != lower_name {
2674 self.attribute_dependencies.insert(lower_name.clone());
2675 }
2676
2677 true
2678 }
2679
2680 fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2681 *self.needs_revalidation = *self.needs_revalidation
2682 || component_needs_revalidation(s, self.passed_rightmost_selector);
2683
2684 match *s {
2685 Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2686 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2692 self.nth_of_custom_state_dependencies.insert(name.0.clone());
2693 }
2694 },
2695 Component::NonTSPseudoClass(ref p) => {
2696 self.state_dependencies.insert(p.state_flag());
2697 self.document_state_dependencies
2698 .insert(p.document_state_flag());
2699
2700 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2701 self.nth_of_state_dependencies.insert(p.state_flag());
2702 }
2703 },
2704 Component::ID(ref id) => {
2705 if !self.passed_rightmost_selector {
2717 self.mapped_ids.insert(id.0.clone());
2718 }
2719
2720 if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2721 self.nth_of_mapped_ids.insert(id.0.clone());
2722 }
2723 },
2724 Component::Class(ref class)
2725 if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2726 {
2727 self.nth_of_class_dependencies.insert(class.0.clone());
2728 },
2729 _ => {},
2730 }
2731
2732 true
2733 }
2734}
2735
2736#[derive(Clone, Debug, Default, MallocSizeOf)]
2738struct GenericElementAndPseudoRules<Map> {
2739 element_map: Map,
2741
2742 pseudos_map: PerPseudoElementMap<Self>,
2749}
2750
2751impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2752 #[inline(always)]
2753 fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2754 let mut current = self;
2755 for &pseudo_element in pseudo_elements {
2756 debug_assert!(
2757 !pseudo_element.is_precomputed()
2758 && !pseudo_element.is_unknown_webkit_pseudo_element(),
2759 "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2760 and unknown webkit pseudos should be discarded before getting here"
2761 );
2762
2763 current = current
2764 .pseudos_map
2765 .get_or_insert_with(pseudo_element, Default::default);
2766 }
2767
2768 &mut current.element_map
2769 }
2770
2771 #[inline]
2772 fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2773 let mut current = self;
2774 for pseudo in pseudo_elements {
2775 current = current.pseudos_map.get(&pseudo)?;
2776 }
2777 Some(¤t.element_map)
2778 }
2779
2780 #[cfg(feature = "gecko")]
2782 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2783 sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2784
2785 for elem in self.pseudos_map.iter() {
2786 sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2787 }
2788 }
2789}
2790
2791type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2792type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2793type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2794
2795impl ElementAndPseudoRules {
2796 fn clear(&mut self) {
2798 self.element_map.clear();
2799 self.pseudos_map.clear();
2800 }
2801
2802 fn shrink_if_needed(&mut self) {
2803 self.element_map.shrink_if_needed();
2804 for pseudo in self.pseudos_map.iter_mut() {
2805 pseudo.shrink_if_needed();
2806 }
2807 }
2808}
2809
2810impl PartElementAndPseudoRules {
2811 fn clear(&mut self) {
2813 self.element_map.clear();
2814 self.pseudos_map.clear();
2815 }
2816}
2817
2818#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2820pub struct LayerId(u16);
2821
2822impl LayerId {
2823 pub const fn root() -> Self {
2825 Self(0)
2826 }
2827}
2828
2829#[derive(Clone, Debug, MallocSizeOf)]
2830struct CascadeLayer {
2831 id: LayerId,
2832 order: LayerOrder,
2833 children: Vec<LayerId>,
2834}
2835
2836impl CascadeLayer {
2837 const fn root() -> Self {
2838 Self {
2839 id: LayerId::root(),
2840 order: LayerOrder::root(),
2841 children: vec![],
2842 }
2843 }
2844}
2845
2846#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2849pub struct ContainerConditionId(u16);
2850
2851impl ContainerConditionId {
2852 pub const fn none() -> Self {
2854 Self(0)
2855 }
2856}
2857
2858#[derive(Clone, Debug, MallocSizeOf)]
2859struct ContainerConditionReference {
2860 parent: ContainerConditionId,
2861 #[ignore_malloc_size_of = "Arc"]
2866 conditions: ArcSlice<ContainerCondition>,
2867}
2868
2869impl ContainerConditionReference {
2870 fn none() -> Self {
2872 Self {
2873 parent: ContainerConditionId::none(),
2874 conditions: ArcSlice::default(),
2875 }
2876 }
2877}
2878
2879#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2882pub struct ScopeConditionId(u16);
2883
2884impl ScopeConditionId {
2885 pub fn new(id: u16) -> Self {
2887 Self(id)
2888 }
2889
2890 pub const fn none() -> Self {
2892 Self(0)
2893 }
2894}
2895
2896#[derive(Clone, Debug, MallocSizeOf)]
2898pub struct ScopeConditionReference {
2899 parent: ScopeConditionId,
2901 condition: Option<ScopeBoundsWithHashes>,
2903 #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2906 implicit_scope_root: StylistImplicitScopeRoot,
2907 is_trivial: bool,
2909}
2910
2911impl ScopeConditionReference {
2912 pub fn new(
2914 parent: ScopeConditionId,
2915 condition: Option<ScopeBoundsWithHashes>,
2916 implicit_scope_root: ImplicitScopeRoot,
2917 is_trivial: bool,
2918 ) -> Self {
2919 Self {
2920 parent,
2921 condition,
2922 implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2923 is_trivial,
2924 }
2925 }
2926
2927 pub const fn none() -> Self {
2929 Self {
2930 parent: ScopeConditionId::none(),
2931 condition: None,
2932 implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2933 is_trivial: true,
2934 }
2935 }
2936}
2937
2938pub struct ScopeRootCandidates {
2940 pub candidates: Vec<ScopeRootCandidate>,
2942 pub is_trivial: bool,
2944}
2945
2946impl Default for ScopeRootCandidates {
2947 fn default() -> Self {
2948 Self {
2949 candidates: vec![],
2950 is_trivial: true,
2951 }
2952 }
2953}
2954
2955impl ScopeRootCandidates {
2956 fn empty(is_trivial: bool) -> Self {
2957 Self {
2958 candidates: vec![],
2959 is_trivial,
2960 }
2961 }
2962}
2963
2964#[derive(Clone, Debug, MallocSizeOf)]
2966pub struct ScopeBoundWithHashes {
2967 #[ignore_malloc_size_of = "Arc"]
2969 selectors: SelectorList<SelectorImpl>,
2970 hashes: SmallVec<[AncestorHashes; 1]>,
2971}
2972
2973impl ScopeBoundWithHashes {
2974 fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2975 let mut hashes = SmallVec::with_capacity(selectors.len());
2976 for selector in selectors.slice() {
2977 hashes.push(AncestorHashes::new(selector, quirks_mode));
2978 }
2979 Self { selectors, hashes }
2980 }
2981
2982 fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
2983 let hashes = selectors
2984 .slice()
2985 .iter()
2986 .map(|_| AncestorHashes {
2987 packed_hashes: [0, 0, 0],
2988 })
2989 .collect();
2990 Self { selectors, hashes }
2991 }
2992}
2993
2994#[derive(Clone, Debug, MallocSizeOf)]
2996pub struct ScopeBoundsWithHashes {
2997 start: Option<ScopeBoundWithHashes>,
2999 end: Option<ScopeBoundWithHashes>,
3001}
3002
3003impl ScopeBoundsWithHashes {
3004 fn new(
3006 quirks_mode: QuirksMode,
3007 start: Option<SelectorList<SelectorImpl>>,
3008 end: Option<SelectorList<SelectorImpl>>,
3009 ) -> Self {
3010 Self {
3011 start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3012 end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
3013 }
3014 }
3015
3016 pub fn new_no_hash(
3018 start: Option<SelectorList<SelectorImpl>>,
3019 end: Option<SelectorList<SelectorImpl>>,
3020 ) -> Self {
3021 Self {
3022 start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3023 end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
3024 }
3025 }
3026
3027 fn selectors_for<'a>(
3028 bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
3029 ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3030 bound_with_hashes
3031 .map(|b| b.selectors.slice().iter())
3032 .into_iter()
3033 .flatten()
3034 }
3035
3036 fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3037 Self::selectors_for(self.start.as_ref())
3038 }
3039
3040 fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
3041 Self::selectors_for(self.end.as_ref())
3042 }
3043
3044 fn is_trivial(&self) -> bool {
3045 fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
3046 bound.as_ref().map_or(default, |bound| {
3047 scope_selector_list_is_trivial(&bound.selectors)
3048 })
3049 }
3050
3051 scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
3053 }
3054}
3055
3056pub fn scope_root_candidates<E>(
3058 scope_conditions: &[ScopeConditionReference],
3059 id: ScopeConditionId,
3060 element: &E,
3061 override_matches_shadow_host_for_part: bool,
3062 scope_subject_map: &ScopeSubjectMap,
3063 context: &mut MatchingContext<SelectorImpl>,
3064) -> ScopeRootCandidates
3065where
3066 E: TElement,
3067{
3068 let condition_ref = &scope_conditions[id.0 as usize];
3069 let bounds = match condition_ref.condition {
3070 None => return ScopeRootCandidates::default(),
3071 Some(ref c) => c,
3072 };
3073 let outer_result = scope_root_candidates(
3077 scope_conditions,
3078 condition_ref.parent,
3079 element,
3080 override_matches_shadow_host_for_part,
3081 scope_subject_map,
3082 context,
3083 );
3084
3085 let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
3086 let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
3087 if !is_outermost_scope && outer_result.candidates.is_empty() {
3088 return ScopeRootCandidates::empty(is_trivial);
3089 }
3090
3091 let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
3092 if let Some(filter) = context.bloom_filter {
3093 if !start
3098 .hashes
3099 .iter()
3100 .any(|entry| selector_may_match(entry, filter))
3101 {
3102 return ScopeRootCandidates::empty(is_trivial);
3103 }
3104 }
3105 (
3106 ScopeTarget::Selector(&start.selectors),
3107 scope_start_matches_shadow_host(&start.selectors),
3108 )
3109 } else {
3110 let implicit_root = condition_ref.implicit_scope_root;
3111 match implicit_root {
3112 StylistImplicitScopeRoot::Normal(r) => (
3113 ScopeTarget::Implicit(r.element(context.current_host.clone())),
3114 r.matches_shadow_host(),
3115 ),
3116 StylistImplicitScopeRoot::Cached(index) => {
3117 let host = context
3118 .current_host
3119 .expect("Cached implicit scope for light DOM implicit scope");
3120 match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
3121 None => return ScopeRootCandidates::empty(is_trivial),
3122 Some(root) => (
3123 ScopeTarget::Implicit(root.element(context.current_host.clone())),
3124 root.matches_shadow_host(),
3125 ),
3126 }
3127 },
3128 }
3129 };
3130 let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
3133
3134 let potential_scope_roots = if is_outermost_scope {
3135 collect_scope_roots(
3136 *element,
3137 None,
3138 context,
3139 &root_target,
3140 matches_shadow_host,
3141 scope_subject_map,
3142 )
3143 } else {
3144 let mut result = vec![];
3145 for activation in outer_result.candidates {
3146 let mut this_result = collect_scope_roots(
3147 *element,
3148 Some(activation.root),
3149 context,
3150 &root_target,
3151 matches_shadow_host,
3152 scope_subject_map,
3153 );
3154 result.append(&mut this_result);
3155 }
3156 result
3157 };
3158
3159 if potential_scope_roots.is_empty() {
3160 return ScopeRootCandidates::empty(is_trivial);
3161 }
3162
3163 let candidates = if let Some(end) = bounds.end.as_ref() {
3164 let mut result = vec![];
3165 for scope_root in potential_scope_roots {
3167 if end
3168 .selectors
3169 .slice()
3170 .iter()
3171 .zip(end.hashes.iter())
3172 .all(|(selector, hashes)| {
3173 if let Some(filter) = context.bloom_filter {
3175 if !selector_may_match(hashes, filter) {
3176 return true;
3178 }
3179 }
3180
3181 !element_is_outside_of_scope(
3182 selector,
3183 *element,
3184 scope_root.root,
3185 context,
3186 matches_shadow_host,
3187 )
3188 })
3189 {
3190 result.push(scope_root);
3191 }
3192 }
3193 result
3194 } else {
3195 potential_scope_roots
3196 };
3197
3198 ScopeRootCandidates {
3199 candidates,
3200 is_trivial,
3201 }
3202}
3203
3204#[derive(Copy, Clone, Debug, MallocSizeOf)]
3207enum StylistImplicitScopeRoot {
3208 Normal(ImplicitScopeRoot),
3209 Cached(usize),
3210}
3211unsafe impl Sync for StylistImplicitScopeRoot {}
3213
3214impl StylistImplicitScopeRoot {
3215 const fn default_const() -> Self {
3216 Self::Normal(ImplicitScopeRoot::DocumentElement)
3218 }
3219}
3220
3221impl Default for StylistImplicitScopeRoot {
3222 fn default() -> Self {
3223 Self::default_const()
3224 }
3225}
3226
3227#[derive(Debug, Clone, MallocSizeOf)]
3233pub struct CascadeData {
3234 normal_rules: ElementAndPseudoRules,
3237
3238 featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
3242
3243 slotted_rules: Option<Box<ElementAndPseudoRules>>,
3251
3252 part_rules: Option<Box<PartElementAndPseudoRules>>,
3257
3258 invalidation_map: InvalidationMap,
3260
3261 relative_selector_invalidation_map: InvalidationMap,
3263
3264 additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
3265
3266 attribute_dependencies: PrecomputedHashSet<LocalName>,
3271
3272 nth_of_class_dependencies: PrecomputedHashSet<Atom>,
3276
3277 nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
3281
3282 nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
3286
3287 state_dependencies: ElementState,
3291
3292 nth_of_state_dependencies: ElementState,
3295
3296 document_state_dependencies: DocumentState,
3300
3301 mapped_ids: PrecomputedHashSet<Atom>,
3306
3307 nth_of_mapped_ids: PrecomputedHashSet<Atom>,
3311
3312 #[ignore_malloc_size_of = "Arc"]
3316 selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
3317
3318 animations: LayerOrderedMap<KeyframesAnimation>,
3321
3322 #[ignore_malloc_size_of = "Arc"]
3325 custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
3326
3327 custom_media: CustomMediaMap,
3329
3330 layer_id: FxHashMap<LayerName, LayerId>,
3332
3333 layers: SmallVec<[CascadeLayer; 1]>,
3335
3336 container_conditions: SmallVec<[ContainerConditionReference; 1]>,
3338
3339 scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
3341
3342 scope_subject_map: ScopeSubjectMap,
3344
3345 effective_media_query_results: EffectiveMediaQueryResults,
3347
3348 extra_data: ExtraStyleData,
3350
3351 rules_source_order: u32,
3354
3355 num_selectors: usize,
3357
3358 num_declarations: usize,
3360}
3361
3362static IMPLICIT_SCOPE: LazyLock<SelectorList<SelectorImpl>> = LazyLock::new(|| {
3363 let list = SelectorList::implicit_scope();
3367 list.mark_as_intentionally_leaked();
3368 list
3369});
3370
3371fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3372 start
3375 .slice()
3376 .iter()
3377 .any(|s| s.matches_featureless_host(true).may_match())
3378}
3379
3380pub fn replace_parent_selector_with_implicit_scope(
3382 selectors: &SelectorList<SelectorImpl>,
3383) -> SelectorList<SelectorImpl> {
3384 selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3385}
3386
3387impl CascadeData {
3388 pub fn new() -> Self {
3390 Self {
3391 normal_rules: ElementAndPseudoRules::default(),
3392 featureless_host_rules: None,
3393 slotted_rules: None,
3394 part_rules: None,
3395 invalidation_map: InvalidationMap::new(),
3396 relative_selector_invalidation_map: InvalidationMap::new(),
3397 additional_relative_selector_invalidation_map:
3398 AdditionalRelativeSelectorInvalidationMap::new(),
3399 nth_of_mapped_ids: PrecomputedHashSet::default(),
3400 nth_of_class_dependencies: PrecomputedHashSet::default(),
3401 nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3402 nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3403 nth_of_state_dependencies: ElementState::empty(),
3404 attribute_dependencies: PrecomputedHashSet::default(),
3405 state_dependencies: ElementState::empty(),
3406 document_state_dependencies: DocumentState::empty(),
3407 mapped_ids: PrecomputedHashSet::default(),
3408 selectors_for_cache_revalidation: SelectorMap::new(),
3409 animations: Default::default(),
3410 custom_property_registrations: Default::default(),
3411 custom_media: Default::default(),
3412 layer_id: Default::default(),
3413 layers: smallvec::smallvec![CascadeLayer::root()],
3414 container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3415 scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3416 scope_subject_map: Default::default(),
3417 extra_data: ExtraStyleData::default(),
3418 effective_media_query_results: EffectiveMediaQueryResults::new(),
3419 rules_source_order: 0,
3420 num_selectors: 0,
3421 num_declarations: 0,
3422 }
3423 }
3424
3425 pub fn rebuild<'a, S>(
3427 &mut self,
3428 device: &Device,
3429 quirks_mode: QuirksMode,
3430 collection: SheetCollectionFlusher<S>,
3431 guard: &SharedRwLockReadGuard,
3432 difference: &mut CascadeDataDifference,
3433 ) -> Result<(), AllocErr>
3434 where
3435 S: StylesheetInDocument + PartialEq + 'static,
3436 {
3437 if !collection.dirty() {
3438 return Ok(());
3439 }
3440
3441 let validity = collection.data_validity();
3442
3443 let mut old_position_try_data = LayerOrderedMap::default();
3444 if validity != DataValidity::Valid {
3445 old_position_try_data = std::mem::take(&mut self.extra_data.position_try_rules);
3446 self.clear_cascade_data();
3447 if validity == DataValidity::FullyInvalid {
3448 self.clear_invalidation_data();
3449 }
3450 }
3451
3452 let mut result = Ok(());
3453
3454 collection.each(|index, stylesheet, rebuild_kind| {
3455 result = self.add_stylesheet(
3456 device,
3457 quirks_mode,
3458 stylesheet,
3459 index,
3460 guard,
3461 rebuild_kind,
3462 None,
3463 if validity == DataValidity::Valid {
3464 Some(difference)
3465 } else {
3466 None
3467 },
3468 );
3469 result.is_ok()
3470 });
3471
3472 self.did_finish_rebuild();
3473
3474 if validity != DataValidity::Valid {
3477 difference.update(&old_position_try_data, &self.extra_data.position_try_rules);
3478 }
3479
3480 result
3481 }
3482
3483 pub fn custom_media_map(&self) -> &CustomMediaMap {
3485 &self.custom_media
3486 }
3487
3488 pub fn invalidation_map(&self) -> &InvalidationMap {
3490 &self.invalidation_map
3491 }
3492
3493 pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3495 &self.relative_selector_invalidation_map
3496 }
3497
3498 pub fn relative_invalidation_map_attributes(
3500 &self,
3501 ) -> &AdditionalRelativeSelectorInvalidationMap {
3502 &self.additional_relative_selector_invalidation_map
3503 }
3504
3505 #[inline]
3508 pub fn has_state_dependency(&self, state: ElementState) -> bool {
3509 self.state_dependencies.intersects(state)
3510 }
3511
3512 #[inline]
3515 pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3516 self.nth_of_custom_state_dependencies.contains(state)
3517 }
3518
3519 #[inline]
3522 pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3523 self.nth_of_state_dependencies.intersects(state)
3524 }
3525
3526 #[inline]
3529 pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3530 self.attribute_dependencies.contains(local_name)
3531 }
3532
3533 #[inline]
3536 pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3537 self.nth_of_mapped_ids.contains(id)
3538 }
3539
3540 #[inline]
3543 pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3544 self.nth_of_class_dependencies.contains(class)
3545 }
3546
3547 #[inline]
3550 pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3551 self.nth_of_attribute_dependencies.contains(local_name)
3552 }
3553
3554 #[inline]
3556 pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3557 self.normal_rules.rules(pseudo_elements)
3558 }
3559
3560 #[inline]
3562 pub fn featureless_host_rules(
3563 &self,
3564 pseudo_elements: &[PseudoElement],
3565 ) -> Option<&SelectorMap<Rule>> {
3566 self.featureless_host_rules
3567 .as_ref()
3568 .and_then(|d| d.rules(pseudo_elements))
3569 }
3570
3571 pub fn any_featureless_host_rules(&self) -> bool {
3573 self.featureless_host_rules.is_some()
3574 }
3575
3576 #[inline]
3578 pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3579 self.slotted_rules
3580 .as_ref()
3581 .and_then(|d| d.rules(pseudo_elements))
3582 }
3583
3584 pub fn any_slotted_rule(&self) -> bool {
3586 self.slotted_rules.is_some()
3587 }
3588
3589 #[inline]
3591 pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3592 self.part_rules
3593 .as_ref()
3594 .and_then(|d| d.rules(pseudo_elements))
3595 }
3596
3597 pub fn any_part_rule(&self) -> bool {
3599 self.part_rules.is_some()
3600 }
3601
3602 #[inline]
3603 fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3604 self.layers[id.0 as usize].order
3605 }
3606
3607 pub(crate) fn container_condition_matches<E>(
3608 &self,
3609 mut id: ContainerConditionId,
3610 stylist: &Stylist,
3611 element: E,
3612 context: &mut MatchingContext<E::Impl>,
3613 ) -> bool
3614 where
3615 E: TElement,
3616 {
3617 loop {
3618 let condition_ref = &self.container_conditions[id.0 as usize];
3619 if condition_ref.conditions.is_empty() {
3620 return true;
3621 }
3622 let matches = condition_ref.conditions.iter().any(|condition| {
3623 condition
3624 .matches(
3625 stylist,
3626 element,
3627 context.extra_data.originating_element_style,
3628 &mut context.extra_data.cascade_input_flags,
3629 )
3630 .to_bool(false)
3631 });
3632 if !matches {
3633 return false;
3634 }
3635 id = condition_ref.parent;
3636 }
3637 }
3638
3639 pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3640 &self,
3641 rule: &Rule,
3642 element: E,
3643 context: &mut MatchingContext<E::Impl>,
3644 ) -> ScopeProximity {
3645 context
3646 .extra_data
3647 .cascade_input_flags
3648 .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3649
3650 let result = scope_root_candidates(
3654 &self.scope_conditions,
3655 rule.scope_condition_id,
3656 &element,
3657 rule.selector.is_part(),
3658 &self.scope_subject_map,
3659 context,
3660 );
3661 for candidate in result.candidates {
3662 if context.nest_for_scope(Some(candidate.root), |context| {
3663 matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3664 }) {
3665 return candidate.proximity;
3666 }
3667 }
3668 ScopeProximity::infinity()
3669 }
3670
3671 fn did_finish_rebuild(&mut self) {
3672 self.shrink_maps_if_needed();
3673 self.compute_layer_order();
3674 }
3675
3676 fn shrink_maps_if_needed(&mut self) {
3677 self.normal_rules.shrink_if_needed();
3678 if let Some(ref mut host_rules) = self.featureless_host_rules {
3679 host_rules.shrink_if_needed();
3680 }
3681 if let Some(ref mut slotted_rules) = self.slotted_rules {
3682 slotted_rules.shrink_if_needed();
3683 }
3684 self.animations.shrink_if_needed();
3685 self.custom_property_registrations.shrink_if_needed();
3686 self.invalidation_map.shrink_if_needed();
3687 self.relative_selector_invalidation_map.shrink_if_needed();
3688 self.additional_relative_selector_invalidation_map
3689 .shrink_if_needed();
3690 self.attribute_dependencies.shrink_if_needed();
3691 self.nth_of_attribute_dependencies.shrink_if_needed();
3692 self.nth_of_custom_state_dependencies.shrink_if_needed();
3693 self.nth_of_class_dependencies.shrink_if_needed();
3694 self.nth_of_mapped_ids.shrink_if_needed();
3695 self.mapped_ids.shrink_if_needed();
3696 self.layer_id.shrink_if_needed();
3697 self.selectors_for_cache_revalidation.shrink_if_needed();
3698 self.scope_subject_map.shrink_if_needed();
3699 }
3700
3701 fn compute_layer_order(&mut self) {
3702 debug_assert_ne!(
3703 self.layers.len(),
3704 0,
3705 "There should be at least the root layer!"
3706 );
3707 if self.layers.len() == 1 {
3708 return; }
3710 let (first, remaining) = self.layers.split_at_mut(1);
3711 let root = &mut first[0];
3712 let mut order = LayerOrder::first();
3713 compute_layer_order_for_subtree(root, remaining, &mut order);
3714
3715 fn compute_layer_order_for_subtree(
3718 parent: &mut CascadeLayer,
3719 remaining_layers: &mut [CascadeLayer],
3720 order: &mut LayerOrder,
3721 ) {
3722 for child in parent.children.iter() {
3723 debug_assert!(
3724 parent.id < *child,
3725 "Children are always registered after parents"
3726 );
3727 let child_index = (child.0 - parent.id.0 - 1) as usize;
3728 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3729 let child = &mut first[child_index];
3730 compute_layer_order_for_subtree(child, remaining, order);
3731 }
3732
3733 if parent.id != LayerId::root() {
3734 parent.order = *order;
3735 order.inc();
3736 }
3737 }
3738 self.extra_data.sort_by_layer(&self.layers);
3739 self.animations
3740 .sort_with(&self.layers, compare_keyframes_in_same_layer);
3741 self.custom_property_registrations.sort(&self.layers)
3742 }
3743
3744 fn collect_applicable_media_query_results_into<S>(
3753 device: &Device,
3754 stylesheet: &S,
3755 guard: &SharedRwLockReadGuard,
3756 results: &mut Vec<MediaListKey>,
3757 contents_list: &mut StyleSheetContentList,
3758 custom_media_map: &mut CustomMediaMap,
3759 ) where
3760 S: StylesheetInDocument + 'static,
3761 {
3762 if !stylesheet.enabled() {
3763 return;
3764 }
3765 if !stylesheet.is_effective_for_device(device, &custom_media_map, guard) {
3766 return;
3767 }
3768
3769 debug!(" + {:?}", stylesheet);
3770 let contents = stylesheet.contents(guard);
3771 results.push(contents.to_media_list_key());
3772
3773 contents_list.push(StylesheetContentsPtr(unsafe {
3775 Arc::from_raw_addrefed(&*contents)
3776 }));
3777
3778 let mut iter = stylesheet
3779 .contents(guard)
3780 .effective_rules(device, custom_media_map, guard);
3781 while let Some(rule) = iter.next() {
3782 match *rule {
3783 CssRule::CustomMedia(ref custom_media) => {
3784 iter.custom_media()
3785 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
3786 },
3787 CssRule::Import(ref lock) => {
3788 let import_rule = lock.read_with(guard);
3789 debug!(" + {:?}", import_rule.stylesheet.media(guard));
3790 results.push(import_rule.to_media_list_key());
3791 },
3792 CssRule::Media(ref media_rule) => {
3793 debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3794 results.push(media_rule.to_media_list_key());
3795 },
3796 _ => {},
3797 }
3798 }
3799 }
3800
3801 fn add_styles(
3802 &mut self,
3803 selectors: &SelectorList<SelectorImpl>,
3804 declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3805 ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3806 containing_rule_state: &ContainingRuleState,
3807 mut replaced_selectors: Option<&mut ReplacedSelectors>,
3808 guard: &SharedRwLockReadGuard,
3809 rebuild_kind: SheetRebuildKind,
3810 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3811 quirks_mode: QuirksMode,
3812 mut collected_scope_dependencies: Option<&mut Vec<Dependency>>,
3813 ) -> Result<(), AllocErr> {
3814 self.num_declarations += declarations.read_with(guard).len();
3815 for selector in selectors.slice() {
3816 self.num_selectors += 1;
3817
3818 let pseudo_elements = selector.pseudo_elements();
3819 let inner_pseudo_element = pseudo_elements.get(0);
3820 if let Some(pseudo) = inner_pseudo_element {
3821 if pseudo.is_precomputed() {
3822 debug_assert!(selector.is_universal());
3823 debug_assert!(ancestor_selectors.is_none());
3824 debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3825 debug_assert!(!containing_rule_state.scope_is_effective());
3827 precomputed_pseudo_element_decls
3828 .as_mut()
3829 .expect("Expected precomputed declarations for the UA level")
3830 .get_or_insert_with(pseudo, Vec::new)
3831 .push(ApplicableDeclarationBlock::new(
3832 StyleSource::from_declarations(declarations.clone()),
3833 self.rules_source_order,
3834 CascadeLevel::new(CascadeOrigin::UA),
3835 selector.specificity(),
3836 LayerOrder::root(),
3837 ScopeProximity::infinity(),
3838 RuleCascadeFlags::empty(),
3839 ));
3840 continue;
3841 }
3842 if pseudo_elements
3843 .iter()
3844 .any(|p| p.is_unknown_webkit_pseudo_element())
3845 {
3846 continue;
3847 }
3848 }
3849
3850 debug_assert!(!pseudo_elements
3851 .iter()
3852 .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3853
3854 let selector = match ancestor_selectors {
3855 Some(ref s) => selector.replace_parent_selector(&s),
3856 None => selector.clone(),
3857 };
3858
3859 let hashes = AncestorHashes::new(&selector, quirks_mode);
3860
3861 let rule = Rule::new(
3862 selector,
3863 hashes,
3864 StyleSource::from_declarations(declarations.clone()),
3865 self.rules_source_order,
3866 containing_rule_state.layer_id,
3867 containing_rule_state.container_condition_id,
3868 containing_rule_state.cascade_flags(),
3869 containing_rule_state.containing_scope_rule_state.id,
3870 );
3871
3872 if let Some(ref mut replaced_selectors) = replaced_selectors {
3873 replaced_selectors.push(rule.selector.clone())
3874 }
3875
3876 if rebuild_kind.should_rebuild_invalidation() {
3877 let mut scope_dependencies = note_selector_for_invalidation(
3878 &rule.selector,
3879 quirks_mode,
3880 &mut self.invalidation_map,
3881 &mut self.relative_selector_invalidation_map,
3882 &mut self.additional_relative_selector_invalidation_map,
3883 None,
3884 None,
3885 )?;
3886 let mut needs_revalidation = false;
3887 let mut visitor = StylistSelectorVisitor {
3888 needs_revalidation: &mut needs_revalidation,
3889 passed_rightmost_selector: false,
3890 in_selector_list_of: SelectorListKind::default(),
3891 mapped_ids: &mut self.mapped_ids,
3892 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3893 attribute_dependencies: &mut self.attribute_dependencies,
3894 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3895 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3896 nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3897 state_dependencies: &mut self.state_dependencies,
3898 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3899 document_state_dependencies: &mut self.document_state_dependencies,
3900 };
3901 rule.selector.visit(&mut visitor);
3902
3903 if needs_revalidation {
3904 self.selectors_for_cache_revalidation.insert(
3905 RevalidationSelectorAndHashes::new(
3906 rule.selector.clone(),
3907 rule.hashes.clone(),
3908 ),
3909 quirks_mode,
3910 )?;
3911 }
3912
3913 match (
3914 scope_dependencies.as_mut(),
3915 collected_scope_dependencies.as_mut(),
3916 ) {
3917 (Some(inner_scope_deps), Some(scope_deps)) => {
3918 scope_deps.append(inner_scope_deps)
3919 },
3920 _ => {},
3921 }
3922 }
3923
3924 if let Some(parts) = rule.selector.parts() {
3928 let map = self
3935 .part_rules
3936 .get_or_insert_with(|| Box::new(Default::default()))
3937 .for_insertion(&pseudo_elements);
3938 map.try_reserve(1)?;
3939 let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3940 vec.try_reserve(1)?;
3941 vec.push(rule);
3942 } else {
3943 let scope_matches_shadow_host = containing_rule_state
3944 .containing_scope_rule_state
3945 .matches_shadow_host
3946 == ScopeMatchesShadowHost::Yes;
3947 let matches_featureless_host_only = match rule
3948 .selector
3949 .matches_featureless_host(scope_matches_shadow_host)
3950 {
3951 MatchesFeaturelessHost::Only => true,
3952 MatchesFeaturelessHost::Yes => {
3953 self.featureless_host_rules
3955 .get_or_insert_with(|| Box::new(Default::default()))
3956 .for_insertion(&pseudo_elements)
3957 .insert(rule.clone(), quirks_mode)?;
3958 false
3959 },
3960 MatchesFeaturelessHost::Never => false,
3961 };
3962
3963 let rules = if matches_featureless_host_only {
3970 self.featureless_host_rules
3971 .get_or_insert_with(|| Box::new(Default::default()))
3972 } else if rule.selector.is_slotted() {
3973 self.slotted_rules
3974 .get_or_insert_with(|| Box::new(Default::default()))
3975 } else {
3976 &mut self.normal_rules
3977 }
3978 .for_insertion(&pseudo_elements);
3979 rules.insert(rule, quirks_mode)?;
3980 }
3981 }
3982 self.rules_source_order += 1;
3983 Ok(())
3984 }
3985
3986 fn add_rule_list<S>(
3987 &mut self,
3988 rules: std::slice::Iter<CssRule>,
3989 device: &Device,
3990 quirks_mode: QuirksMode,
3991 stylesheet: &S,
3992 sheet_index: usize,
3993 guard: &SharedRwLockReadGuard,
3994 rebuild_kind: SheetRebuildKind,
3995 containing_rule_state: &mut ContainingRuleState,
3996 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3997 mut difference: Option<&mut CascadeDataDifference>,
3998 ) -> Result<(), AllocErr>
3999 where
4000 S: StylesheetInDocument + 'static,
4001 {
4002 for rule in rules {
4003 let mut handled = true;
4006 let mut list_for_nested_rules = None;
4007 match *rule {
4008 CssRule::Style(ref locked) => {
4009 let style_rule = locked.read_with(guard);
4010 let has_nested_rules = style_rule.rules.is_some();
4011 let mut replaced_selectors = ReplacedSelectors::new();
4012 let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
4013 let collect_replaced_selectors =
4014 has_nested_rules && ancestor_selectors.is_some();
4015 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4016 .scope_is_effective()
4017 .then(|| Vec::new());
4018 self.add_styles(
4019 &style_rule.selectors,
4020 &style_rule.block,
4021 ancestor_selectors,
4022 containing_rule_state,
4023 if collect_replaced_selectors {
4024 Some(&mut replaced_selectors)
4025 } else {
4026 None
4027 },
4028 guard,
4029 rebuild_kind,
4030 precomputed_pseudo_element_decls.as_deref_mut(),
4031 quirks_mode,
4032 inner_dependencies.as_mut(),
4033 )?;
4034 if let Some(mut scope_dependencies) = inner_dependencies {
4035 containing_rule_state
4036 .containing_scope_rule_state
4037 .inner_dependencies
4038 .append(&mut scope_dependencies);
4039 }
4040 if has_nested_rules {
4041 handled = false;
4042 list_for_nested_rules = Some(if collect_replaced_selectors {
4043 SelectorList::from_iter(replaced_selectors.drain(..))
4044 } else {
4045 style_rule.selectors.clone()
4046 });
4047 }
4048 },
4049 CssRule::NestedDeclarations(ref rule) => {
4050 if let Some(ref ancestor_selectors) =
4051 containing_rule_state.ancestor_selector_lists.last()
4052 {
4053 let decls = &rule.read_with(guard).block;
4054 let selectors = match containing_rule_state.nested_declarations_context {
4055 NestedDeclarationsContext::Style => ancestor_selectors,
4056 NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
4057 };
4058 let mut inner_dependencies: Option<Vec<Dependency>> = containing_rule_state
4059 .scope_is_effective()
4060 .then(|| Vec::new());
4061 self.add_styles(
4062 selectors,
4063 decls,
4064 None,
4065 containing_rule_state,
4066 None,
4067 guard,
4068 SheetRebuildKind::CascadeOnly,
4071 precomputed_pseudo_element_decls.as_deref_mut(),
4072 quirks_mode,
4073 inner_dependencies.as_mut(),
4074 )?;
4075 if let Some(mut scope_dependencies) = inner_dependencies {
4076 containing_rule_state
4077 .containing_scope_rule_state
4078 .inner_dependencies
4079 .append(&mut scope_dependencies);
4080 }
4081 }
4082 },
4083 CssRule::Keyframes(ref keyframes_rule) => {
4084 debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
4085 let keyframes_rule = keyframes_rule.read_with(guard);
4086 let name = keyframes_rule.name.as_atom().clone();
4087 let animation = KeyframesAnimation::from_keyframes(
4088 &keyframes_rule.keyframes,
4089 keyframes_rule.vendor_prefix.clone(),
4090 guard,
4091 );
4092 self.animations.try_insert_with(
4093 name,
4094 animation,
4095 containing_rule_state.layer_id,
4096 compare_keyframes_in_same_layer,
4097 )?;
4098 },
4099 CssRule::Property(ref registration) => {
4100 self.custom_property_registrations.try_insert(
4101 registration.name.0.clone(),
4102 Arc::clone(registration),
4103 containing_rule_state.layer_id,
4104 )?;
4105 },
4106 CssRule::FontFace(ref rule) => {
4107 self.extra_data
4118 .add_font_face(rule, containing_rule_state.layer_id);
4119 },
4120 CssRule::FontFeatureValues(ref rule) => {
4121 self.extra_data
4122 .add_font_feature_values(rule, containing_rule_state.layer_id);
4123 },
4124 CssRule::FontPaletteValues(ref rule) => {
4125 self.extra_data
4126 .add_font_palette_values(rule, containing_rule_state.layer_id);
4127 },
4128 CssRule::CounterStyle(ref rule) => {
4129 self.extra_data.add_counter_style(
4130 guard,
4131 rule,
4132 containing_rule_state.layer_id,
4133 )?;
4134 },
4135 CssRule::PositionTry(ref rule) => {
4136 let name = rule.read_with(guard).name.0.clone();
4137 if let Some(ref mut difference) = difference {
4138 difference.changed_position_try_names.insert(name.clone());
4139 }
4140 self.extra_data.add_position_try(
4141 name,
4142 rule.clone(),
4143 containing_rule_state.layer_id,
4144 )?;
4145 },
4146 CssRule::Page(ref rule) => {
4147 self.extra_data
4148 .add_page(guard, rule, containing_rule_state.layer_id)?;
4149 handled = false;
4150 },
4151 CssRule::ViewTransition(ref rule) => {
4152 self.extra_data
4153 .add_view_transition(rule, containing_rule_state.layer_id);
4154 },
4155 _ => {
4156 handled = false;
4157 },
4158 }
4159
4160 if handled {
4161 if cfg!(debug_assertions) {
4164 let mut effective = false;
4165 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4166 rule,
4167 device,
4168 quirks_mode,
4169 &self.custom_media,
4170 guard,
4171 &mut effective,
4172 );
4173 debug_assert!(children.is_empty());
4174 debug_assert!(effective);
4175 }
4176 continue;
4177 }
4178
4179 let mut effective = false;
4180 let children = EffectiveRulesIterator::<&CustomMediaMap>::children(
4181 rule,
4182 device,
4183 quirks_mode,
4184 &self.custom_media,
4185 guard,
4186 &mut effective,
4187 );
4188 if !effective {
4189 continue;
4190 }
4191
4192 fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
4193 if let Some(id) = data.layer_id.get(layer) {
4197 return *id;
4198 }
4199 let id = LayerId(data.layers.len() as u16);
4200
4201 let parent_layer_id = if layer.layer_names().len() > 1 {
4202 let mut parent = layer.clone();
4203 parent.0.pop();
4204
4205 *data
4206 .layer_id
4207 .get_mut(&parent)
4208 .expect("Parent layers should be registered before child layers")
4209 } else {
4210 LayerId::root()
4211 };
4212
4213 data.layers[parent_layer_id.0 as usize].children.push(id);
4214 data.layers.push(CascadeLayer {
4215 id,
4216 order: LayerOrder::first(),
4219 children: vec![],
4220 });
4221
4222 data.layer_id.insert(layer.clone(), id);
4223
4224 id
4225 }
4226
4227 fn maybe_register_layers(
4228 data: &mut CascadeData,
4229 name: Option<&LayerName>,
4230 containing_rule_state: &mut ContainingRuleState,
4231 ) {
4232 let anon_name;
4233 let name = match name {
4234 Some(name) => name,
4235 None => {
4236 anon_name = LayerName::new_anonymous();
4237 &anon_name
4238 },
4239 };
4240 for name in name.layer_names() {
4241 containing_rule_state.layer_name.0.push(name.clone());
4242 containing_rule_state.layer_id =
4243 maybe_register_layer(data, &containing_rule_state.layer_name);
4244 }
4245 debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
4246 }
4247
4248 let saved_containing_rule_state = containing_rule_state.save();
4249 match *rule {
4250 CssRule::Import(ref lock) => {
4251 let import_rule = lock.read_with(guard);
4252 if rebuild_kind.should_rebuild_invalidation() {
4253 self.effective_media_query_results
4254 .saw_effective(import_rule);
4255 }
4256 match import_rule.layer {
4257 ImportLayer::Named(ref name) => {
4258 maybe_register_layers(self, Some(name), containing_rule_state)
4259 },
4260 ImportLayer::Anonymous => {
4261 maybe_register_layers(self, None, containing_rule_state)
4262 },
4263 ImportLayer::None => {},
4264 }
4265 },
4266 CssRule::Media(ref media_rule) => {
4267 if rebuild_kind.should_rebuild_invalidation() {
4268 self.effective_media_query_results
4269 .saw_effective(&**media_rule);
4270 }
4271 },
4272 CssRule::LayerBlock(ref rule) => {
4273 maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
4274 },
4275 CssRule::CustomMedia(ref custom_media) => {
4276 self.custom_media
4277 .insert(custom_media.name.0.clone(), custom_media.condition.clone());
4278 },
4279 CssRule::LayerStatement(ref rule) => {
4280 for name in &*rule.names {
4281 maybe_register_layers(self, Some(name), containing_rule_state);
4282 containing_rule_state.restore(&saved_containing_rule_state);
4284 }
4285 },
4286 CssRule::Style(..) => {
4287 containing_rule_state.nested_declarations_context =
4288 NestedDeclarationsContext::Style;
4289 if let Some(s) = list_for_nested_rules {
4290 containing_rule_state.ancestor_selector_lists.push(s);
4291 }
4292 },
4293 CssRule::Container(ref rule) => {
4294 let id = ContainerConditionId(self.container_conditions.len() as u16);
4295 let condition = ContainerConditionReference {
4296 parent: containing_rule_state.container_condition_id,
4297 conditions: rule.conditions.0.clone(),
4298 };
4299 self.container_conditions.push(condition);
4300 containing_rule_state.container_condition_id = id;
4301 },
4302 CssRule::StartingStyle(..) => {
4303 containing_rule_state
4304 .cascade_flags
4305 .insert(RuleCascadeFlags::STARTING_STYLE);
4306 },
4307 CssRule::AppearanceBase(..) => {
4308 containing_rule_state
4309 .cascade_flags
4310 .insert(RuleCascadeFlags::APPEARANCE_BASE);
4311 },
4312 CssRule::Scope(ref rule) => {
4313 containing_rule_state.nested_declarations_context =
4314 NestedDeclarationsContext::Scope;
4315 let id = ScopeConditionId(self.scope_conditions.len() as u16);
4316 let mut matches_shadow_host = false;
4317 let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
4318 matches_shadow_host = scope_start_matches_shadow_host(start);
4319 StylistImplicitScopeRoot::default()
4321 } else {
4322 if let Some(root) = stylesheet.implicit_scope_root() {
4325 matches_shadow_host = root.matches_shadow_host();
4326 match root {
4327 ImplicitScopeRoot::InLightTree(_)
4328 | ImplicitScopeRoot::Constructed
4329 | ImplicitScopeRoot::DocumentElement => {
4330 StylistImplicitScopeRoot::Normal(root)
4331 },
4332 ImplicitScopeRoot::ShadowHost(_)
4333 | ImplicitScopeRoot::InShadowTree(_) => {
4334 StylistImplicitScopeRoot::Cached(sheet_index)
4341 },
4342 }
4343 } else {
4344 StylistImplicitScopeRoot::default()
4346 }
4347 };
4348
4349 let replaced =
4350 {
4351 let start = rule.bounds.start.as_ref().map(|selector| {
4352 match containing_rule_state.ancestor_selector_lists.last() {
4353 Some(s) => selector.replace_parent_selector(s),
4354 None => selector.clone(),
4355 }
4356 });
4357 let implicit_scope_selector = &*IMPLICIT_SCOPE;
4358 let end = rule.bounds.end.as_ref().map(|selector| {
4359 selector.replace_parent_selector(implicit_scope_selector)
4360 });
4361 containing_rule_state
4362 .ancestor_selector_lists
4363 .push(implicit_scope_selector.clone());
4364 ScopeBoundsWithHashes::new(quirks_mode, start, end)
4365 };
4366
4367 if let Some(selectors) = replaced.start.as_ref() {
4368 self.scope_subject_map
4369 .add_bound_start(&selectors.selectors, quirks_mode);
4370 }
4371
4372 let is_trivial = replaced.is_trivial();
4373 self.scope_conditions.push(ScopeConditionReference {
4374 parent: containing_rule_state.containing_scope_rule_state.id,
4375 condition: Some(replaced),
4376 implicit_scope_root,
4377 is_trivial,
4378 });
4379
4380 containing_rule_state
4381 .containing_scope_rule_state
4382 .matches_shadow_host
4383 .nest_for_scope(matches_shadow_host);
4384 containing_rule_state.containing_scope_rule_state.id = id;
4385 containing_rule_state
4386 .containing_scope_rule_state
4387 .inner_dependencies
4388 .reserve(children.iter().len());
4389 },
4390 _ => {},
4392 }
4393
4394 if !children.is_empty() {
4395 self.add_rule_list(
4396 children.iter(),
4397 device,
4398 quirks_mode,
4399 stylesheet,
4400 sheet_index,
4401 guard,
4402 rebuild_kind,
4403 containing_rule_state,
4404 precomputed_pseudo_element_decls.as_deref_mut(),
4405 difference.as_deref_mut(),
4406 )?;
4407 }
4408
4409 if let Some(scope_restore_data) =
4410 containing_rule_state.restore(&saved_containing_rule_state)
4411 {
4412 let (cur_scope_inner_dependencies, scope_idx) = scope_restore_data;
4413 let cur_scope = &self.scope_conditions[scope_idx.0 as usize];
4414 if let Some(cond) = cur_scope.condition.as_ref() {
4415 let mut _unused = false;
4416 let visitor = StylistSelectorVisitor {
4417 needs_revalidation: &mut _unused,
4418 passed_rightmost_selector: true,
4419 in_selector_list_of: SelectorListKind::default(),
4420 mapped_ids: &mut self.mapped_ids,
4421 nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
4422 attribute_dependencies: &mut self.attribute_dependencies,
4423 nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
4424 nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
4425 nth_of_custom_state_dependencies: &mut self
4426 .nth_of_custom_state_dependencies,
4427 state_dependencies: &mut self.state_dependencies,
4428 nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
4429 document_state_dependencies: &mut self.document_state_dependencies,
4430 };
4431
4432 let dependency_vector = build_scope_dependencies(
4433 quirks_mode,
4434 cur_scope_inner_dependencies,
4435 visitor,
4436 cond,
4437 &mut self.invalidation_map,
4438 &mut self.relative_selector_invalidation_map,
4439 &mut self.additional_relative_selector_invalidation_map,
4440 )?;
4441
4442 containing_rule_state
4443 .containing_scope_rule_state
4444 .inner_dependencies
4445 .extend(dependency_vector);
4446 }
4447 }
4448 }
4449
4450 Ok(())
4451 }
4452
4453 fn add_stylesheet<S>(
4455 &mut self,
4456 device: &Device,
4457 quirks_mode: QuirksMode,
4458 stylesheet: &S,
4459 sheet_index: usize,
4460 guard: &SharedRwLockReadGuard,
4461 rebuild_kind: SheetRebuildKind,
4462 mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4463 mut difference: Option<&mut CascadeDataDifference>,
4464 ) -> Result<(), AllocErr>
4465 where
4466 S: StylesheetInDocument + 'static,
4467 {
4468 if !stylesheet.enabled() {
4469 return Ok(());
4470 }
4471
4472 if !stylesheet.is_effective_for_device(device, &self.custom_media, guard) {
4473 return Ok(());
4474 }
4475
4476 let contents = stylesheet.contents(guard);
4477 if rebuild_kind.should_rebuild_invalidation() {
4478 self.effective_media_query_results.saw_effective(&*contents);
4479 }
4480
4481 let mut state = ContainingRuleState::default();
4482 self.add_rule_list(
4483 contents.rules(guard).iter(),
4484 device,
4485 quirks_mode,
4486 stylesheet,
4487 sheet_index,
4488 guard,
4489 rebuild_kind,
4490 &mut state,
4491 precomputed_pseudo_element_decls.as_deref_mut(),
4492 difference.as_deref_mut(),
4493 )?;
4494
4495 Ok(())
4496 }
4497
4498 pub fn media_feature_affected_matches<S>(
4501 &self,
4502 stylesheet: &S,
4503 guard: &SharedRwLockReadGuard,
4504 device: &Device,
4505 quirks_mode: QuirksMode,
4506 ) -> bool
4507 where
4508 S: StylesheetInDocument + 'static,
4509 {
4510 use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4511
4512 let effective_now = stylesheet.is_effective_for_device(device, &self.custom_media, guard);
4513
4514 let contents = stylesheet.contents(guard);
4515 let effective_then = self.effective_media_query_results.was_effective(contents);
4516
4517 if effective_now != effective_then {
4518 debug!(
4519 " > Stylesheet {:?} changed -> {}, {}",
4520 stylesheet.media(guard),
4521 effective_then,
4522 effective_now
4523 );
4524 return false;
4525 }
4526
4527 if !effective_now {
4528 return true;
4529 }
4530
4531 let custom_media = CustomMediaMap::default();
4533 let mut iter =
4534 contents.iter_rules::<PotentiallyEffectiveMediaRules, _>(device, &custom_media, guard);
4535 while let Some(rule) = iter.next() {
4536 match *rule {
4537 CssRule::Style(..)
4538 | CssRule::NestedDeclarations(..)
4539 | CssRule::Namespace(..)
4540 | CssRule::FontFace(..)
4541 | CssRule::Container(..)
4542 | CssRule::CounterStyle(..)
4543 | CssRule::Supports(..)
4544 | CssRule::Keyframes(..)
4545 | CssRule::Margin(..)
4546 | CssRule::Page(..)
4547 | CssRule::Property(..)
4548 | CssRule::Document(..)
4549 | CssRule::LayerBlock(..)
4550 | CssRule::LayerStatement(..)
4551 | CssRule::FontPaletteValues(..)
4552 | CssRule::FontFeatureValues(..)
4553 | CssRule::Scope(..)
4554 | CssRule::StartingStyle(..)
4555 | CssRule::AppearanceBase(..)
4556 | CssRule::CustomMedia(..)
4557 | CssRule::PositionTry(..)
4558 | CssRule::ViewTransition(..) => {
4559 continue;
4562 },
4563 CssRule::Import(ref lock) => {
4564 let import_rule = lock.read_with(guard);
4565 let effective_now = match import_rule.stylesheet.media(guard) {
4566 Some(m) => m.evaluate(
4567 device,
4568 quirks_mode,
4569 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4570 ),
4571 None => true,
4572 };
4573 let effective_then = self
4574 .effective_media_query_results
4575 .was_effective(import_rule);
4576 if effective_now != effective_then {
4577 debug!(
4578 " > @import rule {:?} changed {} -> {}",
4579 import_rule.stylesheet.media(guard),
4580 effective_then,
4581 effective_now
4582 );
4583 return false;
4584 }
4585
4586 if !effective_now {
4587 iter.skip_children();
4588 }
4589 },
4590 CssRule::Media(ref media_rule) => {
4591 let mq = media_rule.media_queries.read_with(guard);
4592 let effective_now = mq.evaluate(
4593 device,
4594 quirks_mode,
4595 &mut CustomMediaEvaluator::new(&self.custom_media, guard),
4596 );
4597 let effective_then = self
4598 .effective_media_query_results
4599 .was_effective(&**media_rule);
4600
4601 if effective_now != effective_then {
4602 debug!(
4603 " > @media rule {:?} changed {} -> {}",
4604 mq, effective_then, effective_now
4605 );
4606 return false;
4607 }
4608
4609 if !effective_now {
4610 iter.skip_children();
4611 }
4612 },
4613 }
4614 }
4615
4616 true
4617 }
4618
4619 pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4621 &self.custom_property_registrations
4622 }
4623
4624 fn revalidate_scopes<E: TElement>(
4625 &self,
4626 element: &E,
4627 matching_context: &mut MatchingContext<E::Impl>,
4628 result: &mut ScopeRevalidationResult,
4629 ) {
4630 for condition_id in 1..self.scope_conditions.len() {
4637 let condition = &self.scope_conditions[condition_id];
4638 let matches = if condition.is_trivial {
4639 continue;
4642 } else {
4643 let result = scope_root_candidates(
4644 &self.scope_conditions,
4645 ScopeConditionId(condition_id as u16),
4646 element,
4647 false,
4649 &self.scope_subject_map,
4650 matching_context,
4651 );
4652 !result.candidates.is_empty()
4653 };
4654 result.scopes_matched.push(matches);
4655 }
4656 }
4657
4658 fn clear_cascade_data(&mut self) {
4660 self.normal_rules.clear();
4661 if let Some(ref mut slotted_rules) = self.slotted_rules {
4662 slotted_rules.clear();
4663 }
4664 if let Some(ref mut part_rules) = self.part_rules {
4665 part_rules.clear();
4666 }
4667 if let Some(ref mut host_rules) = self.featureless_host_rules {
4668 host_rules.clear();
4669 }
4670 self.animations.clear();
4671 self.custom_property_registrations.clear();
4672 self.layer_id.clear();
4673 self.layers.clear();
4674 self.layers.push(CascadeLayer::root());
4675 self.custom_media.clear();
4676 self.container_conditions.clear();
4677 self.container_conditions
4678 .push(ContainerConditionReference::none());
4679 self.scope_conditions.clear();
4680 self.scope_conditions.push(ScopeConditionReference::none());
4681 self.extra_data.clear();
4682 self.rules_source_order = 0;
4683 self.num_selectors = 0;
4684 self.num_declarations = 0;
4685 }
4686
4687 fn clear_invalidation_data(&mut self) {
4688 self.invalidation_map.clear();
4689 self.relative_selector_invalidation_map.clear();
4690 self.additional_relative_selector_invalidation_map.clear();
4691 self.attribute_dependencies.clear();
4692 self.nth_of_attribute_dependencies.clear();
4693 self.nth_of_custom_state_dependencies.clear();
4694 self.nth_of_class_dependencies.clear();
4695 self.state_dependencies = ElementState::empty();
4696 self.nth_of_state_dependencies = ElementState::empty();
4697 self.document_state_dependencies = DocumentState::empty();
4698 self.mapped_ids.clear();
4699 self.nth_of_mapped_ids.clear();
4700 self.selectors_for_cache_revalidation.clear();
4701 self.effective_media_query_results.clear();
4702 self.scope_subject_map.clear();
4703 }
4704}
4705
4706fn note_scope_selector_for_invalidation(
4707 quirks_mode: QuirksMode,
4708 scope_dependencies: &Arc<servo_arc::HeaderSlice<(), Dependency>>,
4709 dependency_vector: &mut Vec<Dependency>,
4710 invalidation_map: &mut InvalidationMap,
4711 relative_selector_invalidation_map: &mut InvalidationMap,
4712 additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4713 visitor: &mut StylistSelectorVisitor<'_>,
4714 scope_kind: ScopeDependencyInvalidationKind,
4715 s: &Selector<SelectorImpl>,
4716) -> Result<(), AllocErr> {
4717 let mut new_inner_dependencies = note_selector_for_invalidation(
4718 &s.clone(),
4719 quirks_mode,
4720 invalidation_map,
4721 relative_selector_invalidation_map,
4722 additional_relative_selector_invalidation_map,
4723 Some(&scope_dependencies),
4724 Some(scope_kind),
4725 )?;
4726 s.visit(visitor);
4727 new_inner_dependencies.as_mut().map(|dep| {
4728 dependency_vector.append(dep);
4729 });
4730 Ok(())
4731}
4732
4733fn build_scope_dependencies(
4734 quirks_mode: QuirksMode,
4735 mut cur_scope_inner_dependencies: Vec<Dependency>,
4736 mut visitor: StylistSelectorVisitor<'_>,
4737 cond: &ScopeBoundsWithHashes,
4738 mut invalidation_map: &mut InvalidationMap,
4739 mut relative_selector_invalidation_map: &mut InvalidationMap,
4740 mut additional_relative_selector_invalidation_map: &mut AdditionalRelativeSelectorInvalidationMap,
4741) -> Result<Vec<Dependency>, AllocErr> {
4742 if cond.end.is_some() {
4743 let deps =
4744 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.clone().into_iter());
4745 let mut end_dependency_vector = Vec::new();
4746 for s in cond.end_selectors() {
4747 note_scope_selector_for_invalidation(
4748 quirks_mode,
4749 &deps,
4750 &mut end_dependency_vector,
4751 &mut invalidation_map,
4752 &mut relative_selector_invalidation_map,
4753 &mut additional_relative_selector_invalidation_map,
4754 &mut visitor,
4755 ScopeDependencyInvalidationKind::ScopeEnd,
4756 s,
4757 )?;
4758 }
4759 cur_scope_inner_dependencies.append(&mut end_dependency_vector);
4760 }
4761 let inner_scope_dependencies =
4762 ThinArc::from_header_and_iter((), cur_scope_inner_dependencies.into_iter());
4763
4764 Ok(if cond.start.is_some() {
4765 let mut dependency_vector = Vec::new();
4766 for s in cond.start_selectors() {
4767 note_scope_selector_for_invalidation(
4768 quirks_mode,
4769 &inner_scope_dependencies,
4770 &mut dependency_vector,
4771 &mut invalidation_map,
4772 &mut relative_selector_invalidation_map,
4773 &mut additional_relative_selector_invalidation_map,
4774 &mut visitor,
4775 ScopeDependencyInvalidationKind::ExplicitScope,
4776 s,
4777 )?;
4778 }
4779 dependency_vector
4780 } else {
4781 vec![Dependency::new(
4782 IMPLICIT_SCOPE.slice()[0].clone(),
4783 0,
4784 Some(inner_scope_dependencies),
4785 DependencyInvalidationKind::Scope(ScopeDependencyInvalidationKind::ImplicitScope),
4786 )]
4787 })
4788}
4789
4790impl CascadeDataCacheEntry for CascadeData {
4791 fn rebuild<S>(
4792 device: &Device,
4793 quirks_mode: QuirksMode,
4794 collection: SheetCollectionFlusher<S>,
4795 guard: &SharedRwLockReadGuard,
4796 old: &Self,
4797 difference: &mut CascadeDataDifference,
4798 ) -> Result<Arc<Self>, AllocErr>
4799 where
4800 S: StylesheetInDocument + PartialEq + 'static,
4801 {
4802 debug_assert!(collection.dirty(), "We surely need to do something?");
4803 let mut updatable_entry = match collection.data_validity() {
4805 DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4806 DataValidity::FullyInvalid => Self::new(),
4807 };
4808 updatable_entry.rebuild(device, quirks_mode, collection, guard, difference)?;
4809 Ok(Arc::new(updatable_entry))
4810 }
4811
4812 #[cfg(feature = "gecko")]
4813 fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4814 self.normal_rules.add_size_of(ops, sizes);
4815 if let Some(ref slotted_rules) = self.slotted_rules {
4816 slotted_rules.add_size_of(ops, sizes);
4817 }
4818 if let Some(ref part_rules) = self.part_rules {
4819 part_rules.add_size_of(ops, sizes);
4820 }
4821 if let Some(ref host_rules) = self.featureless_host_rules {
4822 host_rules.add_size_of(ops, sizes);
4823 }
4824 sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4825 sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4826 sizes.mOther += self.animations.size_of(ops);
4827 sizes.mOther += self.effective_media_query_results.size_of(ops);
4828 sizes.mOther += self.extra_data.size_of(ops);
4829 }
4830}
4831
4832impl Default for CascadeData {
4833 fn default() -> Self {
4834 CascadeData::new()
4835 }
4836}
4837
4838#[derive(Clone, Debug, MallocSizeOf)]
4841pub struct Rule {
4842 #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4847 pub selector: Selector<SelectorImpl>,
4848
4849 pub hashes: AncestorHashes,
4851
4852 pub source_order: u32,
4856
4857 pub layer_id: LayerId,
4859
4860 pub container_condition_id: ContainerConditionId,
4862
4863 pub cascade_flags: RuleCascadeFlags,
4865
4866 pub scope_condition_id: ScopeConditionId,
4868
4869 #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4871 pub style_source: StyleSource,
4872}
4873
4874impl SelectorMapEntry for Rule {
4875 fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4876 self.selector.iter()
4877 }
4878}
4879
4880impl Rule {
4881 pub fn specificity(&self) -> u32 {
4883 self.selector.specificity()
4884 }
4885
4886 pub fn to_applicable_declaration_block(
4889 &self,
4890 level: CascadeLevel,
4891 cascade_data: &CascadeData,
4892 scope_proximity: ScopeProximity,
4893 ) -> ApplicableDeclarationBlock {
4894 ApplicableDeclarationBlock::new(
4895 self.style_source.clone(),
4896 self.source_order,
4897 level,
4898 self.specificity(),
4899 cascade_data.layer_order_for(self.layer_id),
4900 scope_proximity,
4901 self.cascade_flags,
4902 )
4903 }
4904
4905 pub fn new(
4907 selector: Selector<SelectorImpl>,
4908 hashes: AncestorHashes,
4909 style_source: StyleSource,
4910 source_order: u32,
4911 layer_id: LayerId,
4912 container_condition_id: ContainerConditionId,
4913 cascade_flags: RuleCascadeFlags,
4914 scope_condition_id: ScopeConditionId,
4915 ) -> Self {
4916 Self {
4917 selector,
4918 hashes,
4919 style_source,
4920 source_order,
4921 layer_id,
4922 container_condition_id,
4923 cascade_flags,
4924 scope_condition_id,
4925 }
4926 }
4927}
4928
4929size_of_test!(Rule, 40);
4934
4935pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4937 let mut needs_revalidation = false;
4938 let mut mapped_ids = Default::default();
4939 let mut nth_of_mapped_ids = Default::default();
4940 let mut attribute_dependencies = Default::default();
4941 let mut nth_of_class_dependencies = Default::default();
4942 let mut nth_of_attribute_dependencies = Default::default();
4943 let mut nth_of_custom_state_dependencies = Default::default();
4944 let mut state_dependencies = ElementState::empty();
4945 let mut nth_of_state_dependencies = ElementState::empty();
4946 let mut document_state_dependencies = DocumentState::empty();
4947 let mut visitor = StylistSelectorVisitor {
4948 passed_rightmost_selector: false,
4949 needs_revalidation: &mut needs_revalidation,
4950 in_selector_list_of: SelectorListKind::default(),
4951 mapped_ids: &mut mapped_ids,
4952 nth_of_mapped_ids: &mut nth_of_mapped_ids,
4953 attribute_dependencies: &mut attribute_dependencies,
4954 nth_of_class_dependencies: &mut nth_of_class_dependencies,
4955 nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4956 nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4957 state_dependencies: &mut state_dependencies,
4958 nth_of_state_dependencies: &mut nth_of_state_dependencies,
4959 document_state_dependencies: &mut document_state_dependencies,
4960 };
4961 s.visit(&mut visitor);
4962 needs_revalidation
4963}