style/
stylist.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Selector matching.
6
7use 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::dom::TElement;
14#[cfg(feature = "gecko")]
15use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
16use crate::invalidation::element::invalidation_map::{
17    note_selector_for_invalidation, AdditionalRelativeSelectorInvalidationMap, Dependency,
18    DependencyInvalidationKind, InvalidationMap, ScopeDependencyInvalidationKind,
19};
20use crate::invalidation::media_queries::{
21    EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
22};
23use crate::invalidation::stylesheets::RuleChangeKind;
24use crate::media_queries::Device;
25use crate::properties::{self, CascadeMode, ComputedValues, FirstLineReparenting};
26use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
27use crate::properties_and_values::registry::{
28    PropertyRegistration, PropertyRegistrationData, ScriptRegistry as CustomPropertyScriptRegistry,
29};
30use crate::rule_cache::{RuleCache, RuleCacheConditions};
31use crate::rule_collector::RuleCollector;
32use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
33use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
34use crate::selector_parser::{
35    NonTSPseudoClass, PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap,
36};
37use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
38use crate::sharing::{RevalidationResult, ScopeRevalidationResult};
39use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
40use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
41use crate::stylesheets::container_rule::ContainerCondition;
42use crate::stylesheets::import_rule::ImportLayer;
43use crate::stylesheets::keyframes_rule::KeyframesAnimation;
44use crate::stylesheets::layer_rule::{LayerName, LayerOrder};
45use crate::stylesheets::scope_rule::{
46    collect_scope_roots, element_is_outside_of_scope, scope_selector_list_is_trivial,
47    ImplicitScopeRoot, ScopeRootCandidate, ScopeSubjectMap, ScopeTarget,
48};
49#[cfg(feature = "gecko")]
50use crate::stylesheets::{
51    CounterStyleRule, FontFaceRule, FontFeatureValuesRule, FontPaletteValuesRule,
52    PagePseudoClassFlags, PositionTryRule,
53};
54use crate::stylesheets::{
55    CssRule, EffectiveRulesIterator, Origin, OriginSet, PageRule, PerOrigin, PerOriginIter,
56    StylesheetContents, StylesheetInDocument,
57};
58use crate::values::{computed, AtomIdent};
59use crate::AllocErr;
60use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
61use dom::{DocumentState, ElementState};
62#[cfg(feature = "gecko")]
63use malloc_size_of::MallocUnconditionalShallowSizeOf;
64use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
65use rustc_hash::FxHashMap;
66use selectors::attr::{CaseSensitivity, NamespaceConstraint};
67use selectors::bloom::BloomFilter;
68use selectors::matching::{
69    matches_selector, selector_may_match, MatchingContext, MatchingMode, NeedsSelectorFlags,
70    SelectorCaches,
71};
72use selectors::matching::{MatchingForInvalidation, VisitedHandlingMode};
73use selectors::parser::{
74    AncestorHashes, Combinator, Component, MatchesFeaturelessHost, Selector, SelectorIter,
75    SelectorList,
76};
77use selectors::visitor::{SelectorListKind, SelectorVisitor};
78use servo_arc::{Arc, ArcBorrow, ThinArc};
79use smallvec::SmallVec;
80use std::cmp::Ordering;
81use std::hash::{Hash, Hasher};
82use std::sync::Mutex;
83use std::{mem, ops};
84
85/// The type of the stylesheets that the stylist contains.
86#[cfg(feature = "servo")]
87pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
88
89/// The type of the stylesheets that the stylist contains.
90#[cfg(feature = "gecko")]
91pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
92
93#[derive(Debug, Clone)]
94struct StylesheetContentsPtr(Arc<StylesheetContents>);
95
96impl PartialEq for StylesheetContentsPtr {
97    #[inline]
98    fn eq(&self, other: &Self) -> bool {
99        Arc::ptr_eq(&self.0, &other.0)
100    }
101}
102
103impl Eq for StylesheetContentsPtr {}
104
105impl Hash for StylesheetContentsPtr {
106    fn hash<H: Hasher>(&self, state: &mut H) {
107        let contents: &StylesheetContents = &*self.0;
108        (contents as *const StylesheetContents).hash(state)
109    }
110}
111
112type StyleSheetContentList = Vec<StylesheetContentsPtr>;
113
114/// A key in the cascade data cache.
115#[derive(Debug, Hash, Default, PartialEq, Eq)]
116struct CascadeDataCacheKey {
117    media_query_results: Vec<MediaListKey>,
118    contents: StyleSheetContentList,
119}
120
121unsafe impl Send for CascadeDataCacheKey {}
122unsafe impl Sync for CascadeDataCacheKey {}
123
124trait CascadeDataCacheEntry: Sized {
125    /// Rebuilds the cascade data for the new stylesheet collection. The
126    /// collection is guaranteed to be dirty.
127    fn rebuild<S>(
128        device: &Device,
129        quirks_mode: QuirksMode,
130        collection: SheetCollectionFlusher<S>,
131        guard: &SharedRwLockReadGuard,
132        old_entry: &Self,
133    ) -> Result<Arc<Self>, AllocErr>
134    where
135        S: StylesheetInDocument + PartialEq + 'static;
136    /// Measures heap memory usage.
137    #[cfg(feature = "gecko")]
138    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
139}
140
141struct CascadeDataCache<Entry> {
142    entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
143}
144
145impl<Entry> CascadeDataCache<Entry>
146where
147    Entry: CascadeDataCacheEntry,
148{
149    fn new() -> Self {
150        Self {
151            entries: Default::default(),
152        }
153    }
154
155    fn len(&self) -> usize {
156        self.entries.len()
157    }
158
159    // FIXME(emilio): This may need to be keyed on quirks-mode too, though for
160    // UA sheets there aren't class / id selectors on those sheets, usually, so
161    // it's probably ok... For the other cache the quirks mode shouldn't differ
162    // so also should be fine.
163    fn lookup<'a, S>(
164        &'a mut self,
165        device: &Device,
166        quirks_mode: QuirksMode,
167        collection: SheetCollectionFlusher<S>,
168        guard: &SharedRwLockReadGuard,
169        old_entry: &Entry,
170    ) -> Result<Option<Arc<Entry>>, AllocErr>
171    where
172        S: StylesheetInDocument + PartialEq + 'static,
173    {
174        use std::collections::hash_map::Entry as HashMapEntry;
175        debug!("StyleSheetCache::lookup({})", self.len());
176
177        if !collection.dirty() {
178            return Ok(None);
179        }
180
181        let mut key = CascadeDataCacheKey::default();
182        for sheet in collection.sheets() {
183            CascadeData::collect_applicable_media_query_results_into(
184                device,
185                sheet,
186                guard,
187                &mut key.media_query_results,
188                &mut key.contents,
189            )
190        }
191
192        let new_entry;
193        match self.entries.entry(key) {
194            HashMapEntry::Vacant(e) => {
195                debug!("> Picking the slow path (not in the cache)");
196                new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
197                e.insert(new_entry.clone());
198            },
199            HashMapEntry::Occupied(mut e) => {
200                // Avoid reusing our old entry (this can happen if we get
201                // invalidated due to CSSOM mutations and our old stylesheet
202                // contents were already unique, for example).
203                if !std::ptr::eq(&**e.get(), old_entry) {
204                    if log_enabled!(log::Level::Debug) {
205                        debug!("cache hit for:");
206                        for sheet in collection.sheets() {
207                            debug!(" > {:?}", sheet);
208                        }
209                    }
210                    // The line below ensures the "committed" bit is updated
211                    // properly.
212                    collection.each(|_, _, _| true);
213                    return Ok(Some(e.get().clone()));
214                }
215
216                debug!("> Picking the slow path due to same entry as old");
217                new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
218                e.insert(new_entry.clone());
219            },
220        }
221
222        Ok(Some(new_entry))
223    }
224
225    /// Returns all the cascade datas that are not being used (that is, that are
226    /// held alive just by this cache).
227    ///
228    /// We return them instead of dropping in place because some of them may
229    /// keep alive some other documents (like the SVG documents kept alive by
230    /// URL references), and thus we don't want to drop them while locking the
231    /// cache to not deadlock.
232    fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
233        let mut unused = SmallVec::new();
234        self.entries.retain(|_key, value| {
235            // is_unique() returns false for static references, but we never
236            // have static references to UserAgentCascadeDatas.  If we did, it
237            // may not make sense to put them in the cache in the first place.
238            if !value.is_unique() {
239                return true;
240            }
241            unused.push(value.clone());
242            false
243        });
244        unused
245    }
246
247    fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
248        mem::take(&mut self.entries)
249    }
250
251    #[cfg(feature = "gecko")]
252    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
253        sizes.mOther += self.entries.shallow_size_of(ops);
254        for (_key, arc) in self.entries.iter() {
255            // These are primary Arc references that can be measured
256            // unconditionally.
257            sizes.mOther += arc.unconditional_shallow_size_of(ops);
258            arc.add_size_of(ops, sizes);
259        }
260    }
261}
262
263/// Measure heap usage of UA_CASCADE_DATA_CACHE.
264#[cfg(feature = "gecko")]
265pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
266    UA_CASCADE_DATA_CACHE
267        .lock()
268        .unwrap()
269        .add_size_of(ops, sizes);
270}
271
272lazy_static! {
273    /// A cache of computed user-agent data, to be shared across documents.
274    static ref UA_CASCADE_DATA_CACHE: Mutex<UserAgentCascadeDataCache> =
275        Mutex::new(UserAgentCascadeDataCache::new());
276}
277
278impl CascadeDataCacheEntry for UserAgentCascadeData {
279    fn rebuild<S>(
280        device: &Device,
281        quirks_mode: QuirksMode,
282        collection: SheetCollectionFlusher<S>,
283        guard: &SharedRwLockReadGuard,
284        _old: &Self,
285    ) -> Result<Arc<Self>, AllocErr>
286    where
287        S: StylesheetInDocument + PartialEq + 'static,
288    {
289        // TODO: Maybe we should support incremental rebuilds, though they seem
290        // uncommon and rebuild() doesn't deal with
291        // precomputed_pseudo_element_decls for now so...
292        let mut new_data = Self {
293            cascade_data: CascadeData::new(),
294            precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
295        };
296
297        for (index, sheet) in collection.sheets().enumerate() {
298            new_data.cascade_data.add_stylesheet(
299                device,
300                quirks_mode,
301                sheet,
302                index,
303                guard,
304                SheetRebuildKind::Full,
305                Some(&mut new_data.precomputed_pseudo_element_decls),
306            )?;
307        }
308
309        new_data.cascade_data.did_finish_rebuild();
310
311        Ok(Arc::new(new_data))
312    }
313
314    #[cfg(feature = "gecko")]
315    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
316        self.cascade_data.add_size_of(ops, sizes);
317        sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
318    }
319}
320
321type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
322
323type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
324
325#[derive(Default)]
326struct UserAgentCascadeData {
327    cascade_data: CascadeData,
328
329    /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
330    ///
331    /// These are eagerly computed once, and then used to resolve the new
332    /// computed values on the fly on layout.
333    ///
334    /// These are only filled from UA stylesheets.
335    precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
336}
337
338lazy_static! {
339    /// The empty UA cascade data for un-filled stylists.
340    static ref EMPTY_UA_CASCADE_DATA: Arc<UserAgentCascadeData> = {
341        let arc = Arc::new(UserAgentCascadeData::default());
342        arc.mark_as_intentionally_leaked();
343        arc
344    };
345}
346
347/// All the computed information for all the stylesheets that apply to the
348/// document.
349#[derive(MallocSizeOf)]
350pub struct DocumentCascadeData {
351    #[ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache or empty"]
352    user_agent: Arc<UserAgentCascadeData>,
353    user: CascadeData,
354    author: CascadeData,
355    per_origin: PerOrigin<()>,
356}
357
358impl Default for DocumentCascadeData {
359    fn default() -> Self {
360        Self {
361            user_agent: EMPTY_UA_CASCADE_DATA.clone(),
362            user: Default::default(),
363            author: Default::default(),
364            per_origin: Default::default(),
365        }
366    }
367}
368
369/// An iterator over the cascade data of a given document.
370pub struct DocumentCascadeDataIter<'a> {
371    iter: PerOriginIter<'a, ()>,
372    cascade_data: &'a DocumentCascadeData,
373}
374
375impl<'a> Iterator for DocumentCascadeDataIter<'a> {
376    type Item = (&'a CascadeData, Origin);
377
378    fn next(&mut self) -> Option<Self::Item> {
379        let (_, origin) = self.iter.next()?;
380        Some((self.cascade_data.borrow_for_origin(origin), origin))
381    }
382}
383
384impl DocumentCascadeData {
385    /// Borrows the cascade data for a given origin.
386    #[inline]
387    pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
388        match origin {
389            Origin::UserAgent => &self.user_agent.cascade_data,
390            Origin::Author => &self.author,
391            Origin::User => &self.user,
392        }
393    }
394
395    fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
396        DocumentCascadeDataIter {
397            iter: self.per_origin.iter_origins(),
398            cascade_data: self,
399        }
400    }
401
402    fn iter_origins_rev(&self) -> DocumentCascadeDataIter<'_> {
403        DocumentCascadeDataIter {
404            iter: self.per_origin.iter_origins_rev(),
405            cascade_data: self,
406        }
407    }
408
409    /// Rebuild the cascade data for the given document stylesheets, and
410    /// optionally with a set of user agent stylesheets.  Returns Err(..)
411    /// to signify OOM.
412    fn rebuild<'a, S>(
413        &mut self,
414        device: &Device,
415        quirks_mode: QuirksMode,
416        mut flusher: DocumentStylesheetFlusher<'a, S>,
417        guards: &StylesheetGuards,
418    ) -> Result<(), AllocErr>
419    where
420        S: StylesheetInDocument + PartialEq + 'static,
421    {
422        // First do UA sheets.
423        {
424            let origin_flusher = flusher.flush_origin(Origin::UserAgent);
425            // Dirty check is just a minor optimization (no need to grab the
426            // lock if nothing has changed).
427            if origin_flusher.dirty() {
428                let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
429                let new_data = ua_cache.lookup(
430                    device,
431                    quirks_mode,
432                    origin_flusher,
433                    guards.ua_or_user,
434                    &self.user_agent,
435                )?;
436                if let Some(new_data) = new_data {
437                    self.user_agent = new_data;
438                }
439                let _unused_entries = ua_cache.take_unused();
440                // See the comments in take_unused() as for why the following
441                // line.
442                std::mem::drop(ua_cache);
443            }
444        }
445
446        // Now do the user sheets.
447        self.user.rebuild(
448            device,
449            quirks_mode,
450            flusher.flush_origin(Origin::User),
451            guards.ua_or_user,
452        )?;
453
454        // And now the author sheets.
455        self.author.rebuild(
456            device,
457            quirks_mode,
458            flusher.flush_origin(Origin::Author),
459            guards.author,
460        )?;
461
462        Ok(())
463    }
464
465    /// Measures heap usage.
466    #[cfg(feature = "gecko")]
467    pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
468        self.user.add_size_of(ops, sizes);
469        self.author.add_size_of(ops, sizes);
470    }
471}
472
473/// Whether author styles are enabled.
474///
475/// This is used to support Gecko.
476#[allow(missing_docs)]
477#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
478pub enum AuthorStylesEnabled {
479    Yes,
480    No,
481}
482
483/// A wrapper over a DocumentStylesheetSet that can be `Sync`, since it's only
484/// used and exposed via mutable methods in the `Stylist`.
485#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
486struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
487// Read above to see why this is fine.
488unsafe impl Sync for StylistStylesheetSet {}
489
490impl StylistStylesheetSet {
491    fn new() -> Self {
492        StylistStylesheetSet(DocumentStylesheetSet::new())
493    }
494}
495
496impl ops::Deref for StylistStylesheetSet {
497    type Target = DocumentStylesheetSet<StylistSheet>;
498
499    fn deref(&self) -> &Self::Target {
500        &self.0
501    }
502}
503
504impl ops::DerefMut for StylistStylesheetSet {
505    fn deref_mut(&mut self) -> &mut Self::Target {
506        &mut self.0
507    }
508}
509
510/// This structure holds all the selectors and device characteristics
511/// for a given document. The selectors are converted into `Rule`s
512/// and sorted into `SelectorMap`s keyed off stylesheet origin and
513/// pseudo-element (see `CascadeData`).
514///
515/// This structure is effectively created once per pipeline, in the
516/// LayoutThread corresponding to that pipeline.
517#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
518pub struct Stylist {
519    /// Device that the stylist is currently evaluating against.
520    ///
521    /// This field deserves a bigger comment due to the different use that Gecko
522    /// and Servo give to it (that we should eventually unify).
523    ///
524    /// With Gecko, the device is never changed. Gecko manually tracks whether
525    /// the device data should be reconstructed, and "resets" the state of the
526    /// device.
527    ///
528    /// On Servo, on the other hand, the device is a really cheap representation
529    /// that is recreated each time some constraint changes and calling
530    /// `set_device`.
531    device: Device,
532
533    /// The list of stylesheets.
534    stylesheets: StylistStylesheetSet,
535
536    /// A cache of CascadeDatas for AuthorStylesheetSets (i.e., shadow DOM).
537    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "XXX: how to handle this?")]
538    author_data_cache: CascadeDataCache<CascadeData>,
539
540    /// If true, the quirks-mode stylesheet is applied.
541    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
542    quirks_mode: QuirksMode,
543
544    /// Selector maps for all of the style sheets in the stylist, after
545    /// evalutaing media rules against the current device, split out per
546    /// cascade level.
547    cascade_data: DocumentCascadeData,
548
549    /// Whether author styles are enabled.
550    author_styles_enabled: AuthorStylesEnabled,
551
552    /// The rule tree, that stores the results of selector matching.
553    rule_tree: RuleTree,
554
555    /// The set of registered custom properties from script.
556    /// <https://drafts.css-houdini.org/css-properties-values-api-1/#dom-window-registeredpropertyset-slot>
557    script_custom_properties: CustomPropertyScriptRegistry,
558
559    /// Initial values for registered custom properties.
560    #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
561    initial_values_for_custom_properties: ComputedCustomProperties,
562
563    /// Flags set from computing registered custom property initial values.
564    initial_values_for_custom_properties_flags: ComputedValueFlags,
565
566    /// The total number of times the stylist has been rebuilt.
567    num_rebuilds: usize,
568}
569
570/// What cascade levels to include when styling elements.
571#[derive(Clone, Copy, PartialEq)]
572pub enum RuleInclusion {
573    /// Include rules for style sheets at all cascade levels.  This is the
574    /// normal rule inclusion mode.
575    All,
576    /// Only include rules from UA and user level sheets.  Used to implement
577    /// `getDefaultComputedStyle`.
578    DefaultOnly,
579}
580
581#[cfg(feature = "gecko")]
582impl From<StyleRuleInclusion> for RuleInclusion {
583    fn from(value: StyleRuleInclusion) -> Self {
584        match value {
585            StyleRuleInclusion::All => RuleInclusion::All,
586            StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
587        }
588    }
589}
590
591/// `:scope` selector, depending on the use case, can match a shadow host.
592/// If used outside of `@scope`, it cannot possibly match the host.
593/// Even when inside of `@scope`, it's conditional if the selector will
594/// match the shadow host.
595#[derive(Clone, Copy, Eq, PartialEq)]
596enum ScopeMatchesShadowHost {
597    NotApplicable,
598    No,
599    Yes,
600}
601
602impl Default for ScopeMatchesShadowHost {
603    fn default() -> Self {
604        Self::NotApplicable
605    }
606}
607
608impl ScopeMatchesShadowHost {
609    fn nest_for_scope(&mut self, matches_shadow_host: bool) {
610        match *self {
611            Self::NotApplicable => {
612                // We're at the outermost `@scope`.
613                *self = if matches_shadow_host {
614                    Self::Yes
615                } else {
616                    Self::No
617                };
618            },
619            Self::Yes if !matches_shadow_host => {
620                // Inner `@scope` will not be able to match the shadow host.
621                *self = Self::No;
622            },
623            _ => (),
624        }
625    }
626}
627
628/// Nested declarations have effectively two behaviors:
629///  * Inside style rules (where they behave as the containing selector).
630///  * Inside @scope (where they behave as :where(:scope)).
631/// It is a bit unfortunate ideally we wouldn't need this, because scope also pushes to the
632/// ancestor_selector_lists, but the behavior isn't quite the same as wrapping in `&`, see
633/// https://github.com/w3c/csswg-drafts/issues/10431
634#[derive(Copy, Clone)]
635enum NestedDeclarationsContext {
636    Style,
637    Scope,
638}
639
640/// A struct containing state from ancestor rules like @layer / @import /
641/// @container / nesting / @scope.
642struct ContainingRuleState {
643    layer_name: LayerName,
644    layer_id: LayerId,
645    container_condition_id: ContainerConditionId,
646    in_starting_style: bool,
647    scope_condition_id: ScopeConditionId,
648    scope_matches_shadow_host: ScopeMatchesShadowHost,
649    ancestor_selector_lists: SmallVec<[SelectorList<SelectorImpl>; 2]>,
650    nested_declarations_context: NestedDeclarationsContext,
651}
652
653impl Default for ContainingRuleState {
654    fn default() -> Self {
655        Self {
656            layer_name: LayerName::new_empty(),
657            layer_id: LayerId::root(),
658            container_condition_id: ContainerConditionId::none(),
659            in_starting_style: false,
660            ancestor_selector_lists: Default::default(),
661            scope_condition_id: ScopeConditionId::none(),
662            scope_matches_shadow_host: Default::default(),
663            nested_declarations_context: NestedDeclarationsContext::Style,
664        }
665    }
666}
667
668struct SavedContainingRuleState {
669    ancestor_selector_lists_len: usize,
670    layer_name_len: usize,
671    layer_id: LayerId,
672    container_condition_id: ContainerConditionId,
673    in_starting_style: bool,
674    scope_condition_id: ScopeConditionId,
675    scope_matches_shadow_host: ScopeMatchesShadowHost,
676    nested_declarations_context: NestedDeclarationsContext,
677}
678
679impl ContainingRuleState {
680    fn save(&self) -> SavedContainingRuleState {
681        SavedContainingRuleState {
682            ancestor_selector_lists_len: self.ancestor_selector_lists.len(),
683            layer_name_len: self.layer_name.0.len(),
684            layer_id: self.layer_id,
685            container_condition_id: self.container_condition_id,
686            in_starting_style: self.in_starting_style,
687            scope_condition_id: self.scope_condition_id,
688            scope_matches_shadow_host: self.scope_matches_shadow_host,
689            nested_declarations_context: self.nested_declarations_context,
690        }
691    }
692
693    fn restore(&mut self, saved: &SavedContainingRuleState) {
694        debug_assert!(self.layer_name.0.len() >= saved.layer_name_len);
695        debug_assert!(self.ancestor_selector_lists.len() >= saved.ancestor_selector_lists_len);
696        self.ancestor_selector_lists
697            .truncate(saved.ancestor_selector_lists_len);
698        self.layer_name.0.truncate(saved.layer_name_len);
699        self.layer_id = saved.layer_id;
700        self.container_condition_id = saved.container_condition_id;
701        self.in_starting_style = saved.in_starting_style;
702        self.scope_condition_id = saved.scope_condition_id;
703        self.scope_matches_shadow_host = saved.scope_matches_shadow_host;
704        self.nested_declarations_context = saved.nested_declarations_context;
705    }
706}
707
708type ReplacedSelectors = SmallVec<[Selector<SelectorImpl>; 4]>;
709
710impl Stylist {
711    /// Construct a new `Stylist`, using given `Device` and `QuirksMode`.
712    /// If more members are added here, think about whether they should
713    /// be reset in clear().
714    #[inline]
715    pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
716        Self {
717            device,
718            quirks_mode,
719            stylesheets: StylistStylesheetSet::new(),
720            author_data_cache: CascadeDataCache::new(),
721            cascade_data: Default::default(),
722            author_styles_enabled: AuthorStylesEnabled::Yes,
723            rule_tree: RuleTree::new(),
724            script_custom_properties: Default::default(),
725            initial_values_for_custom_properties: Default::default(),
726            initial_values_for_custom_properties_flags: Default::default(),
727            num_rebuilds: 0,
728        }
729    }
730
731    /// Returns the document cascade data.
732    #[inline]
733    pub fn cascade_data(&self) -> &DocumentCascadeData {
734        &self.cascade_data
735    }
736
737    /// Returns whether author styles are enabled or not.
738    #[inline]
739    pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
740        self.author_styles_enabled
741    }
742
743    /// Iterate through all the cascade datas from the document.
744    #[inline]
745    pub fn iter_origins(&self) -> DocumentCascadeDataIter<'_> {
746        self.cascade_data.iter_origins()
747    }
748
749    /// Does what the name says, to prevent author_data_cache to grow without
750    /// bound.
751    pub fn remove_unique_author_data_cache_entries(&mut self) {
752        self.author_data_cache.take_unused();
753    }
754
755    /// Returns the custom property registration for this property's name.
756    /// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
757    pub fn get_custom_property_registration(&self, name: &Atom) -> &PropertyRegistrationData {
758        if let Some(registration) = self.custom_property_script_registry().get(name) {
759            return &registration.data;
760        }
761        for (data, _) in self.iter_origins() {
762            if let Some(registration) = data.custom_property_registrations.get(name) {
763                return &registration.data;
764            }
765        }
766        PropertyRegistrationData::unregistered()
767    }
768
769    /// Returns custom properties with their registered initial values.
770    pub fn get_custom_property_initial_values(&self) -> &ComputedCustomProperties {
771        &self.initial_values_for_custom_properties
772    }
773
774    /// Returns flags set from computing the registered custom property initial values.
775    pub fn get_custom_property_initial_values_flags(&self) -> ComputedValueFlags {
776        self.initial_values_for_custom_properties_flags
777    }
778
779    /// Rebuild custom properties with their registered initial values.
780    /// https://drafts.css-houdini.org/css-properties-values-api-1/#determining-registration
781    pub fn rebuild_initial_values_for_custom_properties(&mut self) {
782        let mut initial_values = ComputedCustomProperties::default();
783        let initial_values_flags;
784        {
785            let mut seen_names = PrecomputedHashSet::default();
786            let mut rule_cache_conditions = RuleCacheConditions::default();
787            let context = computed::Context::new_for_initial_at_property_value(
788                self,
789                &mut rule_cache_conditions,
790            );
791
792            for (k, v) in self.custom_property_script_registry().properties().iter() {
793                seen_names.insert(k.clone());
794                let Ok(value) = v.compute_initial_value(&context) else {
795                    continue;
796                };
797                let map = if v.inherits() {
798                    &mut initial_values.inherited
799                } else {
800                    &mut initial_values.non_inherited
801                };
802                map.insert(k, value);
803            }
804            for (data, _) in self.iter_origins() {
805                for (k, v) in data.custom_property_registrations.iter() {
806                    if seen_names.insert(k.clone()) {
807                        let last_value = &v.last().unwrap().0;
808                        let Ok(value) = last_value.compute_initial_value(&context) else {
809                            continue;
810                        };
811                        let map = if last_value.inherits() {
812                            &mut initial_values.inherited
813                        } else {
814                            &mut initial_values.non_inherited
815                        };
816                        map.insert(k, value);
817                    }
818                }
819            }
820            initial_values_flags = context.builder.flags();
821        }
822        self.initial_values_for_custom_properties_flags = initial_values_flags;
823        self.initial_values_for_custom_properties = initial_values;
824    }
825
826    /// Rebuilds (if needed) the CascadeData given a sheet collection.
827    pub fn rebuild_author_data<S>(
828        &mut self,
829        old_data: &CascadeData,
830        collection: SheetCollectionFlusher<S>,
831        guard: &SharedRwLockReadGuard,
832    ) -> Result<Option<Arc<CascadeData>>, AllocErr>
833    where
834        S: StylesheetInDocument + PartialEq + 'static,
835    {
836        self.author_data_cache
837            .lookup(&self.device, self.quirks_mode, collection, guard, old_data)
838    }
839
840    /// Iterate over the extra data in origin order.
841    #[inline]
842    pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator<'_> {
843        ExtraStyleDataIterator(self.cascade_data.iter_origins())
844    }
845
846    /// Iterate over the extra data in reverse origin order.
847    #[inline]
848    pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator<'_> {
849        ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
850    }
851
852    /// Returns the number of selectors.
853    pub fn num_selectors(&self) -> usize {
854        self.cascade_data
855            .iter_origins()
856            .map(|(d, _)| d.num_selectors)
857            .sum()
858    }
859
860    /// Returns the number of declarations.
861    pub fn num_declarations(&self) -> usize {
862        self.cascade_data
863            .iter_origins()
864            .map(|(d, _)| d.num_declarations)
865            .sum()
866    }
867
868    /// Returns the number of times the stylist has been rebuilt.
869    pub fn num_rebuilds(&self) -> usize {
870        self.num_rebuilds
871    }
872
873    /// Returns the number of revalidation_selectors.
874    pub fn num_revalidation_selectors(&self) -> usize {
875        self.cascade_data
876            .iter_origins()
877            .map(|(data, _)| data.selectors_for_cache_revalidation.len())
878            .sum()
879    }
880
881    /// Returns the number of entries in invalidation maps.
882    pub fn num_invalidations(&self) -> usize {
883        self.cascade_data
884            .iter_origins()
885            .map(|(data, _)| {
886                data.invalidation_map.len() + data.relative_selector_invalidation_map.len()
887            })
888            .sum()
889    }
890
891    /// Returns whether the given DocumentState bit is relied upon by a selector
892    /// of some rule.
893    pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
894        self.cascade_data
895            .iter_origins()
896            .any(|(d, _)| d.document_state_dependencies.intersects(state))
897    }
898
899    /// Flush the list of stylesheets if they changed, ensuring the stylist is
900    /// up-to-date.
901    pub fn flush<E>(
902        &mut self,
903        guards: &StylesheetGuards,
904        document_element: Option<E>,
905        snapshots: Option<&SnapshotMap>,
906    ) -> bool
907    where
908        E: TElement,
909    {
910        if !self.stylesheets.has_changed() {
911            return false;
912        }
913
914        self.num_rebuilds += 1;
915
916        let flusher = self.stylesheets.flush(document_element, snapshots);
917
918        let had_invalidations = flusher.had_invalidations();
919
920        self.cascade_data
921            .rebuild(&self.device, self.quirks_mode, flusher, guards)
922            .unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
923
924        self.rebuild_initial_values_for_custom_properties();
925
926        had_invalidations
927    }
928
929    /// Insert a given stylesheet before another stylesheet in the document.
930    pub fn insert_stylesheet_before(
931        &mut self,
932        sheet: StylistSheet,
933        before_sheet: StylistSheet,
934        guard: &SharedRwLockReadGuard,
935    ) {
936        self.stylesheets
937            .insert_stylesheet_before(Some(&self.device), sheet, before_sheet, guard)
938    }
939
940    /// Marks a given stylesheet origin as dirty, due to, for example, changes
941    /// in the declarations that affect a given rule.
942    ///
943    /// FIXME(emilio): Eventually it'd be nice for this to become more
944    /// fine-grained.
945    pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
946        self.stylesheets.force_dirty(origins)
947    }
948
949    /// Sets whether author style is enabled or not.
950    pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
951        self.author_styles_enabled = enabled;
952    }
953
954    /// Returns whether we've recorded any stylesheet change so far.
955    pub fn stylesheets_have_changed(&self) -> bool {
956        self.stylesheets.has_changed()
957    }
958
959    /// Appends a new stylesheet to the current set.
960    pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
961        self.stylesheets
962            .append_stylesheet(Some(&self.device), sheet, guard)
963    }
964
965    /// Remove a given stylesheet to the current set.
966    pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
967        self.stylesheets
968            .remove_stylesheet(Some(&self.device), sheet, guard)
969    }
970
971    /// Notify of a change of a given rule.
972    pub fn rule_changed(
973        &mut self,
974        sheet: &StylistSheet,
975        rule: &CssRule,
976        guard: &SharedRwLockReadGuard,
977        change_kind: RuleChangeKind,
978    ) {
979        self.stylesheets
980            .rule_changed(Some(&self.device), sheet, rule, guard, change_kind)
981    }
982
983    /// Appends a new stylesheet to the current set.
984    #[inline]
985    pub fn sheet_count(&self, origin: Origin) -> usize {
986        self.stylesheets.sheet_count(origin)
987    }
988
989    /// Appends a new stylesheet to the current set.
990    #[inline]
991    pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
992        self.stylesheets.get(origin, index)
993    }
994
995    /// Returns whether for any of the applicable style rule data a given
996    /// condition is true.
997    pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
998    where
999        E: TElement,
1000        F: FnMut(&CascadeData) -> bool,
1001    {
1002        if f(&self.cascade_data.user_agent.cascade_data) {
1003            return true;
1004        }
1005
1006        let mut maybe = false;
1007
1008        let doc_author_rules_apply =
1009            element.each_applicable_non_document_style_rule_data(|data, _| {
1010                maybe = maybe || f(&*data);
1011            });
1012
1013        if maybe || f(&self.cascade_data.user) {
1014            return true;
1015        }
1016
1017        doc_author_rules_apply && f(&self.cascade_data.author)
1018    }
1019
1020    /// Execute callback for all applicable style rule data.
1021    pub fn for_each_cascade_data_with_scope<'a, E, F>(&'a self, element: E, mut f: F)
1022    where
1023        E: TElement + 'a,
1024        F: FnMut(&'a CascadeData, Option<E>),
1025    {
1026        f(&self.cascade_data.user_agent.cascade_data, None);
1027        element.each_applicable_non_document_style_rule_data(|data, scope| {
1028            f(data, Some(scope));
1029        });
1030        f(&self.cascade_data.user, None);
1031        f(&self.cascade_data.author, None);
1032    }
1033
1034    /// Computes the style for a given "precomputed" pseudo-element, taking the
1035    /// universal rules and applying them.
1036    pub fn precomputed_values_for_pseudo<E>(
1037        &self,
1038        guards: &StylesheetGuards,
1039        pseudo: &PseudoElement,
1040        parent: Option<&ComputedValues>,
1041    ) -> Arc<ComputedValues>
1042    where
1043        E: TElement,
1044    {
1045        debug_assert!(pseudo.is_precomputed());
1046
1047        let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
1048
1049        self.precomputed_values_for_pseudo_with_rule_node::<E>(guards, pseudo, parent, rule_node)
1050    }
1051
1052    /// Computes the style for a given "precomputed" pseudo-element with
1053    /// given rule node.
1054    ///
1055    /// TODO(emilio): The type parameter could go away with a void type
1056    /// implementing TElement.
1057    pub fn precomputed_values_for_pseudo_with_rule_node<E>(
1058        &self,
1059        guards: &StylesheetGuards,
1060        pseudo: &PseudoElement,
1061        parent: Option<&ComputedValues>,
1062        rules: StrongRuleNode,
1063    ) -> Arc<ComputedValues>
1064    where
1065        E: TElement,
1066    {
1067        self.compute_pseudo_element_style_with_inputs::<E>(
1068            CascadeInputs {
1069                rules: Some(rules),
1070                visited_rules: None,
1071                flags: Default::default(),
1072            },
1073            pseudo,
1074            guards,
1075            parent,
1076            /* element */ None,
1077        )
1078    }
1079
1080    /// Returns the rule node for a given precomputed pseudo-element.
1081    ///
1082    /// If we want to include extra declarations to this precomputed
1083    /// pseudo-element, we can provide a vector of ApplicableDeclarationBlocks
1084    /// to extra_declarations. This is useful for @page rules.
1085    pub fn rule_node_for_precomputed_pseudo(
1086        &self,
1087        guards: &StylesheetGuards,
1088        pseudo: &PseudoElement,
1089        mut extra_declarations: Vec<ApplicableDeclarationBlock>,
1090    ) -> StrongRuleNode {
1091        let mut declarations_with_extra;
1092        let declarations = match self
1093            .cascade_data
1094            .user_agent
1095            .precomputed_pseudo_element_decls
1096            .get(pseudo)
1097        {
1098            Some(declarations) => {
1099                if !extra_declarations.is_empty() {
1100                    declarations_with_extra = declarations.clone();
1101                    declarations_with_extra.append(&mut extra_declarations);
1102                    &*declarations_with_extra
1103                } else {
1104                    &**declarations
1105                }
1106            },
1107            None => &[],
1108        };
1109
1110        self.rule_tree.insert_ordered_rules_with_important(
1111            declarations.into_iter().map(|a| a.clone().for_rule_tree()),
1112            guards,
1113        )
1114    }
1115
1116    /// Returns the style for an anonymous box of the given type.
1117    ///
1118    /// TODO(emilio): The type parameter could go away with a void type
1119    /// implementing TElement.
1120    #[cfg(feature = "servo")]
1121    pub fn style_for_anonymous<E>(
1122        &self,
1123        guards: &StylesheetGuards,
1124        pseudo: &PseudoElement,
1125        parent_style: &ComputedValues,
1126    ) -> Arc<ComputedValues>
1127    where
1128        E: TElement,
1129    {
1130        self.precomputed_values_for_pseudo::<E>(guards, &pseudo, Some(parent_style))
1131    }
1132
1133    /// Computes a pseudo-element style lazily during layout.
1134    ///
1135    /// This can only be done for a certain set of pseudo-elements, like
1136    /// :selection.
1137    ///
1138    /// Check the documentation on lazy pseudo-elements in
1139    /// docs/components/style.md
1140    pub fn lazily_compute_pseudo_element_style<E>(
1141        &self,
1142        guards: &StylesheetGuards,
1143        element: E,
1144        pseudo: &PseudoElement,
1145        rule_inclusion: RuleInclusion,
1146        originating_element_style: &ComputedValues,
1147        is_probe: bool,
1148        matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1149    ) -> Option<Arc<ComputedValues>>
1150    where
1151        E: TElement,
1152    {
1153        let cascade_inputs = self.lazy_pseudo_rules(
1154            guards,
1155            element,
1156            originating_element_style,
1157            pseudo,
1158            is_probe,
1159            rule_inclusion,
1160            matching_fn,
1161        )?;
1162
1163        Some(self.compute_pseudo_element_style_with_inputs(
1164            cascade_inputs,
1165            pseudo,
1166            guards,
1167            Some(originating_element_style),
1168            Some(element),
1169        ))
1170    }
1171
1172    /// Computes a pseudo-element style lazily using the given CascadeInputs.
1173    /// This can be used for truly lazy pseudo-elements or to avoid redoing
1174    /// selector matching for eager pseudo-elements when we need to recompute
1175    /// their style with a new parent style.
1176    pub fn compute_pseudo_element_style_with_inputs<E>(
1177        &self,
1178        inputs: CascadeInputs,
1179        pseudo: &PseudoElement,
1180        guards: &StylesheetGuards,
1181        parent_style: Option<&ComputedValues>,
1182        element: Option<E>,
1183    ) -> Arc<ComputedValues>
1184    where
1185        E: TElement,
1186    {
1187        // FIXME(emilio): The lack of layout_parent_style here could be
1188        // worrying, but we're probably dropping the display fixup for
1189        // pseudos other than before and after, so it's probably ok.
1190        //
1191        // (Though the flags don't indicate so!)
1192        //
1193        // It'd be fine to assert that this isn't called with a parent style
1194        // where display contents is in effect, but in practice this is hard to
1195        // do for stuff like :-moz-fieldset-content with a
1196        // <fieldset style="display: contents">. That is, the computed value of
1197        // display for the fieldset is "contents", even though it's not the used
1198        // value, so we don't need to adjust in a different way anyway.
1199        self.cascade_style_and_visited(
1200            element,
1201            Some(pseudo),
1202            inputs,
1203            guards,
1204            parent_style,
1205            parent_style,
1206            FirstLineReparenting::No,
1207            /* rule_cache = */ None,
1208            &mut RuleCacheConditions::default(),
1209        )
1210    }
1211
1212    /// Computes a style using the given CascadeInputs.  This can be used to
1213    /// compute a style any time we know what rules apply and just need to use
1214    /// the given parent styles.
1215    ///
1216    /// parent_style is the style to inherit from for properties affected by
1217    /// first-line ancestors.
1218    ///
1219    /// parent_style_ignoring_first_line is the style to inherit from for
1220    /// properties not affected by first-line ancestors.
1221    ///
1222    /// layout_parent_style is the style used for some property fixups.  It's
1223    /// the style of the nearest ancestor with a layout box.
1224    pub fn cascade_style_and_visited<E>(
1225        &self,
1226        element: Option<E>,
1227        pseudo: Option<&PseudoElement>,
1228        inputs: CascadeInputs,
1229        guards: &StylesheetGuards,
1230        parent_style: Option<&ComputedValues>,
1231        layout_parent_style: Option<&ComputedValues>,
1232        first_line_reparenting: FirstLineReparenting,
1233        rule_cache: Option<&RuleCache>,
1234        rule_cache_conditions: &mut RuleCacheConditions,
1235    ) -> Arc<ComputedValues>
1236    where
1237        E: TElement,
1238    {
1239        debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1240
1241        // We need to compute visited values if we have visited rules or if our
1242        // parent has visited values.
1243        let visited_rules = match inputs.visited_rules.as_ref() {
1244            Some(rules) => Some(rules),
1245            None => {
1246                if parent_style.and_then(|s| s.visited_style()).is_some() {
1247                    Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1248                } else {
1249                    None
1250                }
1251            },
1252        };
1253
1254        let mut implemented_pseudo = None;
1255        // Read the comment on `precomputed_values_for_pseudo` to see why it's
1256        // difficult to assert that display: contents nodes never arrive here
1257        // (tl;dr: It doesn't apply for replaced elements and such, but the
1258        // computed value is still "contents").
1259        //
1260        // FIXME(emilio): We should assert that it holds if pseudo.is_none()!
1261        properties::cascade::<E>(
1262            &self,
1263            pseudo.or_else(|| {
1264                implemented_pseudo = element.unwrap().implemented_pseudo_element();
1265                implemented_pseudo.as_ref()
1266            }),
1267            inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1268            guards,
1269            parent_style,
1270            layout_parent_style,
1271            first_line_reparenting,
1272            visited_rules,
1273            inputs.flags,
1274            rule_cache,
1275            rule_cache_conditions,
1276            element,
1277        )
1278    }
1279
1280    /// Computes the cascade inputs for a lazily-cascaded pseudo-element.
1281    ///
1282    /// See the documentation on lazy pseudo-elements in
1283    /// docs/components/style.md
1284    fn lazy_pseudo_rules<E>(
1285        &self,
1286        guards: &StylesheetGuards,
1287        element: E,
1288        originating_element_style: &ComputedValues,
1289        pseudo: &PseudoElement,
1290        is_probe: bool,
1291        rule_inclusion: RuleInclusion,
1292        matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1293    ) -> Option<CascadeInputs>
1294    where
1295        E: TElement,
1296    {
1297        debug_assert!(pseudo.is_lazy());
1298
1299        let mut selector_caches = SelectorCaches::default();
1300        // No need to bother setting the selector flags when we're computing
1301        // default styles.
1302        let needs_selector_flags = if rule_inclusion == RuleInclusion::DefaultOnly {
1303            NeedsSelectorFlags::No
1304        } else {
1305            NeedsSelectorFlags::Yes
1306        };
1307
1308        let mut declarations = ApplicableDeclarationList::new();
1309        let mut matching_context = MatchingContext::<'_, E::Impl>::new(
1310            MatchingMode::ForStatelessPseudoElement,
1311            None,
1312            &mut selector_caches,
1313            self.quirks_mode,
1314            needs_selector_flags,
1315            MatchingForInvalidation::No,
1316        );
1317
1318        matching_context.pseudo_element_matching_fn = matching_fn;
1319        matching_context.extra_data.originating_element_style = Some(originating_element_style);
1320
1321        self.push_applicable_declarations(
1322            element,
1323            Some(&pseudo),
1324            None,
1325            None,
1326            /* animation_declarations = */ Default::default(),
1327            rule_inclusion,
1328            &mut declarations,
1329            &mut matching_context,
1330        );
1331
1332        if declarations.is_empty() && is_probe {
1333            return None;
1334        }
1335
1336        let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1337
1338        let mut visited_rules = None;
1339        if originating_element_style.visited_style().is_some() {
1340            let mut declarations = ApplicableDeclarationList::new();
1341            let mut selector_caches = SelectorCaches::default();
1342
1343            let mut matching_context = MatchingContext::<'_, E::Impl>::new_for_visited(
1344                MatchingMode::ForStatelessPseudoElement,
1345                None,
1346                &mut selector_caches,
1347                VisitedHandlingMode::RelevantLinkVisited,
1348                selectors::matching::IncludeStartingStyle::No,
1349                self.quirks_mode,
1350                needs_selector_flags,
1351                MatchingForInvalidation::No,
1352            );
1353            matching_context.pseudo_element_matching_fn = matching_fn;
1354            matching_context.extra_data.originating_element_style = Some(originating_element_style);
1355
1356            self.push_applicable_declarations(
1357                element,
1358                Some(&pseudo),
1359                None,
1360                None,
1361                /* animation_declarations = */ Default::default(),
1362                rule_inclusion,
1363                &mut declarations,
1364                &mut matching_context,
1365            );
1366            if !declarations.is_empty() {
1367                let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1368                    declarations.drain(..).map(|a| a.for_rule_tree()),
1369                    guards,
1370                );
1371                if rule_node != *self.rule_tree.root() {
1372                    visited_rules = Some(rule_node);
1373                }
1374            }
1375        }
1376
1377        Some(CascadeInputs {
1378            rules: Some(rules),
1379            visited_rules,
1380            flags: matching_context.extra_data.cascade_input_flags,
1381        })
1382    }
1383
1384    /// Set a given device, which may change the styles that apply to the
1385    /// document.
1386    ///
1387    /// Returns the sheet origins that were actually affected.
1388    ///
1389    /// This means that we may need to rebuild style data even if the
1390    /// stylesheets haven't changed.
1391    ///
1392    /// Also, the device that arrives here may need to take the viewport rules
1393    /// into account.
1394    pub fn set_device(&mut self, device: Device, guards: &StylesheetGuards) -> OriginSet {
1395        self.device = device;
1396        self.media_features_change_changed_style(guards, &self.device)
1397    }
1398
1399    /// Returns whether, given a media feature change, any previously-applicable
1400    /// style has become non-applicable, or vice-versa for each origin, using
1401    /// `device`.
1402    pub fn media_features_change_changed_style(
1403        &self,
1404        guards: &StylesheetGuards,
1405        device: &Device,
1406    ) -> OriginSet {
1407        debug!("Stylist::media_features_change_changed_style {:?}", device);
1408
1409        let mut origins = OriginSet::empty();
1410        let stylesheets = self.stylesheets.iter();
1411
1412        for (stylesheet, origin) in stylesheets {
1413            if origins.contains(origin.into()) {
1414                continue;
1415            }
1416
1417            let guard = guards.for_origin(origin);
1418            let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1419
1420            let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1421                stylesheet,
1422                guard,
1423                device,
1424                self.quirks_mode,
1425            );
1426
1427            if affected_changed {
1428                origins |= origin;
1429            }
1430        }
1431
1432        origins
1433    }
1434
1435    /// Returns the Quirks Mode of the document.
1436    pub fn quirks_mode(&self) -> QuirksMode {
1437        self.quirks_mode
1438    }
1439
1440    /// Sets the quirks mode of the document.
1441    pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1442        if self.quirks_mode == quirks_mode {
1443            return;
1444        }
1445        self.quirks_mode = quirks_mode;
1446        self.force_stylesheet_origins_dirty(OriginSet::all());
1447    }
1448
1449    /// Returns the applicable CSS declarations for the given element.
1450    pub fn push_applicable_declarations<E>(
1451        &self,
1452        element: E,
1453        pseudo_element: Option<&PseudoElement>,
1454        style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1455        smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1456        animation_declarations: AnimationDeclarations,
1457        rule_inclusion: RuleInclusion,
1458        applicable_declarations: &mut ApplicableDeclarationList,
1459        context: &mut MatchingContext<E::Impl>,
1460    ) where
1461        E: TElement,
1462    {
1463        let mut cur = element;
1464        let mut pseudos = SmallVec::new();
1465        if let Some(pseudo) = pseudo_element {
1466            pseudos.push(pseudo.clone());
1467        }
1468        while let Some(p) = cur.implemented_pseudo_element() {
1469            pseudos.push(p);
1470            let Some(parent_pseudo) = cur.pseudo_element_originating_element() else {
1471                break;
1472            };
1473            cur = parent_pseudo;
1474        }
1475        RuleCollector::new(
1476            self,
1477            element,
1478            pseudos,
1479            style_attribute,
1480            smil_override,
1481            animation_declarations,
1482            rule_inclusion,
1483            applicable_declarations,
1484            context,
1485        )
1486        .collect_all();
1487    }
1488
1489    /// Given an id, returns whether there might be any rules for that id in any
1490    /// of our rule maps.
1491    #[inline]
1492    pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1493    where
1494        E: TElement,
1495    {
1496        // If id needs to be compared case-insensitively, the logic below
1497        // wouldn't work. Just conservatively assume it may have such rules.
1498        match self.quirks_mode().classes_and_ids_case_sensitivity() {
1499            CaseSensitivity::AsciiCaseInsensitive => return true,
1500            CaseSensitivity::CaseSensitive => {},
1501        }
1502
1503        self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1504    }
1505
1506    /// Looks up a CascadeData-dependent rule for a given element.
1507    ///
1508    /// NOTE(emilio): This is a best-effort thing, the right fix is a bit TBD because it involves
1509    /// "recording" which tree the name came from, see [1][2].
1510    ///
1511    /// [1]: https://github.com/w3c/csswg-drafts/issues/1995
1512    /// [2]: https://bugzil.la/1458189
1513    #[inline]
1514    fn lookup_element_dependent_at_rule<'a, T, F, E>(
1515        &'a self,
1516        element: E,
1517        find_in: F,
1518    ) -> Option<&'a T>
1519    where
1520        E: TElement + 'a,
1521        F: Fn(&'a CascadeData) -> Option<&'a T>,
1522    {
1523        macro_rules! try_find_in {
1524            ($data:expr) => {
1525                if let Some(thing) = find_in(&$data) {
1526                    return Some(thing);
1527                }
1528            };
1529        }
1530
1531        let mut result = None;
1532        let doc_rules_apply =
1533            element.each_applicable_non_document_style_rule_data(|data, _host| {
1534                if result.is_none() {
1535                    result = find_in(data);
1536                }
1537            });
1538
1539        if result.is_some() {
1540            return result;
1541        }
1542
1543        if doc_rules_apply {
1544            try_find_in!(self.cascade_data.author);
1545        }
1546        try_find_in!(self.cascade_data.user);
1547        try_find_in!(self.cascade_data.user_agent.cascade_data);
1548
1549        None
1550    }
1551
1552    /// Returns the registered `@keyframes` animation for the specified name.
1553    #[inline]
1554    pub fn lookup_keyframes<'a, E>(
1555        &'a self,
1556        name: &Atom,
1557        element: E,
1558    ) -> Option<&'a KeyframesAnimation>
1559    where
1560        E: TElement + 'a,
1561    {
1562        self.lookup_element_dependent_at_rule(element, |data| data.animations.get(name))
1563    }
1564
1565    /// Returns the registered `@position-try-rule` animation for the specified name.
1566    #[inline]
1567    #[cfg(feature = "gecko")]
1568    pub fn lookup_position_try<'a, E>(
1569        &'a self,
1570        name: &Atom,
1571        element: E,
1572    ) -> Option<&'a Arc<Locked<PositionTryRule>>>
1573    where
1574        E: TElement + 'a,
1575    {
1576        self.lookup_element_dependent_at_rule(element, |data| {
1577            data.extra_data.position_try_rules.get(name)
1578        })
1579    }
1580
1581    /// Computes the match results of a given element against the set of
1582    /// revalidation selectors.
1583    pub fn match_revalidation_selectors<E>(
1584        &self,
1585        element: E,
1586        bloom: Option<&BloomFilter>,
1587        selector_caches: &mut SelectorCaches,
1588        needs_selector_flags: NeedsSelectorFlags,
1589    ) -> RevalidationResult
1590    where
1591        E: TElement,
1592    {
1593        // NB: `MatchingMode` doesn't really matter, given we don't share style
1594        // between pseudos.
1595        let mut matching_context = MatchingContext::new(
1596            MatchingMode::Normal,
1597            bloom,
1598            selector_caches,
1599            self.quirks_mode,
1600            needs_selector_flags,
1601            MatchingForInvalidation::No,
1602        );
1603
1604        // Note that, by the time we're revalidating, we're guaranteed that the
1605        // candidate and the entry have the same id, classes, and local name.
1606        // This means we're guaranteed to get the same rulehash buckets for all
1607        // the lookups, which means that the bitvecs are comparable. We verify
1608        // this in the caller by asserting that the bitvecs are same-length.
1609        let mut result = RevalidationResult::default();
1610        let mut relevant_attributes = &mut result.relevant_attributes;
1611        let selectors_matched = &mut result.selectors_matched;
1612
1613        let matches_document_rules =
1614            element.each_applicable_non_document_style_rule_data(|data, host| {
1615                matching_context.with_shadow_host(Some(host), |matching_context| {
1616                    data.selectors_for_cache_revalidation.lookup(
1617                        element,
1618                        self.quirks_mode,
1619                        Some(&mut relevant_attributes),
1620                        |selector_and_hashes| {
1621                            selectors_matched.push(matches_selector(
1622                                &selector_and_hashes.selector,
1623                                selector_and_hashes.selector_offset,
1624                                Some(&selector_and_hashes.hashes),
1625                                &element,
1626                                matching_context,
1627                            ));
1628                            true
1629                        },
1630                    );
1631                })
1632            });
1633
1634        for (data, origin) in self.cascade_data.iter_origins() {
1635            if origin == Origin::Author && !matches_document_rules {
1636                continue;
1637            }
1638
1639            data.selectors_for_cache_revalidation.lookup(
1640                element,
1641                self.quirks_mode,
1642                Some(&mut relevant_attributes),
1643                |selector_and_hashes| {
1644                    selectors_matched.push(matches_selector(
1645                        &selector_and_hashes.selector,
1646                        selector_and_hashes.selector_offset,
1647                        Some(&selector_and_hashes.hashes),
1648                        &element,
1649                        &mut matching_context,
1650                    ));
1651                    true
1652                },
1653            );
1654        }
1655
1656        result
1657    }
1658
1659    /// Computes currently active scopes for the given element for revalidation purposes.
1660    pub fn revalidate_scopes<E: TElement>(
1661        &self,
1662        element: &E,
1663        selector_caches: &mut SelectorCaches,
1664        needs_selector_flags: NeedsSelectorFlags,
1665    ) -> ScopeRevalidationResult {
1666        let mut matching_context = MatchingContext::new(
1667            MatchingMode::Normal,
1668            None,
1669            selector_caches,
1670            self.quirks_mode,
1671            needs_selector_flags,
1672            MatchingForInvalidation::No,
1673        );
1674
1675        let mut result = ScopeRevalidationResult::default();
1676        let matches_document_rules =
1677            element.each_applicable_non_document_style_rule_data(|data, host| {
1678                matching_context.with_shadow_host(Some(host), |matching_context| {
1679                    data.revalidate_scopes(element, matching_context, &mut result);
1680                })
1681            });
1682
1683        for (data, origin) in self.cascade_data.iter_origins() {
1684            if origin == Origin::Author && !matches_document_rules {
1685                continue;
1686            }
1687
1688            data.revalidate_scopes(element, &mut matching_context, &mut result);
1689        }
1690
1691        result
1692    }
1693
1694    /// Computes styles for a given declaration with parent_style.
1695    ///
1696    /// FIXME(emilio): the lack of pseudo / cascade flags look quite dubious,
1697    /// hopefully this is only used for some canvas font stuff.
1698    ///
1699    /// TODO(emilio): The type parameter can go away when
1700    /// https://github.com/rust-lang/rust/issues/35121 is fixed.
1701    pub fn compute_for_declarations<E>(
1702        &self,
1703        guards: &StylesheetGuards,
1704        parent_style: &ComputedValues,
1705        declarations: Arc<Locked<PropertyDeclarationBlock>>,
1706    ) -> Arc<ComputedValues>
1707    where
1708        E: TElement,
1709    {
1710        let block = declarations.read_with(guards.author);
1711
1712        // We don't bother inserting these declarations in the rule tree, since
1713        // it'd be quite useless and slow.
1714        //
1715        // TODO(emilio): Now that we fixed bug 1493420, we should consider
1716        // reversing this as it shouldn't be slow anymore, and should avoid
1717        // generating two instantiations of apply_declarations.
1718        properties::apply_declarations::<E, _>(
1719            &self,
1720            /* pseudo = */ None,
1721            self.rule_tree.root(),
1722            guards,
1723            block.declaration_importance_iter().map(|(declaration, _)| {
1724                (
1725                    declaration,
1726                    CascadePriority::new(
1727                        CascadeLevel::same_tree_author_normal(),
1728                        LayerOrder::root(),
1729                    ),
1730                )
1731            }),
1732            Some(parent_style),
1733            Some(parent_style),
1734            FirstLineReparenting::No,
1735            CascadeMode::Unvisited {
1736                visited_rules: None,
1737            },
1738            Default::default(),
1739            /* rule_cache = */ None,
1740            &mut Default::default(),
1741            /* element = */ None,
1742        )
1743    }
1744
1745    /// Accessor for a shared reference to the device.
1746    #[inline]
1747    pub fn device(&self) -> &Device {
1748        &self.device
1749    }
1750
1751    /// Accessor for a mutable reference to the device.
1752    #[inline]
1753    pub fn device_mut(&mut self) -> &mut Device {
1754        &mut self.device
1755    }
1756
1757    /// Accessor for a shared reference to the rule tree.
1758    #[inline]
1759    pub fn rule_tree(&self) -> &RuleTree {
1760        &self.rule_tree
1761    }
1762
1763    /// Returns the script-registered custom property registry.
1764    #[inline]
1765    pub fn custom_property_script_registry(&self) -> &CustomPropertyScriptRegistry {
1766        &self.script_custom_properties
1767    }
1768
1769    /// Returns the script-registered custom property registry, as a mutable ref.
1770    #[inline]
1771    pub fn custom_property_script_registry_mut(&mut self) -> &mut CustomPropertyScriptRegistry {
1772        &mut self.script_custom_properties
1773    }
1774
1775    /// Measures heap usage.
1776    #[cfg(feature = "gecko")]
1777    pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
1778        self.cascade_data.add_size_of(ops, sizes);
1779        self.author_data_cache.add_size_of(ops, sizes);
1780        sizes.mRuleTree += self.rule_tree.size_of(ops);
1781
1782        // We may measure other fields in the future if DMD says it's worth it.
1783    }
1784
1785    /// Shutdown the static data that this module stores.
1786    pub fn shutdown() {
1787        let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
1788    }
1789}
1790
1791/// A vector that is sorted in layer order.
1792#[derive(Clone, Debug, Deref, MallocSizeOf)]
1793pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
1794impl<T> Default for LayerOrderedVec<T> {
1795    fn default() -> Self {
1796        Self(Default::default())
1797    }
1798}
1799
1800/// A map that is sorted in layer order.
1801#[derive(Clone, Debug, Deref, MallocSizeOf)]
1802pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
1803impl<T> Default for LayerOrderedMap<T> {
1804    fn default() -> Self {
1805        Self(Default::default())
1806    }
1807}
1808
1809#[cfg(feature = "gecko")]
1810impl<T: 'static> LayerOrderedVec<T> {
1811    fn clear(&mut self) {
1812        self.0.clear();
1813    }
1814    fn push(&mut self, v: T, id: LayerId) {
1815        self.0.push((v, id));
1816    }
1817    fn sort(&mut self, layers: &[CascadeLayer]) {
1818        self.0
1819            .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
1820    }
1821}
1822
1823impl<T: 'static> LayerOrderedMap<T> {
1824    fn shrink_if_needed(&mut self) {
1825        self.0.shrink_if_needed();
1826    }
1827    fn clear(&mut self) {
1828        self.0.clear();
1829    }
1830    fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
1831        self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
1832    }
1833    fn try_insert_with(
1834        &mut self,
1835        name: Atom,
1836        v: T,
1837        id: LayerId,
1838        cmp: impl Fn(&T, &T) -> Ordering,
1839    ) -> Result<(), AllocErr> {
1840        self.0.try_reserve(1)?;
1841        let vec = self.0.entry(name).or_default();
1842        if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
1843            if *last_id == id {
1844                if cmp(&val, &v) != Ordering::Greater {
1845                    *val = v;
1846                }
1847                return Ok(());
1848            }
1849        }
1850        vec.push((v, id));
1851        Ok(())
1852    }
1853    fn sort(&mut self, layers: &[CascadeLayer]) {
1854        self.sort_with(layers, |_, _| Ordering::Equal)
1855    }
1856    fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
1857        for (_, v) in self.0.iter_mut() {
1858            v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
1859                let order1 = layers[id1.0 as usize].order;
1860                let order2 = layers[id2.0 as usize].order;
1861                order1.cmp(&order2).then_with(|| cmp(v1, v2))
1862            })
1863        }
1864    }
1865    /// Get an entry on the LayerOrderedMap by name.
1866    pub fn get(&self, name: &Atom) -> Option<&T> {
1867        let vec = self.0.get(name)?;
1868        Some(&vec.last()?.0)
1869    }
1870}
1871
1872/// Wrapper to allow better tracking of memory usage by page rule lists.
1873///
1874/// This includes the layer ID for use with the named page table.
1875#[derive(Clone, Debug, MallocSizeOf)]
1876pub struct PageRuleData {
1877    /// Layer ID for sorting page rules after matching.
1878    pub layer: LayerId,
1879    /// Page rule
1880    #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
1881    pub rule: Arc<Locked<PageRule>>,
1882}
1883
1884/// Stores page rules indexed by page names.
1885#[derive(Clone, Debug, Default, MallocSizeOf)]
1886pub struct PageRuleMap {
1887    /// Page rules, indexed by page name. An empty atom indicates no page name.
1888    pub rules: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
1889}
1890
1891#[cfg(feature = "gecko")]
1892impl PageRuleMap {
1893    #[inline]
1894    fn clear(&mut self) {
1895        self.rules.clear();
1896    }
1897
1898    /// Uses page-name and pseudo-classes to match all applicable
1899    /// page-rules and append them to the matched_rules vec.
1900    /// This will ensure correct rule order for cascading.
1901    pub fn match_and_append_rules(
1902        &self,
1903        matched_rules: &mut Vec<ApplicableDeclarationBlock>,
1904        origin: Origin,
1905        guards: &StylesheetGuards,
1906        cascade_data: &DocumentCascadeData,
1907        name: &Option<Atom>,
1908        pseudos: PagePseudoClassFlags,
1909    ) {
1910        let level = match origin {
1911            Origin::UserAgent => CascadeLevel::UANormal,
1912            Origin::User => CascadeLevel::UserNormal,
1913            Origin::Author => CascadeLevel::same_tree_author_normal(),
1914        };
1915        let cascade_data = cascade_data.borrow_for_origin(origin);
1916        let start = matched_rules.len();
1917
1918        self.match_and_add_rules(
1919            matched_rules,
1920            level,
1921            guards,
1922            cascade_data,
1923            &atom!(""),
1924            pseudos,
1925        );
1926        if let Some(name) = name {
1927            self.match_and_add_rules(matched_rules, level, guards, cascade_data, name, pseudos);
1928        }
1929
1930        // Because page-rules do not have source location information stored,
1931        // use stable sort to ensure source locations are preserved.
1932        matched_rules[start..].sort_by_key(|block| block.sort_key());
1933    }
1934
1935    fn match_and_add_rules(
1936        &self,
1937        extra_declarations: &mut Vec<ApplicableDeclarationBlock>,
1938        level: CascadeLevel,
1939        guards: &StylesheetGuards,
1940        cascade_data: &CascadeData,
1941        name: &Atom,
1942        pseudos: PagePseudoClassFlags,
1943    ) {
1944        let rules = match self.rules.get(name) {
1945            Some(rules) => rules,
1946            None => return,
1947        };
1948        for data in rules.iter() {
1949            let rule = data.rule.read_with(level.guard(&guards));
1950            let specificity = match rule.match_specificity(pseudos) {
1951                Some(specificity) => specificity,
1952                None => continue,
1953            };
1954            let block = rule.block.clone();
1955            extra_declarations.push(ApplicableDeclarationBlock::new(
1956                StyleSource::from_declarations(block),
1957                0,
1958                level,
1959                specificity,
1960                cascade_data.layer_order_for(data.layer),
1961                ScopeProximity::infinity(), // Page rule can't have nested rules anyway.
1962            ));
1963        }
1964    }
1965}
1966
1967impl MallocShallowSizeOf for PageRuleMap {
1968    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1969        self.rules.shallow_size_of(ops)
1970    }
1971}
1972
1973/// This struct holds data which users of Stylist may want to extract
1974/// from stylesheets which can be done at the same time as updating.
1975#[derive(Clone, Debug, Default)]
1976#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
1977pub struct ExtraStyleData {
1978    /// A list of effective font-face rules and their origin.
1979    #[cfg(feature = "gecko")]
1980    pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
1981
1982    /// A list of effective font-feature-values rules.
1983    #[cfg(feature = "gecko")]
1984    pub font_feature_values: LayerOrderedVec<Arc<FontFeatureValuesRule>>,
1985
1986    /// A list of effective font-palette-values rules.
1987    #[cfg(feature = "gecko")]
1988    pub font_palette_values: LayerOrderedVec<Arc<FontPaletteValuesRule>>,
1989
1990    /// A map of effective counter-style rules.
1991    #[cfg(feature = "gecko")]
1992    pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
1993
1994    /// A map of effective @position-try rules.
1995    #[cfg(feature = "gecko")]
1996    pub position_try_rules: LayerOrderedMap<Arc<Locked<PositionTryRule>>>,
1997
1998    /// A map of effective page rules.
1999    #[cfg(feature = "gecko")]
2000    pub pages: PageRuleMap,
2001}
2002
2003#[cfg(feature = "gecko")]
2004impl ExtraStyleData {
2005    /// Add the given @font-face rule.
2006    fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
2007        self.font_faces.push(rule.clone(), layer);
2008    }
2009
2010    /// Add the given @font-feature-values rule.
2011    fn add_font_feature_values(&mut self, rule: &Arc<FontFeatureValuesRule>, layer: LayerId) {
2012        self.font_feature_values.push(rule.clone(), layer);
2013    }
2014
2015    /// Add the given @font-palette-values rule.
2016    fn add_font_palette_values(&mut self, rule: &Arc<FontPaletteValuesRule>, layer: LayerId) {
2017        self.font_palette_values.push(rule.clone(), layer);
2018    }
2019
2020    /// Add the given @counter-style rule.
2021    fn add_counter_style(
2022        &mut self,
2023        guard: &SharedRwLockReadGuard,
2024        rule: &Arc<Locked<CounterStyleRule>>,
2025        layer: LayerId,
2026    ) -> Result<(), AllocErr> {
2027        let name = rule.read_with(guard).name().0.clone();
2028        self.counter_styles.try_insert(name, rule.clone(), layer)
2029    }
2030
2031    /// Add the given @position-try rule.
2032    fn add_position_try(
2033        &mut self,
2034        guard: &SharedRwLockReadGuard,
2035        rule: &Arc<Locked<PositionTryRule>>,
2036        layer: LayerId,
2037    ) -> Result<(), AllocErr> {
2038        let name = rule.read_with(guard).name.0.clone();
2039        self.position_try_rules
2040            .try_insert(name, rule.clone(), layer)
2041    }
2042
2043    /// Add the given @page rule.
2044    fn add_page(
2045        &mut self,
2046        guard: &SharedRwLockReadGuard,
2047        rule: &Arc<Locked<PageRule>>,
2048        layer: LayerId,
2049    ) -> Result<(), AllocErr> {
2050        let page_rule = rule.read_with(guard);
2051        let mut add_rule = |name| {
2052            let vec = self.pages.rules.entry(name).or_default();
2053            vec.push(PageRuleData {
2054                layer,
2055                rule: rule.clone(),
2056            });
2057        };
2058        if page_rule.selectors.0.is_empty() {
2059            add_rule(atom!(""));
2060        } else {
2061            for selector in page_rule.selectors.as_slice() {
2062                add_rule(selector.name.0.clone());
2063            }
2064        }
2065        Ok(())
2066    }
2067
2068    fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
2069        self.font_faces.sort(layers);
2070        self.font_feature_values.sort(layers);
2071        self.font_palette_values.sort(layers);
2072        self.counter_styles.sort(layers);
2073        self.position_try_rules.sort(layers);
2074    }
2075
2076    fn clear(&mut self) {
2077        self.font_faces.clear();
2078        self.font_feature_values.clear();
2079        self.font_palette_values.clear();
2080        self.counter_styles.clear();
2081        self.position_try_rules.clear();
2082        self.pages.clear();
2083    }
2084}
2085
2086// Don't let a prefixed keyframes animation override
2087// a non-prefixed one.
2088fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
2089    if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
2090        Ordering::Equal
2091    } else if v2.vendor_prefix.is_some() {
2092        Ordering::Greater
2093    } else {
2094        Ordering::Less
2095    }
2096}
2097
2098/// An iterator over the different ExtraStyleData.
2099pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
2100
2101impl<'a> Iterator for ExtraStyleDataIterator<'a> {
2102    type Item = (&'a ExtraStyleData, Origin);
2103
2104    fn next(&mut self) -> Option<Self::Item> {
2105        self.0.next().map(|d| (&d.0.extra_data, d.1))
2106    }
2107}
2108
2109#[cfg(feature = "gecko")]
2110impl MallocSizeOf for ExtraStyleData {
2111    /// Measure heap usage.
2112    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
2113        let mut n = 0;
2114        n += self.font_faces.shallow_size_of(ops);
2115        n += self.font_feature_values.shallow_size_of(ops);
2116        n += self.font_palette_values.shallow_size_of(ops);
2117        n += self.counter_styles.shallow_size_of(ops);
2118        n += self.position_try_rules.shallow_size_of(ops);
2119        n += self.pages.shallow_size_of(ops);
2120        n
2121    }
2122}
2123
2124/// SelectorMapEntry implementation for use in our revalidation selector map.
2125#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
2126#[derive(Clone, Debug)]
2127struct RevalidationSelectorAndHashes {
2128    #[cfg_attr(
2129        feature = "gecko",
2130        ignore_malloc_size_of = "CssRules have primary refs, we measure there"
2131    )]
2132    selector: Selector<SelectorImpl>,
2133    selector_offset: usize,
2134    hashes: AncestorHashes,
2135}
2136
2137impl RevalidationSelectorAndHashes {
2138    fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
2139        let selector_offset = {
2140            // We basically want to check whether the first combinator is a
2141            // pseudo-element combinator.  If it is, we want to use the offset
2142            // one past it.  Otherwise, our offset is 0.
2143            let mut index = 0;
2144            let mut iter = selector.iter();
2145
2146            // First skip over the first ComplexSelector.
2147            //
2148            // We can't check what sort of what combinator we have until we do
2149            // that.
2150            for _ in &mut iter {
2151                index += 1; // Simple selector
2152            }
2153
2154            match iter.next_sequence() {
2155                Some(Combinator::PseudoElement) => index + 1, // +1 for the combinator
2156                _ => 0,
2157            }
2158        };
2159
2160        RevalidationSelectorAndHashes {
2161            selector,
2162            selector_offset,
2163            hashes,
2164        }
2165    }
2166}
2167
2168impl SelectorMapEntry for RevalidationSelectorAndHashes {
2169    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
2170        self.selector.iter_from(self.selector_offset)
2171    }
2172}
2173
2174/// A selector visitor implementation that collects all the state the Stylist
2175/// cares about a selector.
2176struct StylistSelectorVisitor<'a> {
2177    /// Whether we've past the rightmost compound selector, not counting
2178    /// pseudo-elements.
2179    passed_rightmost_selector: bool,
2180
2181    /// Whether the selector needs revalidation for the style sharing cache.
2182    needs_revalidation: &'a mut bool,
2183
2184    /// Flags for which selector list-containing components the visitor is
2185    /// inside of, if any
2186    in_selector_list_of: SelectorListKind,
2187
2188    /// The filter with all the id's getting referenced from rightmost
2189    /// selectors.
2190    mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2191
2192    /// The filter with the IDs getting referenced from the selector list of
2193    /// :nth-child(... of <selector list>) selectors.
2194    nth_of_mapped_ids: &'a mut PrecomputedHashSet<Atom>,
2195
2196    /// The filter with the local names of attributes there are selectors for.
2197    attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2198
2199    /// The filter with the classes getting referenced from the selector list of
2200    /// :nth-child(... of <selector list>) selectors.
2201    nth_of_class_dependencies: &'a mut PrecomputedHashSet<Atom>,
2202
2203    /// The filter with the local names of attributes there are selectors for
2204    /// within the selector list of :nth-child(... of <selector list>)
2205    /// selectors.
2206    nth_of_attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
2207
2208    /// The filter with the local names of custom states in selectors for
2209    /// within the selector list of :nth-child(... of <selector list>)
2210    /// selectors.
2211    nth_of_custom_state_dependencies: &'a mut PrecomputedHashSet<AtomIdent>,
2212
2213    /// All the states selectors in the page reference.
2214    state_dependencies: &'a mut ElementState,
2215
2216    /// All the state selectors in the page reference within the selector list
2217    /// of :nth-child(... of <selector list>) selectors.
2218    nth_of_state_dependencies: &'a mut ElementState,
2219
2220    /// All the document states selectors in the page reference.
2221    document_state_dependencies: &'a mut DocumentState,
2222}
2223
2224fn component_needs_revalidation(
2225    c: &Component<SelectorImpl>,
2226    passed_rightmost_selector: bool,
2227) -> bool {
2228    match *c {
2229        Component::ID(_) => {
2230            // TODO(emilio): This could also check that the ID is not already in
2231            // the rule hash. In that case, we could avoid making this a
2232            // revalidation selector too.
2233            //
2234            // See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
2235            passed_rightmost_selector
2236        },
2237        Component::AttributeInNoNamespaceExists { .. }
2238        | Component::AttributeInNoNamespace { .. }
2239        | Component::AttributeOther(_)
2240        | Component::Empty
2241        | Component::Nth(_)
2242        | Component::NthOf(_)
2243        | Component::Has(_) => true,
2244        Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
2245        _ => false,
2246    }
2247}
2248
2249impl<'a> StylistSelectorVisitor<'a> {
2250    fn visit_nested_selector(
2251        &mut self,
2252        in_selector_list_of: SelectorListKind,
2253        selector: &Selector<SelectorImpl>,
2254    ) {
2255        let old_passed_rightmost_selector = self.passed_rightmost_selector;
2256        let old_in_selector_list_of = self.in_selector_list_of;
2257
2258        self.passed_rightmost_selector = false;
2259        self.in_selector_list_of = in_selector_list_of;
2260        let _ret = selector.visit(self);
2261        debug_assert!(_ret, "We never return false");
2262
2263        self.passed_rightmost_selector = old_passed_rightmost_selector;
2264        self.in_selector_list_of = old_in_selector_list_of;
2265    }
2266}
2267
2268impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
2269    type Impl = SelectorImpl;
2270
2271    fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
2272        *self.needs_revalidation =
2273            *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
2274
2275        // NOTE(emilio): this call happens before we visit any of the simple
2276        // selectors in the next ComplexSelector, so we can use this to skip
2277        // looking at them.
2278        self.passed_rightmost_selector = self.passed_rightmost_selector
2279            || !matches!(combinator, None | Some(Combinator::PseudoElement));
2280
2281        true
2282    }
2283
2284    fn visit_selector_list(
2285        &mut self,
2286        list_kind: SelectorListKind,
2287        list: &[Selector<Self::Impl>],
2288    ) -> bool {
2289        let in_selector_list_of = self.in_selector_list_of | list_kind;
2290        for selector in list {
2291            self.visit_nested_selector(in_selector_list_of, selector);
2292        }
2293        true
2294    }
2295
2296    fn visit_relative_selector_list(
2297        &mut self,
2298        list: &[selectors::parser::RelativeSelector<Self::Impl>],
2299    ) -> bool {
2300        let in_selector_list_of = self.in_selector_list_of | SelectorListKind::HAS;
2301        for selector in list {
2302            self.visit_nested_selector(in_selector_list_of, &selector.selector);
2303        }
2304        true
2305    }
2306
2307    fn visit_attribute_selector(
2308        &mut self,
2309        _ns: &NamespaceConstraint<&Namespace>,
2310        name: &LocalName,
2311        lower_name: &LocalName,
2312    ) -> bool {
2313        if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2314            self.nth_of_attribute_dependencies.insert(name.clone());
2315            if name != lower_name {
2316                self.nth_of_attribute_dependencies
2317                    .insert(lower_name.clone());
2318            }
2319        }
2320
2321        self.attribute_dependencies.insert(name.clone());
2322        if name != lower_name {
2323            self.attribute_dependencies.insert(lower_name.clone());
2324        }
2325
2326        true
2327    }
2328
2329    fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
2330        *self.needs_revalidation = *self.needs_revalidation
2331            || component_needs_revalidation(s, self.passed_rightmost_selector);
2332
2333        match *s {
2334            Component::NonTSPseudoClass(NonTSPseudoClass::CustomState(ref name)) => {
2335                // CustomStateSet is special cased as it is a functional pseudo
2336                // class with unbounded inner values. This is different to
2337                // other psuedo class like :emtpy or :dir() which can be packed
2338                // into the ElementState bitflags. For CustomState, however,
2339                // the state name should be checked for presence in the selector.
2340                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2341                    self.nth_of_custom_state_dependencies.insert(name.0.clone());
2342                }
2343            },
2344            Component::NonTSPseudoClass(ref p) => {
2345                self.state_dependencies.insert(p.state_flag());
2346                self.document_state_dependencies
2347                    .insert(p.document_state_flag());
2348
2349                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2350                    self.nth_of_state_dependencies.insert(p.state_flag());
2351                }
2352            },
2353            Component::ID(ref id) => {
2354                // We want to stop storing mapped ids as soon as we've moved off
2355                // the rightmost ComplexSelector that is not a pseudo-element.
2356                //
2357                // That can be detected by a visit_complex_selector call with a
2358                // combinator other than None and PseudoElement.
2359                //
2360                // Importantly, this call happens before we visit any of the
2361                // simple selectors in that ComplexSelector.
2362                //
2363                // NOTE(emilio): See the comment regarding on when this may
2364                // break in visit_complex_selector.
2365                if !self.passed_rightmost_selector {
2366                    self.mapped_ids.insert(id.0.clone());
2367                }
2368
2369                if self.in_selector_list_of.relevant_to_nth_of_dependencies() {
2370                    self.nth_of_mapped_ids.insert(id.0.clone());
2371                }
2372            },
2373            Component::Class(ref class)
2374                if self.in_selector_list_of.relevant_to_nth_of_dependencies() =>
2375            {
2376                self.nth_of_class_dependencies.insert(class.0.clone());
2377            },
2378            _ => {},
2379        }
2380
2381        true
2382    }
2383}
2384
2385/// A set of rules for element and pseudo-elements.
2386#[derive(Clone, Debug, Default, MallocSizeOf)]
2387struct GenericElementAndPseudoRules<Map> {
2388    /// Rules from stylesheets at this `CascadeData`'s origin.
2389    element_map: Map,
2390
2391    /// Rules from stylesheets at this `CascadeData`'s origin that correspond
2392    /// to a given pseudo-element.
2393    ///
2394    /// FIXME(emilio): There are a bunch of wasted entries here in practice.
2395    /// Figure out a good way to do a `PerNonAnonBox` and `PerAnonBox` (for
2396    /// `precomputed_values_for_pseudo`) without duplicating a lot of code.
2397    pseudos_map: PerPseudoElementMap<Self>,
2398}
2399
2400impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2401    #[inline(always)]
2402    fn for_insertion<'a>(&mut self, pseudo_elements: &[&'a PseudoElement]) -> &mut Map {
2403        let mut current = self;
2404        for &pseudo_element in pseudo_elements {
2405            debug_assert!(
2406                !pseudo_element.is_precomputed()
2407                    && !pseudo_element.is_unknown_webkit_pseudo_element(),
2408                "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2409                 and unknown webkit pseudos should be discarded before getting here"
2410            );
2411
2412            current = current
2413                .pseudos_map
2414                .get_or_insert_with(pseudo_element, Default::default);
2415        }
2416
2417        &mut current.element_map
2418    }
2419
2420    #[inline]
2421    fn rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&Map> {
2422        let mut current = self;
2423        for pseudo in pseudo_elements {
2424            current = current.pseudos_map.get(&pseudo)?;
2425        }
2426        Some(&current.element_map)
2427    }
2428
2429    /// Measures heap usage.
2430    #[cfg(feature = "gecko")]
2431    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2432        sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2433
2434        for elem in self.pseudos_map.iter() {
2435            sizes.mElementAndPseudosMaps += MallocSizeOf::size_of(elem, ops);
2436        }
2437    }
2438}
2439
2440type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2441type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2442type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2443
2444impl ElementAndPseudoRules {
2445    // TODO(emilio): Should we retain storage of these?
2446    fn clear(&mut self) {
2447        self.element_map.clear();
2448        self.pseudos_map.clear();
2449    }
2450
2451    fn shrink_if_needed(&mut self) {
2452        self.element_map.shrink_if_needed();
2453        for pseudo in self.pseudos_map.iter_mut() {
2454            pseudo.shrink_if_needed();
2455        }
2456    }
2457}
2458
2459impl PartElementAndPseudoRules {
2460    // TODO(emilio): Should we retain storage of these?
2461    fn clear(&mut self) {
2462        self.element_map.clear();
2463        self.pseudos_map.clear();
2464    }
2465}
2466
2467/// The id of a given layer, a sequentially-increasing identifier.
2468#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2469pub struct LayerId(u16);
2470
2471impl LayerId {
2472    /// The id of the root layer.
2473    pub const fn root() -> Self {
2474        Self(0)
2475    }
2476}
2477
2478#[derive(Clone, Debug, MallocSizeOf)]
2479struct CascadeLayer {
2480    id: LayerId,
2481    order: LayerOrder,
2482    children: Vec<LayerId>,
2483}
2484
2485impl CascadeLayer {
2486    const fn root() -> Self {
2487        Self {
2488            id: LayerId::root(),
2489            order: LayerOrder::root(),
2490            children: vec![],
2491        }
2492    }
2493}
2494
2495/// The id of a given container condition, a sequentially-increasing identifier
2496/// for a given style set.
2497#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2498pub struct ContainerConditionId(u16);
2499
2500impl ContainerConditionId {
2501    /// A special id that represents no container rule.
2502    pub const fn none() -> Self {
2503        Self(0)
2504    }
2505}
2506
2507#[derive(Clone, Debug, MallocSizeOf)]
2508struct ContainerConditionReference {
2509    parent: ContainerConditionId,
2510    #[ignore_malloc_size_of = "Arc"]
2511    condition: Option<Arc<ContainerCondition>>,
2512}
2513
2514impl ContainerConditionReference {
2515    const fn none() -> Self {
2516        Self {
2517            parent: ContainerConditionId::none(),
2518            condition: None,
2519        }
2520    }
2521}
2522
2523/// The id of a given scope condition, a sequentially-increasing identifier
2524/// for a given style set.
2525#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord)]
2526pub struct ScopeConditionId(u16);
2527
2528impl ScopeConditionId {
2529    /// Construct a new scope condition id.
2530    pub fn new(id: u16) -> Self {
2531        Self(id)
2532    }
2533
2534    /// A special id that represents no scope rule.
2535    pub const fn none() -> Self {
2536        Self(0)
2537    }
2538}
2539
2540/// Data required to process this scope condition.
2541#[derive(Clone, Debug, MallocSizeOf)]
2542pub struct ScopeConditionReference {
2543    /// The ID of outer scope condition, `none()` otherwise.
2544    parent: ScopeConditionId,
2545    /// Start and end bounds of the scope. None implies sentinel data (i.e. Not a scope condition).
2546    condition: Option<ScopeBoundsWithHashes>,
2547    /// Implicit scope root of this scope condition, computed unconditionally,
2548    /// even if the start bound may be Some.
2549    #[ignore_malloc_size_of = "Raw ptr behind the scenes"]
2550    implicit_scope_root: StylistImplicitScopeRoot,
2551    /// Is the condition trivial? See `ScopeBoundsWithHashes::is_trivial`.
2552    is_trivial: bool,
2553}
2554
2555impl ScopeConditionReference {
2556    /// Create a new scope condition.
2557    pub fn new(
2558        parent: ScopeConditionId,
2559        condition: Option<ScopeBoundsWithHashes>,
2560        implicit_scope_root: ImplicitScopeRoot,
2561        is_trivial: bool,
2562    ) -> Self {
2563        Self {
2564            parent,
2565            condition,
2566            implicit_scope_root: StylistImplicitScopeRoot::Normal(implicit_scope_root),
2567            is_trivial,
2568        }
2569    }
2570
2571    /// Create a sentinel scope condition.
2572    pub const fn none() -> Self {
2573        Self {
2574            parent: ScopeConditionId::none(),
2575            condition: None,
2576            implicit_scope_root: StylistImplicitScopeRoot::default_const(),
2577            is_trivial: true,
2578        }
2579    }
2580}
2581
2582/// All potential sscope root candidates.
2583pub struct ScopeRootCandidates {
2584    /// List of scope root candidates.
2585    pub candidates: Vec<ScopeRootCandidate>,
2586    /// Is the scope condition matching these candidates trivial? See `ScopeBoundsWithHashes::is_trivial`.
2587    pub is_trivial: bool,
2588}
2589
2590impl Default for ScopeRootCandidates {
2591    fn default() -> Self {
2592        Self {
2593            candidates: vec![],
2594            is_trivial: true,
2595        }
2596    }
2597}
2598
2599impl ScopeRootCandidates {
2600    fn empty(is_trivial: bool) -> Self {
2601        Self {
2602            candidates: vec![],
2603            is_trivial,
2604        }
2605    }
2606}
2607
2608/// Start and end bound of a scope, along with their selector hashes.
2609#[derive(Clone, Debug, MallocSizeOf)]
2610pub struct ScopeBoundWithHashes {
2611    // TODO(dshin): With replaced parent selectors, these may be unique...
2612    #[ignore_malloc_size_of = "Arc"]
2613    selectors: SelectorList<SelectorImpl>,
2614    hashes: SmallVec<[AncestorHashes; 1]>,
2615}
2616
2617impl ScopeBoundWithHashes {
2618    fn new(quirks_mode: QuirksMode, selectors: SelectorList<SelectorImpl>) -> Self {
2619        let mut hashes = SmallVec::with_capacity(selectors.len());
2620        for selector in selectors.slice() {
2621            hashes.push(AncestorHashes::new(selector, quirks_mode));
2622        }
2623        Self { selectors, hashes }
2624    }
2625
2626    fn new_no_hash(selectors: SelectorList<SelectorImpl>) -> Self {
2627        let hashes = selectors
2628            .slice()
2629            .iter()
2630            .map(|_| AncestorHashes {
2631                packed_hashes: [0, 0, 0],
2632            })
2633            .collect();
2634        Self { selectors, hashes }
2635    }
2636}
2637
2638/// Bounds for this scope, along with corresponding selector hashes.
2639#[derive(Clone, Debug, MallocSizeOf)]
2640pub struct ScopeBoundsWithHashes {
2641    /// Start of the scope bound. If None, implies implicit scope root.
2642    start: Option<ScopeBoundWithHashes>,
2643    /// Optional end of the scope bound.
2644    end: Option<ScopeBoundWithHashes>,
2645}
2646
2647impl ScopeBoundsWithHashes {
2648    /// Create a new scope bound, hashing selectors for fast rejection.
2649    fn new(
2650        quirks_mode: QuirksMode,
2651        start: Option<SelectorList<SelectorImpl>>,
2652        end: Option<SelectorList<SelectorImpl>>,
2653    ) -> Self {
2654        Self {
2655            start: start.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2656            end: end.map(|selectors| ScopeBoundWithHashes::new(quirks_mode, selectors)),
2657        }
2658    }
2659
2660    /// Create a new scope bound, but not hashing any selector.
2661    pub fn new_no_hash(
2662        start: Option<SelectorList<SelectorImpl>>,
2663        end: Option<SelectorList<SelectorImpl>>,
2664    ) -> Self {
2665        Self {
2666            start: start.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2667            end: end.map(|selectors| ScopeBoundWithHashes::new_no_hash(selectors)),
2668        }
2669    }
2670
2671    fn selectors_for<'a>(
2672        bound_with_hashes: Option<&'a ScopeBoundWithHashes>,
2673    ) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2674        bound_with_hashes
2675            .map(|b| b.selectors.slice().iter())
2676            .into_iter()
2677            .flatten()
2678    }
2679
2680    fn start_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2681        Self::selectors_for(self.start.as_ref())
2682    }
2683
2684    fn end_selectors<'a>(&'a self) -> impl Iterator<Item = &'a Selector<SelectorImpl>> {
2685        Self::selectors_for(self.end.as_ref())
2686    }
2687
2688    fn is_trivial(&self) -> bool {
2689        fn scope_bound_is_trivial(bound: &Option<ScopeBoundWithHashes>, default: bool) -> bool {
2690            bound.as_ref().map_or(default, |bound| {
2691                scope_selector_list_is_trivial(&bound.selectors)
2692            })
2693        }
2694
2695        // Given an implicit scope, we are unable to tell if the cousins share the same implicit root.
2696        scope_bound_is_trivial(&self.start, false) && scope_bound_is_trivial(&self.end, true)
2697    }
2698}
2699
2700/// Find all scope conditions for a given condition ID, indexing into the given list of scope conditions.
2701pub fn scope_root_candidates<E>(
2702    scope_conditions: &[ScopeConditionReference],
2703    id: ScopeConditionId,
2704    element: &E,
2705    override_matches_shadow_host_for_part: bool,
2706    scope_subject_map: &ScopeSubjectMap,
2707    context: &mut MatchingContext<SelectorImpl>,
2708) -> ScopeRootCandidates
2709where
2710    E: TElement,
2711{
2712    let condition_ref = &scope_conditions[id.0 as usize];
2713    let bounds = match condition_ref.condition {
2714        None => return ScopeRootCandidates::default(),
2715        Some(ref c) => c,
2716    };
2717    // Make sure the parent scopes ara evaluated first. This runs a bit counter to normal
2718    // selector matching where rightmost selectors match first. However, this avoids having
2719    // to traverse through descendants (i.e. Avoids tree traversal vs linear traversal).
2720    let outer_result = scope_root_candidates(
2721        scope_conditions,
2722        condition_ref.parent,
2723        element,
2724        override_matches_shadow_host_for_part,
2725        scope_subject_map,
2726        context,
2727    );
2728
2729    let is_trivial = condition_ref.is_trivial && outer_result.is_trivial;
2730    let is_outermost_scope = condition_ref.parent == ScopeConditionId::none();
2731    if !is_outermost_scope && outer_result.candidates.is_empty() {
2732        return ScopeRootCandidates::empty(is_trivial);
2733    }
2734
2735    let (root_target, matches_shadow_host) = if let Some(start) = bounds.start.as_ref() {
2736        if let Some(filter) = context.bloom_filter {
2737            // Use the bloom filter here. If our ancestors do not have the right hashes,
2738            // there's no point in traversing up. Besides, the filter is built for this depth,
2739            // so the filter contains more data than it should, the further we go up the ancestor
2740            // chain. It wouldn't generate wrong results, but makes the traversal even more pointless.
2741            if !start
2742                .hashes
2743                .iter()
2744                .any(|entry| selector_may_match(entry, filter))
2745            {
2746                return ScopeRootCandidates::empty(is_trivial);
2747            }
2748        }
2749        (
2750            ScopeTarget::Selector(&start.selectors),
2751            scope_start_matches_shadow_host(&start.selectors),
2752        )
2753    } else {
2754        let implicit_root = condition_ref.implicit_scope_root;
2755        match implicit_root {
2756            StylistImplicitScopeRoot::Normal(r) => (
2757                ScopeTarget::Implicit(r.element(context.current_host.clone())),
2758                r.matches_shadow_host(),
2759            ),
2760            StylistImplicitScopeRoot::Cached(index) => {
2761                let host = context
2762                    .current_host
2763                    .expect("Cached implicit scope for light DOM implicit scope");
2764                match E::implicit_scope_for_sheet_in_shadow_root(host, index) {
2765                    None => return ScopeRootCandidates::empty(is_trivial),
2766                    Some(root) => (
2767                        ScopeTarget::Implicit(root.element(context.current_host.clone())),
2768                        root.matches_shadow_host(),
2769                    ),
2770                }
2771            },
2772        }
2773    };
2774    // For `::part`, we need to be able to reach the outer tree. Parts without the corresponding
2775    // `exportparts` attribute will be rejected at the selector matching time.
2776    let matches_shadow_host = override_matches_shadow_host_for_part || matches_shadow_host;
2777
2778    let potential_scope_roots = if is_outermost_scope {
2779        collect_scope_roots(
2780            *element,
2781            None,
2782            context,
2783            &root_target,
2784            matches_shadow_host,
2785            scope_subject_map,
2786        )
2787    } else {
2788        let mut result = vec![];
2789        for activation in outer_result.candidates {
2790            let mut this_result = collect_scope_roots(
2791                *element,
2792                Some(activation.root),
2793                context,
2794                &root_target,
2795                matches_shadow_host,
2796                scope_subject_map,
2797            );
2798            result.append(&mut this_result);
2799        }
2800        result
2801    };
2802
2803    if potential_scope_roots.is_empty() {
2804        return ScopeRootCandidates::empty(is_trivial);
2805    }
2806
2807    let candidates = if let Some(end) = bounds.end.as_ref() {
2808        let mut result = vec![];
2809        // If any scope-end selector matches, we're not in scope.
2810        for scope_root in potential_scope_roots {
2811            if end
2812                .selectors
2813                .slice()
2814                .iter()
2815                .zip(end.hashes.iter())
2816                .all(|(selector, hashes)| {
2817                    // Like checking for scope-start, use the bloom filter here.
2818                    if let Some(filter) = context.bloom_filter {
2819                        if !selector_may_match(hashes, filter) {
2820                            // Selector this hash belongs to won't cause us to be out of this scope.
2821                            return true;
2822                        }
2823                    }
2824
2825                    !element_is_outside_of_scope(
2826                        selector,
2827                        *element,
2828                        scope_root.root,
2829                        context,
2830                        matches_shadow_host,
2831                    )
2832                })
2833            {
2834                result.push(scope_root);
2835            }
2836        }
2837        result
2838    } else {
2839        potential_scope_roots
2840    };
2841
2842    ScopeRootCandidates {
2843        candidates,
2844        is_trivial,
2845    }
2846}
2847
2848/// Implicit scope root, which may or may not be cached (i.e. For shadow DOM author
2849/// styles that are cached and shared).
2850#[derive(Copy, Clone, Debug, MallocSizeOf)]
2851enum StylistImplicitScopeRoot {
2852    Normal(ImplicitScopeRoot),
2853    Cached(usize),
2854}
2855// Should be safe, only mutated through mutable methods in `Stylist`.
2856unsafe impl Sync for StylistImplicitScopeRoot {}
2857
2858impl StylistImplicitScopeRoot {
2859    const fn default_const() -> Self {
2860        // Use the "safest" fallback.
2861        Self::Normal(ImplicitScopeRoot::DocumentElement)
2862    }
2863}
2864
2865impl Default for StylistImplicitScopeRoot {
2866    fn default() -> Self {
2867        Self::default_const()
2868    }
2869}
2870
2871/// Data resulting from performing the CSS cascade that is specific to a given
2872/// origin.
2873///
2874/// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
2875/// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
2876#[derive(Debug, Clone, MallocSizeOf)]
2877pub struct CascadeData {
2878    /// The data coming from normal style rules that apply to elements at this
2879    /// cascade level.
2880    normal_rules: ElementAndPseudoRules,
2881
2882    /// The `:host` pseudo rules that are the rightmost selector (without
2883    /// accounting for pseudo-elements), or `:scope` rules that may match
2884    /// the featureless host.
2885    featureless_host_rules: Option<Box<ElementAndPseudoRules>>,
2886
2887    /// The data coming from ::slotted() pseudo-element rules.
2888    ///
2889    /// We need to store them separately because an element needs to match
2890    /// ::slotted() pseudo-element rules in different shadow roots.
2891    ///
2892    /// In particular, we need to go through all the style data in all the
2893    /// containing style scopes starting from the closest assigned slot.
2894    slotted_rules: Option<Box<ElementAndPseudoRules>>,
2895
2896    /// The data coming from ::part() pseudo-element rules.
2897    ///
2898    /// We need to store them separately because an element needs to match
2899    /// ::part() pseudo-element rules in different shadow roots.
2900    part_rules: Option<Box<PartElementAndPseudoRules>>,
2901
2902    /// The invalidation map for these rules.
2903    invalidation_map: InvalidationMap,
2904
2905    /// The relative selector equivalent of the invalidation map.
2906    relative_selector_invalidation_map: InvalidationMap,
2907
2908    additional_relative_selector_invalidation_map: AdditionalRelativeSelectorInvalidationMap,
2909
2910    /// The attribute local names that appear in attribute selectors.  Used
2911    /// to avoid taking element snapshots when an irrelevant attribute changes.
2912    /// (We don't bother storing the namespace, since namespaced attributes are
2913    /// rare.)
2914    attribute_dependencies: PrecomputedHashSet<LocalName>,
2915
2916    /// The classes that appear in the selector list of
2917    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
2918    /// an element when an irrelevant class changes.
2919    nth_of_class_dependencies: PrecomputedHashSet<Atom>,
2920
2921    /// The attributes that appear in the selector list of
2922    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
2923    /// an element when an irrelevant attribute changes.
2924    nth_of_attribute_dependencies: PrecomputedHashSet<LocalName>,
2925
2926    /// The custom states that appear in the selector list of
2927    /// :nth-child(... of <selector list>). Used to avoid restyling siblings of
2928    /// an element when an irrelevant custom state changes.
2929    nth_of_custom_state_dependencies: PrecomputedHashSet<AtomIdent>,
2930
2931    /// The element state bits that are relied on by selectors.  Like
2932    /// `attribute_dependencies`, this is used to avoid taking element snapshots
2933    /// when an irrelevant element state bit changes.
2934    state_dependencies: ElementState,
2935
2936    /// The element state bits that are relied on by selectors that appear in
2937    /// the selector list of :nth-child(... of <selector list>).
2938    nth_of_state_dependencies: ElementState,
2939
2940    /// The document state bits that are relied on by selectors.  This is used
2941    /// to tell whether we need to restyle the entire document when a document
2942    /// state bit changes.
2943    document_state_dependencies: DocumentState,
2944
2945    /// The ids that appear in the rightmost complex selector of selectors (and
2946    /// hence in our selector maps).  Used to determine when sharing styles is
2947    /// safe: we disallow style sharing for elements whose id matches this
2948    /// filter, and hence might be in one of our selector maps.
2949    mapped_ids: PrecomputedHashSet<Atom>,
2950
2951    /// The IDs that appear in the selector list of
2952    /// :nth-child(... of <selector list>). Used to avoid restyling siblings
2953    /// of an element when an irrelevant ID changes.
2954    nth_of_mapped_ids: PrecomputedHashSet<Atom>,
2955
2956    /// Selectors that require explicit cache revalidation (i.e. which depend
2957    /// on state that is not otherwise visible to the cache, like attributes or
2958    /// tree-structural state like child index and pseudos).
2959    #[ignore_malloc_size_of = "Arc"]
2960    selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
2961
2962    /// A map with all the animations at this `CascadeData`'s origin, indexed
2963    /// by name.
2964    animations: LayerOrderedMap<KeyframesAnimation>,
2965
2966    /// A map with all the layer-ordered registrations from style at this `CascadeData`'s origin,
2967    /// indexed by name.
2968    #[ignore_malloc_size_of = "Arc"]
2969    custom_property_registrations: LayerOrderedMap<Arc<PropertyRegistration>>,
2970
2971    /// A map from cascade layer name to layer order.
2972    layer_id: FxHashMap<LayerName, LayerId>,
2973
2974    /// The list of cascade layers, indexed by their layer id.
2975    layers: SmallVec<[CascadeLayer; 1]>,
2976
2977    /// The list of container conditions, indexed by their id.
2978    container_conditions: SmallVec<[ContainerConditionReference; 1]>,
2979
2980    /// The list of scope conditions, indexed by their id.
2981    scope_conditions: SmallVec<[ScopeConditionReference; 1]>,
2982
2983    /// Map of unique selectors on scope start selectors' subjects.
2984    scope_subject_map: ScopeSubjectMap,
2985
2986    /// Effective media query results cached from the last rebuild.
2987    effective_media_query_results: EffectiveMediaQueryResults,
2988
2989    /// Extra data, like different kinds of rules, etc.
2990    extra_data: ExtraStyleData,
2991
2992    /// A monotonically increasing counter to represent the order on which a
2993    /// style rule appears in a stylesheet, needed to sort them by source order.
2994    rules_source_order: u32,
2995
2996    /// The total number of selectors.
2997    num_selectors: usize,
2998
2999    /// The total number of declarations.
3000    num_declarations: usize,
3001}
3002
3003lazy_static! {
3004    static ref IMPLICIT_SCOPE: SelectorList<SelectorImpl> = {
3005        // Implicit scope, as per https://github.com/w3c/csswg-drafts/issues/10196
3006        // Also, `&` is `:where(:scope)`, as per https://github.com/w3c/csswg-drafts/issues/9740
3007        // ``:where(:scope)` effectively behaves the same as the implicit scope.
3008        let list = SelectorList::implicit_scope();
3009        list.mark_as_intentionally_leaked();
3010        list
3011    };
3012}
3013
3014fn scope_start_matches_shadow_host(start: &SelectorList<SelectorImpl>) -> bool {
3015    // TODO(emilio): Should we carry a MatchesFeaturelessHost rather than a bool around?
3016    // Pre-existing behavior with multiple selectors matches this tho.
3017    start
3018        .slice()
3019        .iter()
3020        .any(|s| s.matches_featureless_host(true).may_match())
3021}
3022
3023/// Replace any occurrence of parent selector in the given selector with a implicit scope selector.
3024pub fn replace_parent_selector_with_implicit_scope(
3025    selectors: &SelectorList<SelectorImpl>,
3026) -> SelectorList<SelectorImpl> {
3027    selectors.replace_parent_selector(&IMPLICIT_SCOPE)
3028}
3029
3030impl CascadeData {
3031    /// Creates an empty `CascadeData`.
3032    pub fn new() -> Self {
3033        Self {
3034            normal_rules: ElementAndPseudoRules::default(),
3035            featureless_host_rules: None,
3036            slotted_rules: None,
3037            part_rules: None,
3038            invalidation_map: InvalidationMap::new(),
3039            relative_selector_invalidation_map: InvalidationMap::new(),
3040            additional_relative_selector_invalidation_map:
3041                AdditionalRelativeSelectorInvalidationMap::new(),
3042            nth_of_mapped_ids: PrecomputedHashSet::default(),
3043            nth_of_class_dependencies: PrecomputedHashSet::default(),
3044            nth_of_attribute_dependencies: PrecomputedHashSet::default(),
3045            nth_of_custom_state_dependencies: PrecomputedHashSet::default(),
3046            nth_of_state_dependencies: ElementState::empty(),
3047            attribute_dependencies: PrecomputedHashSet::default(),
3048            state_dependencies: ElementState::empty(),
3049            document_state_dependencies: DocumentState::empty(),
3050            mapped_ids: PrecomputedHashSet::default(),
3051            selectors_for_cache_revalidation: SelectorMap::new(),
3052            animations: Default::default(),
3053            custom_property_registrations: Default::default(),
3054            layer_id: Default::default(),
3055            layers: smallvec::smallvec![CascadeLayer::root()],
3056            container_conditions: smallvec::smallvec![ContainerConditionReference::none()],
3057            scope_conditions: smallvec::smallvec![ScopeConditionReference::none()],
3058            scope_subject_map: Default::default(),
3059            extra_data: ExtraStyleData::default(),
3060            effective_media_query_results: EffectiveMediaQueryResults::new(),
3061            rules_source_order: 0,
3062            num_selectors: 0,
3063            num_declarations: 0,
3064        }
3065    }
3066
3067    /// Rebuild the cascade data from a given SheetCollection, incrementally if
3068    /// possible.
3069    pub fn rebuild<'a, S>(
3070        &mut self,
3071        device: &Device,
3072        quirks_mode: QuirksMode,
3073        collection: SheetCollectionFlusher<S>,
3074        guard: &SharedRwLockReadGuard,
3075    ) -> Result<(), AllocErr>
3076    where
3077        S: StylesheetInDocument + PartialEq + 'static,
3078    {
3079        if !collection.dirty() {
3080            return Ok(());
3081        }
3082
3083        let validity = collection.data_validity();
3084
3085        match validity {
3086            DataValidity::Valid => {},
3087            DataValidity::CascadeInvalid => self.clear_cascade_data(),
3088            DataValidity::FullyInvalid => self.clear(),
3089        }
3090
3091        let mut result = Ok(());
3092
3093        collection.each(|index, stylesheet, rebuild_kind| {
3094            result = self.add_stylesheet(
3095                device,
3096                quirks_mode,
3097                stylesheet,
3098                index,
3099                guard,
3100                rebuild_kind,
3101                /* precomputed_pseudo_element_decls = */ None,
3102            );
3103            result.is_ok()
3104        });
3105
3106        self.did_finish_rebuild();
3107
3108        result
3109    }
3110
3111    /// Returns the invalidation map.
3112    pub fn invalidation_map(&self) -> &InvalidationMap {
3113        &self.invalidation_map
3114    }
3115
3116    /// Returns the relative selector invalidation map.
3117    pub fn relative_selector_invalidation_map(&self) -> &InvalidationMap {
3118        &self.relative_selector_invalidation_map
3119    }
3120
3121    /// Returns the relative selector invalidation map data.
3122    pub fn relative_invalidation_map_attributes(
3123        &self,
3124    ) -> &AdditionalRelativeSelectorInvalidationMap {
3125        &self.additional_relative_selector_invalidation_map
3126    }
3127
3128    /// Returns whether the given ElementState bit is relied upon by a selector
3129    /// of some rule.
3130    #[inline]
3131    pub fn has_state_dependency(&self, state: ElementState) -> bool {
3132        self.state_dependencies.intersects(state)
3133    }
3134
3135    /// Returns whether the given Custom State is relied upon by a selector
3136    /// of some rule in the selector list of :nth-child(... of <selector list>).
3137    #[inline]
3138    pub fn has_nth_of_custom_state_dependency(&self, state: &AtomIdent) -> bool {
3139        self.nth_of_custom_state_dependencies.contains(state)
3140    }
3141
3142    /// Returns whether the given ElementState bit is relied upon by a selector
3143    /// of some rule in the selector list of :nth-child(... of <selector list>).
3144    #[inline]
3145    pub fn has_nth_of_state_dependency(&self, state: ElementState) -> bool {
3146        self.nth_of_state_dependencies.intersects(state)
3147    }
3148
3149    /// Returns whether the given attribute might appear in an attribute
3150    /// selector of some rule.
3151    #[inline]
3152    pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
3153        self.attribute_dependencies.contains(local_name)
3154    }
3155
3156    /// Returns whether the given ID might appear in an ID selector in the
3157    /// selector list of :nth-child(... of <selector list>).
3158    #[inline]
3159    pub fn might_have_nth_of_id_dependency(&self, id: &Atom) -> bool {
3160        self.nth_of_mapped_ids.contains(id)
3161    }
3162
3163    /// Returns whether the given class might appear in a class selector in the
3164    /// selector list of :nth-child(... of <selector list>).
3165    #[inline]
3166    pub fn might_have_nth_of_class_dependency(&self, class: &Atom) -> bool {
3167        self.nth_of_class_dependencies.contains(class)
3168    }
3169
3170    /// Returns whether the given attribute might appear in an attribute
3171    /// selector in the selector list of :nth-child(... of <selector list>).
3172    #[inline]
3173    pub fn might_have_nth_of_attribute_dependency(&self, local_name: &LocalName) -> bool {
3174        self.nth_of_attribute_dependencies.contains(local_name)
3175    }
3176
3177    /// Returns the normal rule map for a given pseudo-element.
3178    #[inline]
3179    pub fn normal_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3180        self.normal_rules.rules(pseudo_elements)
3181    }
3182
3183    /// Returns the featureless pseudo rule map for a given pseudo-element.
3184    #[inline]
3185    pub fn featureless_host_rules(
3186        &self,
3187        pseudo_elements: &[PseudoElement],
3188    ) -> Option<&SelectorMap<Rule>> {
3189        self.featureless_host_rules
3190            .as_ref()
3191            .and_then(|d| d.rules(pseudo_elements))
3192    }
3193
3194    /// Whether there's any featureless rule that could match in this scope.
3195    pub fn any_featureless_host_rules(&self) -> bool {
3196        self.featureless_host_rules.is_some()
3197    }
3198
3199    /// Returns the slotted rule map for a given pseudo-element.
3200    #[inline]
3201    pub fn slotted_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&SelectorMap<Rule>> {
3202        self.slotted_rules
3203            .as_ref()
3204            .and_then(|d| d.rules(pseudo_elements))
3205    }
3206
3207    /// Whether there's any ::slotted rule that could match in this scope.
3208    pub fn any_slotted_rule(&self) -> bool {
3209        self.slotted_rules.is_some()
3210    }
3211
3212    /// Returns the parts rule map for a given pseudo-element.
3213    #[inline]
3214    pub fn part_rules(&self, pseudo_elements: &[PseudoElement]) -> Option<&PartMap> {
3215        self.part_rules
3216            .as_ref()
3217            .and_then(|d| d.rules(pseudo_elements))
3218    }
3219
3220    /// Whether there's any ::part rule that could match in this scope.
3221    pub fn any_part_rule(&self) -> bool {
3222        self.part_rules.is_some()
3223    }
3224
3225    #[inline]
3226    fn layer_order_for(&self, id: LayerId) -> LayerOrder {
3227        self.layers[id.0 as usize].order
3228    }
3229
3230    pub(crate) fn container_condition_matches<E>(
3231        &self,
3232        mut id: ContainerConditionId,
3233        stylist: &Stylist,
3234        element: E,
3235        context: &mut MatchingContext<E::Impl>,
3236    ) -> bool
3237    where
3238        E: TElement,
3239    {
3240        loop {
3241            let condition_ref = &self.container_conditions[id.0 as usize];
3242            let condition = match condition_ref.condition {
3243                None => return true,
3244                Some(ref c) => c,
3245            };
3246            let matches = condition
3247                .matches(
3248                    stylist,
3249                    element,
3250                    context.extra_data.originating_element_style,
3251                    &mut context.extra_data.cascade_input_flags,
3252                )
3253                .to_bool(/* unknown = */ false);
3254            if !matches {
3255                return false;
3256            }
3257            id = condition_ref.parent;
3258        }
3259    }
3260
3261    pub(crate) fn find_scope_proximity_if_matching<E: TElement>(
3262        &self,
3263        rule: &Rule,
3264        element: E,
3265        context: &mut MatchingContext<E::Impl>,
3266    ) -> ScopeProximity {
3267        context
3268            .extra_data
3269            .cascade_input_flags
3270            .insert(ComputedValueFlags::CONSIDERED_NONTRIVIAL_SCOPED_STYLE);
3271
3272        // Whether the scope root matches a shadow host mostly olny depends on scope-intrinsic
3273        // parameters (i.e. bounds/implicit scope) - except for the use of `::parts`, where
3274        // matching crosses the shadow boundary.
3275        let result = scope_root_candidates(
3276            &self.scope_conditions,
3277            rule.scope_condition_id,
3278            &element,
3279            rule.selector.is_part(),
3280            &self.scope_subject_map,
3281            context,
3282        );
3283        for candidate in result.candidates {
3284            if context.nest_for_scope(Some(candidate.root), |context| {
3285                matches_selector(&rule.selector, 0, Some(&rule.hashes), &element, context)
3286            }) {
3287                return candidate.proximity;
3288            }
3289        }
3290        ScopeProximity::infinity()
3291    }
3292
3293    fn did_finish_rebuild(&mut self) {
3294        self.shrink_maps_if_needed();
3295        self.compute_layer_order();
3296    }
3297
3298    fn shrink_maps_if_needed(&mut self) {
3299        self.normal_rules.shrink_if_needed();
3300        if let Some(ref mut host_rules) = self.featureless_host_rules {
3301            host_rules.shrink_if_needed();
3302        }
3303        if let Some(ref mut slotted_rules) = self.slotted_rules {
3304            slotted_rules.shrink_if_needed();
3305        }
3306        self.animations.shrink_if_needed();
3307        self.custom_property_registrations.shrink_if_needed();
3308        self.invalidation_map.shrink_if_needed();
3309        self.relative_selector_invalidation_map.shrink_if_needed();
3310        self.additional_relative_selector_invalidation_map
3311            .shrink_if_needed();
3312        self.attribute_dependencies.shrink_if_needed();
3313        self.nth_of_attribute_dependencies.shrink_if_needed();
3314        self.nth_of_custom_state_dependencies.shrink_if_needed();
3315        self.nth_of_class_dependencies.shrink_if_needed();
3316        self.nth_of_mapped_ids.shrink_if_needed();
3317        self.mapped_ids.shrink_if_needed();
3318        self.layer_id.shrink_if_needed();
3319        self.selectors_for_cache_revalidation.shrink_if_needed();
3320        self.scope_subject_map.shrink_if_needed();
3321    }
3322
3323    fn compute_layer_order(&mut self) {
3324        debug_assert_ne!(
3325            self.layers.len(),
3326            0,
3327            "There should be at least the root layer!"
3328        );
3329        if self.layers.len() == 1 {
3330            return; // Nothing to do
3331        }
3332        let (first, remaining) = self.layers.split_at_mut(1);
3333        let root = &mut first[0];
3334        let mut order = LayerOrder::first();
3335        compute_layer_order_for_subtree(root, remaining, &mut order);
3336
3337        // NOTE(emilio): This is a bit trickier than it should to avoid having
3338        // to clone() around layer indices.
3339        fn compute_layer_order_for_subtree(
3340            parent: &mut CascadeLayer,
3341            remaining_layers: &mut [CascadeLayer],
3342            order: &mut LayerOrder,
3343        ) {
3344            for child in parent.children.iter() {
3345                debug_assert!(
3346                    parent.id < *child,
3347                    "Children are always registered after parents"
3348                );
3349                let child_index = (child.0 - parent.id.0 - 1) as usize;
3350                let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
3351                let child = &mut first[child_index];
3352                compute_layer_order_for_subtree(child, remaining, order);
3353            }
3354
3355            if parent.id != LayerId::root() {
3356                parent.order = *order;
3357                order.inc();
3358            }
3359        }
3360        #[cfg(feature = "gecko")]
3361        self.extra_data.sort_by_layer(&self.layers);
3362        self.animations
3363            .sort_with(&self.layers, compare_keyframes_in_same_layer);
3364        self.custom_property_registrations.sort(&self.layers)
3365    }
3366
3367    /// Collects all the applicable media query results into `results`.
3368    ///
3369    /// This duplicates part of the logic in `add_stylesheet`, which is
3370    /// a bit unfortunate.
3371    ///
3372    /// FIXME(emilio): With a bit of smartness in
3373    /// `media_feature_affected_matches`, we could convert
3374    /// `EffectiveMediaQueryResults` into a vector without too much effort.
3375    fn collect_applicable_media_query_results_into<S>(
3376        device: &Device,
3377        stylesheet: &S,
3378        guard: &SharedRwLockReadGuard,
3379        results: &mut Vec<MediaListKey>,
3380        contents_list: &mut StyleSheetContentList,
3381    ) where
3382        S: StylesheetInDocument + 'static,
3383    {
3384        if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
3385            return;
3386        }
3387
3388        debug!(" + {:?}", stylesheet);
3389        let contents = stylesheet.contents();
3390        results.push(contents.to_media_list_key());
3391
3392        // Safety: StyleSheetContents are reference-counted with Arc.
3393        contents_list.push(StylesheetContentsPtr(unsafe {
3394            Arc::from_raw_addrefed(contents)
3395        }));
3396
3397        for rule in stylesheet.effective_rules(device, guard) {
3398            match *rule {
3399                CssRule::Import(ref lock) => {
3400                    let import_rule = lock.read_with(guard);
3401                    debug!(" + {:?}", import_rule.stylesheet.media(guard));
3402                    results.push(import_rule.to_media_list_key());
3403                },
3404                CssRule::Media(ref media_rule) => {
3405                    debug!(" + {:?}", media_rule.media_queries.read_with(guard));
3406                    results.push(media_rule.to_media_list_key());
3407                },
3408                _ => {},
3409            }
3410        }
3411    }
3412
3413    fn note_scope_selector_for_invalidation(
3414        &mut self,
3415        quirks_mode: QuirksMode,
3416        inner_scope_dependencies: &Option<Arc<servo_arc::HeaderSlice<(), Dependency>>>,
3417        dependency_vector: &mut Vec<Dependency>,
3418        s: &Selector<SelectorImpl>,
3419        scope_kind: ScopeDependencyInvalidationKind,
3420    ) -> Result<(), AllocErr> {
3421        let mut new_inner_dependencies = note_selector_for_invalidation(
3422            &s.clone(),
3423            quirks_mode,
3424            &mut self.invalidation_map,
3425            &mut self.relative_selector_invalidation_map,
3426            &mut self.additional_relative_selector_invalidation_map,
3427            inner_scope_dependencies.as_ref(),
3428            Some(scope_kind),
3429        )?;
3430        let mut _unused = false;
3431        let mut visitor = StylistSelectorVisitor {
3432            needs_revalidation: &mut _unused,
3433            passed_rightmost_selector: true,
3434            in_selector_list_of: SelectorListKind::default(),
3435            mapped_ids: &mut self.mapped_ids,
3436            nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3437            attribute_dependencies: &mut self.attribute_dependencies,
3438            nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3439            nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3440            nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3441            state_dependencies: &mut self.state_dependencies,
3442            nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3443            document_state_dependencies: &mut self.document_state_dependencies,
3444        };
3445        s.visit(&mut visitor);
3446        new_inner_dependencies.as_mut().map(|dep| {
3447            dependency_vector.append(dep);
3448        });
3449        Ok(())
3450    }
3451
3452    fn add_styles(
3453        &mut self,
3454        selectors: &SelectorList<SelectorImpl>,
3455        declarations: &Arc<Locked<PropertyDeclarationBlock>>,
3456        ancestor_selectors: Option<&SelectorList<SelectorImpl>>,
3457        containing_rule_state: &ContainingRuleState,
3458        mut replaced_selectors: Option<&mut ReplacedSelectors>,
3459        guard: &SharedRwLockReadGuard,
3460        rebuild_kind: SheetRebuildKind,
3461        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3462        quirks_mode: QuirksMode,
3463    ) -> Result<(), AllocErr> {
3464        self.num_declarations += declarations.read_with(guard).len();
3465        for selector in selectors.slice() {
3466            self.num_selectors += 1;
3467
3468            let pseudo_elements = selector.pseudo_elements();
3469            let inner_pseudo_element = pseudo_elements.get(0);
3470            if let Some(pseudo) = inner_pseudo_element {
3471                if pseudo.is_precomputed() {
3472                    debug_assert!(selector.is_universal());
3473                    debug_assert!(ancestor_selectors.is_none());
3474                    debug_assert_eq!(containing_rule_state.layer_id, LayerId::root());
3475                    // Because we precompute pseudos, we cannot possibly calculate scope proximity.
3476                    debug_assert_eq!(
3477                        containing_rule_state.scope_condition_id,
3478                        ScopeConditionId::none()
3479                    );
3480                    precomputed_pseudo_element_decls
3481                        .as_mut()
3482                        .expect("Expected precomputed declarations for the UA level")
3483                        .get_or_insert_with(pseudo, Vec::new)
3484                        .push(ApplicableDeclarationBlock::new(
3485                            StyleSource::from_declarations(declarations.clone()),
3486                            self.rules_source_order,
3487                            CascadeLevel::UANormal,
3488                            selector.specificity(),
3489                            LayerOrder::root(),
3490                            ScopeProximity::infinity(),
3491                        ));
3492                    continue;
3493                }
3494                if pseudo_elements
3495                    .iter()
3496                    .any(|p| p.is_unknown_webkit_pseudo_element())
3497                {
3498                    continue;
3499                }
3500            }
3501
3502            debug_assert!(!pseudo_elements
3503                .iter()
3504                .any(|p| p.is_precomputed() || p.is_unknown_webkit_pseudo_element()));
3505
3506            let selector = match ancestor_selectors {
3507                Some(ref s) => selector.replace_parent_selector(&s),
3508                None => selector.clone(),
3509            };
3510
3511            let hashes = AncestorHashes::new(&selector, quirks_mode);
3512
3513            let rule = Rule::new(
3514                selector,
3515                hashes,
3516                StyleSource::from_declarations(declarations.clone()),
3517                self.rules_source_order,
3518                containing_rule_state.layer_id,
3519                containing_rule_state.container_condition_id,
3520                containing_rule_state.in_starting_style,
3521                containing_rule_state.scope_condition_id,
3522            );
3523
3524            if let Some(ref mut replaced_selectors) = replaced_selectors {
3525                replaced_selectors.push(rule.selector.clone())
3526            }
3527
3528            if rebuild_kind.should_rebuild_invalidation() {
3529                let innermost_dependency = note_selector_for_invalidation(
3530                    &rule.selector,
3531                    quirks_mode,
3532                    &mut self.invalidation_map,
3533                    &mut self.relative_selector_invalidation_map,
3534                    &mut self.additional_relative_selector_invalidation_map,
3535                    None,
3536                    None,
3537                )?;
3538                let mut needs_revalidation = false;
3539                let mut visitor = StylistSelectorVisitor {
3540                    needs_revalidation: &mut needs_revalidation,
3541                    passed_rightmost_selector: false,
3542                    in_selector_list_of: SelectorListKind::default(),
3543                    mapped_ids: &mut self.mapped_ids,
3544                    nth_of_mapped_ids: &mut self.nth_of_mapped_ids,
3545                    attribute_dependencies: &mut self.attribute_dependencies,
3546                    nth_of_class_dependencies: &mut self.nth_of_class_dependencies,
3547                    nth_of_attribute_dependencies: &mut self.nth_of_attribute_dependencies,
3548                    nth_of_custom_state_dependencies: &mut self.nth_of_custom_state_dependencies,
3549                    state_dependencies: &mut self.state_dependencies,
3550                    nth_of_state_dependencies: &mut self.nth_of_state_dependencies,
3551                    document_state_dependencies: &mut self.document_state_dependencies,
3552                };
3553                rule.selector.visit(&mut visitor);
3554
3555                if needs_revalidation {
3556                    self.selectors_for_cache_revalidation.insert(
3557                        RevalidationSelectorAndHashes::new(
3558                            rule.selector.clone(),
3559                            rule.hashes.clone(),
3560                        ),
3561                        quirks_mode,
3562                    )?;
3563                }
3564
3565                let mut scope_idx = containing_rule_state.scope_condition_id;
3566                let mut inner_scope_dependencies: Option<ThinArc<(), Dependency>> =
3567                    innermost_dependency
3568                        .map(|dep_vec| ThinArc::from_header_and_iter((), dep_vec.into_iter()));
3569
3570                while scope_idx != ScopeConditionId::none() {
3571                    let cur_scope = self.scope_conditions[scope_idx.0 as usize].clone();
3572
3573                    if let Some(cond) = cur_scope.condition.as_ref() {
3574                        let mut dependency_vector: Vec<Dependency> = Vec::new();
3575
3576                        if cond.start.is_none() {
3577                            dependency_vector.push(Dependency::new(
3578                                IMPLICIT_SCOPE.slice()[0].clone(),
3579                                0,
3580                                inner_scope_dependencies.clone(),
3581                                DependencyInvalidationKind::Scope(
3582                                    ScopeDependencyInvalidationKind::ImplicitScope,
3583                                ),
3584                            ));
3585                        }
3586
3587                        for s in cond.start_selectors() {
3588                            self.note_scope_selector_for_invalidation(
3589                                quirks_mode,
3590                                &inner_scope_dependencies,
3591                                &mut dependency_vector,
3592                                s,
3593                                ScopeDependencyInvalidationKind::ExplicitScope,
3594                            )?;
3595                        }
3596
3597                        // End-Scope selectors require special handling
3598                        for s in cond.end_selectors() {
3599                            self.note_scope_selector_for_invalidation(
3600                                quirks_mode,
3601                                &inner_scope_dependencies,
3602                                &mut dependency_vector,
3603                                s,
3604                                ScopeDependencyInvalidationKind::ScopeEnd,
3605                            )?;
3606                        }
3607
3608                        inner_scope_dependencies = Some(ThinArc::from_header_and_iter(
3609                            (),
3610                            dependency_vector.into_iter(),
3611                        ));
3612                    }
3613                    scope_idx = cur_scope.parent;
3614                }
3615            }
3616
3617            // Part is special, since given it doesn't have any
3618            // selectors inside, it's not worth using a whole
3619            // SelectorMap for it.
3620            if let Some(parts) = rule.selector.parts() {
3621                // ::part() has all semantics, so we just need to
3622                // put any of them in the selector map.
3623                //
3624                // We choose the last one quite arbitrarily,
3625                // expecting it's slightly more likely to be more
3626                // specific.
3627                let map = self
3628                    .part_rules
3629                    .get_or_insert_with(|| Box::new(Default::default()))
3630                    .for_insertion(&pseudo_elements);
3631                map.try_reserve(1)?;
3632                let vec = map.entry(parts.last().unwrap().clone().0).or_default();
3633                vec.try_reserve(1)?;
3634                vec.push(rule);
3635            } else {
3636                let scope_matches_shadow_host =
3637                    containing_rule_state.scope_matches_shadow_host == ScopeMatchesShadowHost::Yes;
3638                let matches_featureless_host_only = match rule
3639                    .selector
3640                    .matches_featureless_host(scope_matches_shadow_host)
3641                {
3642                    MatchesFeaturelessHost::Only => true,
3643                    MatchesFeaturelessHost::Yes => {
3644                        // We need to insert this in featureless_host_rules but also normal_rules.
3645                        self.featureless_host_rules
3646                            .get_or_insert_with(|| Box::new(Default::default()))
3647                            .for_insertion(&pseudo_elements)
3648                            .insert(rule.clone(), quirks_mode)?;
3649                        false
3650                    },
3651                    MatchesFeaturelessHost::Never => false,
3652                };
3653
3654                // NOTE(emilio): It's fine to look at :host and then at
3655                // ::slotted(..), since :host::slotted(..) could never
3656                // possibly match, as <slot> is not a valid shadow host.
3657                // :scope may match featureless shadow host if the scope
3658                // root is the shadow root.
3659                // See https://github.com/w3c/csswg-drafts/issues/9025
3660                let rules = if matches_featureless_host_only {
3661                    self.featureless_host_rules
3662                        .get_or_insert_with(|| Box::new(Default::default()))
3663                } else if rule.selector.is_slotted() {
3664                    self.slotted_rules
3665                        .get_or_insert_with(|| Box::new(Default::default()))
3666                } else {
3667                    &mut self.normal_rules
3668                }
3669                .for_insertion(&pseudo_elements);
3670                rules.insert(rule, quirks_mode)?;
3671            }
3672        }
3673        self.rules_source_order += 1;
3674        Ok(())
3675    }
3676
3677    fn add_rule_list<S>(
3678        &mut self,
3679        rules: std::slice::Iter<CssRule>,
3680        device: &Device,
3681        quirks_mode: QuirksMode,
3682        stylesheet: &S,
3683        sheet_index: usize,
3684        guard: &SharedRwLockReadGuard,
3685        rebuild_kind: SheetRebuildKind,
3686        containing_rule_state: &mut ContainingRuleState,
3687        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
3688    ) -> Result<(), AllocErr>
3689    where
3690        S: StylesheetInDocument + 'static,
3691    {
3692        for rule in rules {
3693            // Handle leaf rules first, as those are by far the most common
3694            // ones, and are always effective, so we can skip some checks.
3695            let mut handled = true;
3696            let mut list_for_nested_rules = None;
3697            match *rule {
3698                CssRule::Style(ref locked) => {
3699                    let style_rule = locked.read_with(guard);
3700                    let has_nested_rules = style_rule.rules.is_some();
3701                    let mut replaced_selectors = ReplacedSelectors::new();
3702                    let ancestor_selectors = containing_rule_state.ancestor_selector_lists.last();
3703                    let collect_replaced_selectors =
3704                        has_nested_rules && ancestor_selectors.is_some();
3705                    self.add_styles(
3706                        &style_rule.selectors,
3707                        &style_rule.block,
3708                        ancestor_selectors,
3709                        &containing_rule_state,
3710                        if collect_replaced_selectors {
3711                            Some(&mut replaced_selectors)
3712                        } else {
3713                            None
3714                        },
3715                        guard,
3716                        rebuild_kind,
3717                        precomputed_pseudo_element_decls.as_deref_mut(),
3718                        quirks_mode,
3719                    )?;
3720                    if has_nested_rules {
3721                        handled = false;
3722                        list_for_nested_rules = Some(if collect_replaced_selectors {
3723                            SelectorList::from_iter(replaced_selectors.drain(..))
3724                        } else {
3725                            style_rule.selectors.clone()
3726                        });
3727                    }
3728                },
3729                CssRule::NestedDeclarations(ref rule) => {
3730                    if let Some(ref ancestor_selectors) =
3731                        containing_rule_state.ancestor_selector_lists.last()
3732                    {
3733                        let decls = &rule.read_with(guard).block;
3734                        let selectors = match containing_rule_state.nested_declarations_context {
3735                            NestedDeclarationsContext::Style => ancestor_selectors,
3736                            NestedDeclarationsContext::Scope => &*IMPLICIT_SCOPE,
3737                        };
3738                        self.add_styles(
3739                            selectors,
3740                            decls,
3741                            /* ancestor_selectors = */ None,
3742                            &containing_rule_state,
3743                            /* replaced_selectors = */ None,
3744                            guard,
3745                            // We don't need to rebuild invalidation data, since our ancestor style
3746                            // rule would've done this.
3747                            SheetRebuildKind::CascadeOnly,
3748                            precomputed_pseudo_element_decls.as_deref_mut(),
3749                            quirks_mode,
3750                        )?;
3751                    }
3752                },
3753                CssRule::Keyframes(ref keyframes_rule) => {
3754                    debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
3755                    let keyframes_rule = keyframes_rule.read_with(guard);
3756                    let name = keyframes_rule.name.as_atom().clone();
3757                    let animation = KeyframesAnimation::from_keyframes(
3758                        &keyframes_rule.keyframes,
3759                        keyframes_rule.vendor_prefix.clone(),
3760                        guard,
3761                    );
3762                    self.animations.try_insert_with(
3763                        name,
3764                        animation,
3765                        containing_rule_state.layer_id,
3766                        compare_keyframes_in_same_layer,
3767                    )?;
3768                },
3769                CssRule::Property(ref registration) => {
3770                    self.custom_property_registrations.try_insert(
3771                        registration.name.0.clone(),
3772                        Arc::clone(registration),
3773                        containing_rule_state.layer_id,
3774                    )?;
3775                },
3776                #[cfg(feature = "gecko")]
3777                CssRule::FontFace(ref rule) => {
3778                    // NOTE(emilio): We don't care about container_condition_id
3779                    // because:
3780                    //
3781                    //     Global, name-defining at-rules such as @keyframes or
3782                    //     @font-face or @layer that are defined inside container
3783                    //     queries are not constrained by the container query
3784                    //     conditions.
3785                    //
3786                    // https://drafts.csswg.org/css-contain-3/#container-rule
3787                    // (Same elsewhere)
3788                    self.extra_data
3789                        .add_font_face(rule, containing_rule_state.layer_id);
3790                },
3791                #[cfg(feature = "gecko")]
3792                CssRule::FontFeatureValues(ref rule) => {
3793                    self.extra_data
3794                        .add_font_feature_values(rule, containing_rule_state.layer_id);
3795                },
3796                #[cfg(feature = "gecko")]
3797                CssRule::FontPaletteValues(ref rule) => {
3798                    self.extra_data
3799                        .add_font_palette_values(rule, containing_rule_state.layer_id);
3800                },
3801                #[cfg(feature = "gecko")]
3802                CssRule::CounterStyle(ref rule) => {
3803                    self.extra_data.add_counter_style(
3804                        guard,
3805                        rule,
3806                        containing_rule_state.layer_id,
3807                    )?;
3808                },
3809                #[cfg(feature = "gecko")]
3810                CssRule::PositionTry(ref rule) => {
3811                    self.extra_data.add_position_try(
3812                        guard,
3813                        rule,
3814                        containing_rule_state.layer_id,
3815                    )?;
3816                },
3817                #[cfg(feature = "gecko")]
3818                CssRule::Page(ref rule) => {
3819                    self.extra_data
3820                        .add_page(guard, rule, containing_rule_state.layer_id)?;
3821                    handled = false;
3822                },
3823                _ => {
3824                    handled = false;
3825                },
3826            }
3827
3828            if handled {
3829                // Assert that there are no children, and that the rule is
3830                // effective.
3831                if cfg!(debug_assertions) {
3832                    let mut effective = false;
3833                    let children = EffectiveRulesIterator::children(
3834                        rule,
3835                        device,
3836                        quirks_mode,
3837                        guard,
3838                        &mut effective,
3839                    );
3840                    debug_assert!(children.is_none());
3841                    debug_assert!(effective);
3842                }
3843                continue;
3844            }
3845
3846            let mut effective = false;
3847            let children =
3848                EffectiveRulesIterator::children(rule, device, quirks_mode, guard, &mut effective);
3849
3850            if !effective {
3851                continue;
3852            }
3853
3854            fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
3855                // TODO: Measure what's more common / expensive, if
3856                // layer.clone() or the double hash lookup in the insert
3857                // case.
3858                if let Some(id) = data.layer_id.get(layer) {
3859                    return *id;
3860                }
3861                let id = LayerId(data.layers.len() as u16);
3862
3863                let parent_layer_id = if layer.layer_names().len() > 1 {
3864                    let mut parent = layer.clone();
3865                    parent.0.pop();
3866
3867                    *data
3868                        .layer_id
3869                        .get_mut(&parent)
3870                        .expect("Parent layers should be registered before child layers")
3871                } else {
3872                    LayerId::root()
3873                };
3874
3875                data.layers[parent_layer_id.0 as usize].children.push(id);
3876                data.layers.push(CascadeLayer {
3877                    id,
3878                    // NOTE(emilio): Order is evaluated after rebuild in
3879                    // compute_layer_order.
3880                    order: LayerOrder::first(),
3881                    children: vec![],
3882                });
3883
3884                data.layer_id.insert(layer.clone(), id);
3885
3886                id
3887            }
3888
3889            fn maybe_register_layers(
3890                data: &mut CascadeData,
3891                name: Option<&LayerName>,
3892                containing_rule_state: &mut ContainingRuleState,
3893            ) {
3894                let anon_name;
3895                let name = match name {
3896                    Some(name) => name,
3897                    None => {
3898                        anon_name = LayerName::new_anonymous();
3899                        &anon_name
3900                    },
3901                };
3902                for name in name.layer_names() {
3903                    containing_rule_state.layer_name.0.push(name.clone());
3904                    containing_rule_state.layer_id =
3905                        maybe_register_layer(data, &containing_rule_state.layer_name);
3906                }
3907                debug_assert_ne!(containing_rule_state.layer_id, LayerId::root());
3908            }
3909
3910            let saved_containing_rule_state = containing_rule_state.save();
3911            match *rule {
3912                CssRule::Import(ref lock) => {
3913                    let import_rule = lock.read_with(guard);
3914                    if rebuild_kind.should_rebuild_invalidation() {
3915                        self.effective_media_query_results
3916                            .saw_effective(import_rule);
3917                    }
3918                    match import_rule.layer {
3919                        ImportLayer::Named(ref name) => {
3920                            maybe_register_layers(self, Some(name), containing_rule_state)
3921                        },
3922                        ImportLayer::Anonymous => {
3923                            maybe_register_layers(self, None, containing_rule_state)
3924                        },
3925                        ImportLayer::None => {},
3926                    }
3927                },
3928                CssRule::Media(ref media_rule) => {
3929                    if rebuild_kind.should_rebuild_invalidation() {
3930                        self.effective_media_query_results
3931                            .saw_effective(&**media_rule);
3932                    }
3933                },
3934                CssRule::LayerBlock(ref rule) => {
3935                    maybe_register_layers(self, rule.name.as_ref(), containing_rule_state);
3936                },
3937                CssRule::LayerStatement(ref rule) => {
3938                    for name in &*rule.names {
3939                        maybe_register_layers(self, Some(name), containing_rule_state);
3940                        // Register each layer individually.
3941                        containing_rule_state.restore(&saved_containing_rule_state);
3942                    }
3943                },
3944                CssRule::Style(..) => {
3945                    containing_rule_state.nested_declarations_context =
3946                        NestedDeclarationsContext::Style;
3947                    if let Some(s) = list_for_nested_rules {
3948                        containing_rule_state.ancestor_selector_lists.push(s);
3949                    }
3950                },
3951                CssRule::Container(ref rule) => {
3952                    let id = ContainerConditionId(self.container_conditions.len() as u16);
3953                    self.container_conditions.push(ContainerConditionReference {
3954                        parent: containing_rule_state.container_condition_id,
3955                        condition: Some(rule.condition.clone()),
3956                    });
3957                    containing_rule_state.container_condition_id = id;
3958                },
3959                CssRule::StartingStyle(..) => {
3960                    containing_rule_state.in_starting_style = true;
3961                },
3962                CssRule::Scope(ref rule) => {
3963                    containing_rule_state.nested_declarations_context =
3964                        NestedDeclarationsContext::Scope;
3965                    let id = ScopeConditionId(self.scope_conditions.len() as u16);
3966                    let mut matches_shadow_host = false;
3967                    let implicit_scope_root = if let Some(start) = rule.bounds.start.as_ref() {
3968                        matches_shadow_host = scope_start_matches_shadow_host(start);
3969                        // Would be unused, but use the default as fallback.
3970                        StylistImplicitScopeRoot::default()
3971                    } else {
3972                        // (Re)Moving stylesheets trigger a complete flush, so saving the implicit
3973                        // root here should be safe.
3974                        if let Some(root) = stylesheet.implicit_scope_root() {
3975                            matches_shadow_host = root.matches_shadow_host();
3976                            match root {
3977                                ImplicitScopeRoot::InLightTree(_)
3978                                | ImplicitScopeRoot::Constructed
3979                                | ImplicitScopeRoot::DocumentElement => {
3980                                    StylistImplicitScopeRoot::Normal(root)
3981                                },
3982                                ImplicitScopeRoot::ShadowHost(_)
3983                                | ImplicitScopeRoot::InShadowTree(_) => {
3984                                    // Style data can be shared between shadow trees, so we must
3985                                    // query the implicit root for that specific tree.
3986                                    // Shared stylesheet means shared sheet indices, so we can
3987                                    // use that to locate the implicit root.
3988                                    // Technically, this can also be applied to the light tree,
3989                                    // but that requires also knowing about what cascade level we're at.
3990                                    StylistImplicitScopeRoot::Cached(sheet_index)
3991                                },
3992                            }
3993                        } else {
3994                            // Could not find implicit scope root, but use the default as fallback.
3995                            StylistImplicitScopeRoot::default()
3996                        }
3997                    };
3998
3999                    let replaced =
4000                        {
4001                            let start = rule.bounds.start.as_ref().map(|selector| {
4002                                match containing_rule_state.ancestor_selector_lists.last() {
4003                                    Some(s) => selector.replace_parent_selector(s),
4004                                    None => selector.clone(),
4005                                }
4006                            });
4007                            let implicit_scope_selector = &*IMPLICIT_SCOPE;
4008                            let end = rule.bounds.end.as_ref().map(|selector| {
4009                                selector.replace_parent_selector(implicit_scope_selector)
4010                            });
4011                            containing_rule_state
4012                                .ancestor_selector_lists
4013                                .push(implicit_scope_selector.clone());
4014                            ScopeBoundsWithHashes::new(quirks_mode, start, end)
4015                        };
4016
4017                    if let Some(selectors) = replaced.start.as_ref() {
4018                        self.scope_subject_map
4019                            .add_bound_start(&selectors.selectors, quirks_mode);
4020                    }
4021
4022                    let is_trivial = replaced.is_trivial();
4023                    self.scope_conditions.push(ScopeConditionReference {
4024                        parent: containing_rule_state.scope_condition_id,
4025                        condition: Some(replaced),
4026                        implicit_scope_root,
4027                        is_trivial,
4028                    });
4029                    containing_rule_state
4030                        .scope_matches_shadow_host
4031                        .nest_for_scope(matches_shadow_host);
4032                    containing_rule_state.scope_condition_id = id;
4033                },
4034                // We don't care about any other rule.
4035                _ => {},
4036            }
4037
4038            if let Some(children) = children {
4039                self.add_rule_list(
4040                    children,
4041                    device,
4042                    quirks_mode,
4043                    stylesheet,
4044                    sheet_index,
4045                    guard,
4046                    rebuild_kind,
4047                    containing_rule_state,
4048                    precomputed_pseudo_element_decls.as_deref_mut(),
4049                )?;
4050            }
4051
4052            containing_rule_state.restore(&saved_containing_rule_state);
4053        }
4054
4055        Ok(())
4056    }
4057
4058    // Returns Err(..) to signify OOM
4059    fn add_stylesheet<S>(
4060        &mut self,
4061        device: &Device,
4062        quirks_mode: QuirksMode,
4063        stylesheet: &S,
4064        sheet_index: usize,
4065        guard: &SharedRwLockReadGuard,
4066        rebuild_kind: SheetRebuildKind,
4067        mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
4068    ) -> Result<(), AllocErr>
4069    where
4070        S: StylesheetInDocument + 'static,
4071    {
4072        if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
4073            return Ok(());
4074        }
4075
4076        let contents = stylesheet.contents();
4077
4078        if rebuild_kind.should_rebuild_invalidation() {
4079            self.effective_media_query_results.saw_effective(contents);
4080        }
4081
4082        let mut state = ContainingRuleState::default();
4083        self.add_rule_list(
4084            contents.rules(guard).iter(),
4085            device,
4086            quirks_mode,
4087            stylesheet,
4088            sheet_index,
4089            guard,
4090            rebuild_kind,
4091            &mut state,
4092            precomputed_pseudo_element_decls.as_deref_mut(),
4093        )?;
4094
4095        Ok(())
4096    }
4097
4098    /// Returns whether all the media-feature affected values matched before and
4099    /// match now in the given stylesheet.
4100    pub fn media_feature_affected_matches<S>(
4101        &self,
4102        stylesheet: &S,
4103        guard: &SharedRwLockReadGuard,
4104        device: &Device,
4105        quirks_mode: QuirksMode,
4106    ) -> bool
4107    where
4108        S: StylesheetInDocument + 'static,
4109    {
4110        use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
4111
4112        let effective_now = stylesheet.is_effective_for_device(device, guard);
4113
4114        let effective_then = self
4115            .effective_media_query_results
4116            .was_effective(stylesheet.contents());
4117
4118        if effective_now != effective_then {
4119            debug!(
4120                " > Stylesheet {:?} changed -> {}, {}",
4121                stylesheet.media(guard),
4122                effective_then,
4123                effective_now
4124            );
4125            return false;
4126        }
4127
4128        if !effective_now {
4129            return true;
4130        }
4131
4132        let mut iter = stylesheet.iter_rules::<PotentiallyEffectiveMediaRules>(device, guard);
4133
4134        while let Some(rule) = iter.next() {
4135            match *rule {
4136                CssRule::Style(..)
4137                | CssRule::NestedDeclarations(..)
4138                | CssRule::Namespace(..)
4139                | CssRule::FontFace(..)
4140                | CssRule::Container(..)
4141                | CssRule::CounterStyle(..)
4142                | CssRule::Supports(..)
4143                | CssRule::Keyframes(..)
4144                | CssRule::Margin(..)
4145                | CssRule::Page(..)
4146                | CssRule::Property(..)
4147                | CssRule::Document(..)
4148                | CssRule::LayerBlock(..)
4149                | CssRule::LayerStatement(..)
4150                | CssRule::FontPaletteValues(..)
4151                | CssRule::FontFeatureValues(..)
4152                | CssRule::Scope(..)
4153                | CssRule::StartingStyle(..)
4154                | CssRule::PositionTry(..) => {
4155                    // Not affected by device changes.
4156                    continue;
4157                },
4158                CssRule::Import(ref lock) => {
4159                    let import_rule = lock.read_with(guard);
4160                    let effective_now = match import_rule.stylesheet.media(guard) {
4161                        Some(m) => m.evaluate(device, quirks_mode),
4162                        None => true,
4163                    };
4164                    let effective_then = self
4165                        .effective_media_query_results
4166                        .was_effective(import_rule);
4167                    if effective_now != effective_then {
4168                        debug!(
4169                            " > @import rule {:?} changed {} -> {}",
4170                            import_rule.stylesheet.media(guard),
4171                            effective_then,
4172                            effective_now
4173                        );
4174                        return false;
4175                    }
4176
4177                    if !effective_now {
4178                        iter.skip_children();
4179                    }
4180                },
4181                CssRule::Media(ref media_rule) => {
4182                    let mq = media_rule.media_queries.read_with(guard);
4183                    let effective_now = mq.evaluate(device, quirks_mode);
4184                    let effective_then = self
4185                        .effective_media_query_results
4186                        .was_effective(&**media_rule);
4187
4188                    if effective_now != effective_then {
4189                        debug!(
4190                            " > @media rule {:?} changed {} -> {}",
4191                            mq, effective_then, effective_now
4192                        );
4193                        return false;
4194                    }
4195
4196                    if !effective_now {
4197                        iter.skip_children();
4198                    }
4199                },
4200            }
4201        }
4202
4203        true
4204    }
4205
4206    /// Returns the custom properties map.
4207    pub fn custom_property_registrations(&self) -> &LayerOrderedMap<Arc<PropertyRegistration>> {
4208        &self.custom_property_registrations
4209    }
4210
4211    fn revalidate_scopes<E: TElement>(
4212        &self,
4213        element: &E,
4214        matching_context: &mut MatchingContext<E::Impl>,
4215        result: &mut ScopeRevalidationResult,
4216    ) {
4217        // TODO(dshin): A scope block may not contain style rule for this element, but we don't keep
4218        // track of that, so we check _all_ scope conditions. It's possible for two comparable elements
4219        // to share scope & relevant styles rules, but also differ in scopes that do not contain style
4220        // rules relevant to them. So while we can be certain that an identical result share scoped styles
4221        // (Given that other sharing conditions are met), it is uncertain if elements with non-matching
4222        // results do not.
4223        for condition_id in 1..self.scope_conditions.len() {
4224            let condition = &self.scope_conditions[condition_id];
4225            let matches = if condition.is_trivial {
4226                // Just ignore this condition - for style sharing candidates, guaranteed
4227                // the same match result.
4228                continue;
4229            } else {
4230                let result = scope_root_candidates(
4231                    &self.scope_conditions,
4232                    ScopeConditionId(condition_id as u16),
4233                    element,
4234                    // This should be ok since we aren't sharing styles across shadow boundaries.
4235                    false,
4236                    &self.scope_subject_map,
4237                    matching_context,
4238                );
4239                !result.candidates.is_empty()
4240            };
4241            result.scopes_matched.push(matches);
4242        }
4243    }
4244
4245    /// Clears the cascade data, but not the invalidation data.
4246    fn clear_cascade_data(&mut self) {
4247        self.normal_rules.clear();
4248        if let Some(ref mut slotted_rules) = self.slotted_rules {
4249            slotted_rules.clear();
4250        }
4251        if let Some(ref mut part_rules) = self.part_rules {
4252            part_rules.clear();
4253        }
4254        if let Some(ref mut host_rules) = self.featureless_host_rules {
4255            host_rules.clear();
4256        }
4257        self.animations.clear();
4258        self.custom_property_registrations.clear();
4259        self.layer_id.clear();
4260        self.layers.clear();
4261        self.layers.push(CascadeLayer::root());
4262        self.container_conditions.clear();
4263        self.container_conditions
4264            .push(ContainerConditionReference::none());
4265        self.scope_conditions.clear();
4266        self.scope_conditions.push(ScopeConditionReference::none());
4267        #[cfg(feature = "gecko")]
4268        self.extra_data.clear();
4269        self.rules_source_order = 0;
4270        self.num_selectors = 0;
4271        self.num_declarations = 0;
4272    }
4273
4274    fn clear(&mut self) {
4275        self.clear_cascade_data();
4276        self.invalidation_map.clear();
4277        self.relative_selector_invalidation_map.clear();
4278        self.additional_relative_selector_invalidation_map.clear();
4279        self.attribute_dependencies.clear();
4280        self.nth_of_attribute_dependencies.clear();
4281        self.nth_of_custom_state_dependencies.clear();
4282        self.nth_of_class_dependencies.clear();
4283        self.state_dependencies = ElementState::empty();
4284        self.nth_of_state_dependencies = ElementState::empty();
4285        self.document_state_dependencies = DocumentState::empty();
4286        self.mapped_ids.clear();
4287        self.nth_of_mapped_ids.clear();
4288        self.selectors_for_cache_revalidation.clear();
4289        self.effective_media_query_results.clear();
4290        self.scope_subject_map.clear();
4291    }
4292}
4293
4294impl CascadeDataCacheEntry for CascadeData {
4295    fn rebuild<S>(
4296        device: &Device,
4297        quirks_mode: QuirksMode,
4298        collection: SheetCollectionFlusher<S>,
4299        guard: &SharedRwLockReadGuard,
4300        old: &Self,
4301    ) -> Result<Arc<Self>, AllocErr>
4302    where
4303        S: StylesheetInDocument + PartialEq + 'static,
4304    {
4305        debug_assert!(collection.dirty(), "We surely need to do something?");
4306        // If we're doing a full rebuild anyways, don't bother cloning the data.
4307        let mut updatable_entry = match collection.data_validity() {
4308            DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
4309            DataValidity::FullyInvalid => Self::new(),
4310        };
4311        updatable_entry.rebuild(device, quirks_mode, collection, guard)?;
4312        Ok(Arc::new(updatable_entry))
4313    }
4314
4315    #[cfg(feature = "gecko")]
4316    fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
4317        self.normal_rules.add_size_of(ops, sizes);
4318        if let Some(ref slotted_rules) = self.slotted_rules {
4319            slotted_rules.add_size_of(ops, sizes);
4320        }
4321        if let Some(ref part_rules) = self.part_rules {
4322            part_rules.add_size_of(ops, sizes);
4323        }
4324        if let Some(ref host_rules) = self.featureless_host_rules {
4325            host_rules.add_size_of(ops, sizes);
4326        }
4327        sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
4328        sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
4329        sizes.mOther += self.animations.size_of(ops);
4330        sizes.mOther += self.effective_media_query_results.size_of(ops);
4331        sizes.mOther += self.extra_data.size_of(ops);
4332    }
4333}
4334
4335impl Default for CascadeData {
4336    fn default() -> Self {
4337        CascadeData::new()
4338    }
4339}
4340
4341/// A rule, that wraps a style rule, but represents a single selector of the
4342/// rule.
4343#[derive(Clone, Debug, MallocSizeOf)]
4344pub struct Rule {
4345    /// The selector this struct represents. We store this and the
4346    /// any_{important,normal} booleans inline in the Rule to avoid
4347    /// pointer-chasing when gathering applicable declarations, which
4348    /// can ruin performance when there are a lot of rules.
4349    #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
4350    pub selector: Selector<SelectorImpl>,
4351
4352    /// The ancestor hashes associated with the selector.
4353    pub hashes: AncestorHashes,
4354
4355    /// The source order this style rule appears in. Note that we only use
4356    /// three bytes to store this value in ApplicableDeclarationsBlock, so
4357    /// we could repurpose that storage here if we needed to.
4358    pub source_order: u32,
4359
4360    /// The current layer id of this style rule.
4361    pub layer_id: LayerId,
4362
4363    /// The current @container rule id.
4364    pub container_condition_id: ContainerConditionId,
4365
4366    /// True if this rule is inside @starting-style.
4367    pub is_starting_style: bool,
4368
4369    /// The current @scope rule id.
4370    pub scope_condition_id: ScopeConditionId,
4371
4372    /// The actual style rule.
4373    #[ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."]
4374    pub style_source: StyleSource,
4375}
4376
4377impl SelectorMapEntry for Rule {
4378    fn selector(&self) -> SelectorIter<'_, SelectorImpl> {
4379        self.selector.iter()
4380    }
4381}
4382
4383impl Rule {
4384    /// Returns the specificity of the rule.
4385    pub fn specificity(&self) -> u32 {
4386        self.selector.specificity()
4387    }
4388
4389    /// Turns this rule into an `ApplicableDeclarationBlock` for the given
4390    /// cascade level.
4391    pub fn to_applicable_declaration_block(
4392        &self,
4393        level: CascadeLevel,
4394        cascade_data: &CascadeData,
4395        scope_proximity: ScopeProximity,
4396    ) -> ApplicableDeclarationBlock {
4397        ApplicableDeclarationBlock::new(
4398            self.style_source.clone(),
4399            self.source_order,
4400            level,
4401            self.specificity(),
4402            cascade_data.layer_order_for(self.layer_id),
4403            scope_proximity,
4404        )
4405    }
4406
4407    /// Creates a new Rule.
4408    pub fn new(
4409        selector: Selector<SelectorImpl>,
4410        hashes: AncestorHashes,
4411        style_source: StyleSource,
4412        source_order: u32,
4413        layer_id: LayerId,
4414        container_condition_id: ContainerConditionId,
4415        is_starting_style: bool,
4416        scope_condition_id: ScopeConditionId,
4417    ) -> Self {
4418        Self {
4419            selector,
4420            hashes,
4421            style_source,
4422            source_order,
4423            layer_id,
4424            container_condition_id,
4425            is_starting_style,
4426            scope_condition_id,
4427        }
4428    }
4429}
4430
4431// The size of this is critical to performance on the bloom-basic
4432// microbenchmark.
4433// When iterating over a large Rule array, we want to be able to fast-reject
4434// selectors (with the inline hashes) with as few cache misses as possible.
4435size_of_test!(Rule, 40);
4436
4437/// A function to be able to test the revalidation stuff.
4438pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
4439    let mut needs_revalidation = false;
4440    let mut mapped_ids = Default::default();
4441    let mut nth_of_mapped_ids = Default::default();
4442    let mut attribute_dependencies = Default::default();
4443    let mut nth_of_class_dependencies = Default::default();
4444    let mut nth_of_attribute_dependencies = Default::default();
4445    let mut nth_of_custom_state_dependencies = Default::default();
4446    let mut state_dependencies = ElementState::empty();
4447    let mut nth_of_state_dependencies = ElementState::empty();
4448    let mut document_state_dependencies = DocumentState::empty();
4449    let mut visitor = StylistSelectorVisitor {
4450        passed_rightmost_selector: false,
4451        needs_revalidation: &mut needs_revalidation,
4452        in_selector_list_of: SelectorListKind::default(),
4453        mapped_ids: &mut mapped_ids,
4454        nth_of_mapped_ids: &mut nth_of_mapped_ids,
4455        attribute_dependencies: &mut attribute_dependencies,
4456        nth_of_class_dependencies: &mut nth_of_class_dependencies,
4457        nth_of_attribute_dependencies: &mut nth_of_attribute_dependencies,
4458        nth_of_custom_state_dependencies: &mut nth_of_custom_state_dependencies,
4459        state_dependencies: &mut state_dependencies,
4460        nth_of_state_dependencies: &mut nth_of_state_dependencies,
4461        document_state_dependencies: &mut document_state_dependencies,
4462    };
4463    s.visit(&mut visitor);
4464    needs_revalidation
4465}