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 
7 use crate::applicable_declarations::{
8     ApplicableDeclarationBlock, ApplicableDeclarationList, CascadePriority,
9 };
10 use crate::context::{CascadeInputs, QuirksMode};
11 use crate::dom::{TElement, TShadowRoot};
12 use crate::element_state::{DocumentState, ElementState};
13 use crate::font_metrics::FontMetricsProvider;
14 #[cfg(feature = "gecko")]
15 use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion};
16 use crate::invalidation::element::invalidation_map::InvalidationMap;
17 use crate::invalidation::media_queries::{
18     EffectiveMediaQueryResults, MediaListKey, ToMediaListKey,
19 };
20 use crate::invalidation::stylesheets::RuleChangeKind;
21 use crate::media_queries::Device;
22 use crate::properties::{self, CascadeMode, ComputedValues};
23 use crate::properties::{AnimationDeclarations, PropertyDeclarationBlock};
24 use crate::rule_cache::{RuleCache, RuleCacheConditions};
25 use crate::rule_collector::{containing_shadow_ignoring_svg_use, RuleCollector};
26 use crate::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource};
27 use crate::selector_map::{PrecomputedHashMap, PrecomputedHashSet, SelectorMap, SelectorMapEntry};
28 use crate::selector_parser::{PerPseudoElementMap, PseudoElement, SelectorImpl, SnapshotMap};
29 use crate::shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
30 use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKind};
31 use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher};
32 use crate::stylesheets::keyframes_rule::KeyframesAnimation;
33 use crate::stylesheets::layer_rule::{LayerId, LayerName, LayerOrder};
34 use crate::stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
35 #[cfg(feature = "gecko")]
36 use crate::stylesheets::{
37     CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule, ScrollTimelineRule,
38 };
39 use crate::stylesheets::{
40     CssRule, EffectiveRulesIterator, Origin, OriginSet, PerOrigin, PerOriginIter,
41 };
42 use crate::stylesheets::{StyleRule, StylesheetContents, StylesheetInDocument};
43 use crate::thread_state::{self, ThreadState};
44 use crate::AllocErr;
45 use crate::{Atom, LocalName, Namespace, ShrinkIfNeeded, WeakAtom};
46 use fxhash::FxHashMap;
47 use malloc_size_of::MallocSizeOf;
48 #[cfg(feature = "gecko")]
49 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf};
50 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
51 use selectors::bloom::BloomFilter;
52 use selectors::matching::VisitedHandlingMode;
53 use selectors::matching::{matches_selector, ElementSelectorFlags, MatchingContext, MatchingMode};
54 use selectors::parser::{AncestorHashes, Combinator, Component, Selector, SelectorIter};
55 use selectors::visitor::SelectorVisitor;
56 use selectors::NthIndexCache;
57 use servo_arc::{Arc, ArcBorrow};
58 use smallbitvec::SmallBitVec;
59 use smallvec::SmallVec;
60 use std::cmp::Ordering;
61 use std::hash::{Hash, Hasher};
62 use std::sync::Mutex;
63 use std::{mem, ops};
64 use style_traits::viewport::ViewportConstraints;
65 
66 /// The type of the stylesheets that the stylist contains.
67 #[cfg(feature = "servo")]
68 pub type StylistSheet = crate::stylesheets::DocumentStyleSheet;
69 
70 /// The type of the stylesheets that the stylist contains.
71 #[cfg(feature = "gecko")]
72 pub type StylistSheet = crate::gecko::data::GeckoStyleSheet;
73 
74 #[derive(Debug, Clone)]
75 struct StylesheetContentsPtr(Arc<StylesheetContents>);
76 
77 impl PartialEq for StylesheetContentsPtr {
78     #[inline]
eq(&self, other: &Self) -> bool79     fn eq(&self, other: &Self) -> bool {
80         Arc::ptr_eq(&self.0, &other.0)
81     }
82 }
83 
84 impl Eq for StylesheetContentsPtr {}
85 
86 impl Hash for StylesheetContentsPtr {
hash<H: Hasher>(&self, state: &mut H)87     fn hash<H: Hasher>(&self, state: &mut H) {
88         let contents: &StylesheetContents = &*self.0;
89         (contents as *const StylesheetContents).hash(state)
90     }
91 }
92 
93 type StyleSheetContentList = Vec<StylesheetContentsPtr>;
94 
95 /// A key in the cascade data cache.
96 #[derive(Debug, Hash, Default, PartialEq, Eq)]
97 struct CascadeDataCacheKey {
98     media_query_results: Vec<MediaListKey>,
99     contents: StyleSheetContentList,
100 }
101 
102 unsafe impl Send for CascadeDataCacheKey {}
103 unsafe impl Sync for CascadeDataCacheKey {}
104 
105 trait CascadeDataCacheEntry: Sized {
106     /// Returns a reference to the cascade data.
cascade_data(&self) -> &CascadeData107     fn cascade_data(&self) -> &CascadeData;
108     /// Rebuilds the cascade data for the new stylesheet collection. The
109     /// collection is guaranteed to be dirty.
rebuild<S>( device: &Device, quirks_mode: QuirksMode, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, old_entry: &Self, ) -> Result<Arc<Self>, AllocErr> where S: StylesheetInDocument + PartialEq + 'static110     fn rebuild<S>(
111         device: &Device,
112         quirks_mode: QuirksMode,
113         collection: SheetCollectionFlusher<S>,
114         guard: &SharedRwLockReadGuard,
115         old_entry: &Self,
116     ) -> Result<Arc<Self>, AllocErr>
117     where
118         S: StylesheetInDocument + PartialEq + 'static;
119     /// Measures heap memory usage.
120     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)121     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes);
122 }
123 
124 struct CascadeDataCache<Entry> {
125     entries: FxHashMap<CascadeDataCacheKey, Arc<Entry>>,
126 }
127 
128 impl<Entry> CascadeDataCache<Entry>
129 where
130     Entry: CascadeDataCacheEntry,
131 {
new() -> Self132     fn new() -> Self {
133         Self {
134             entries: Default::default(),
135         }
136     }
137 
len(&self) -> usize138     fn len(&self) -> usize {
139         self.entries.len()
140     }
141 
142     // FIXME(emilio): This may need to be keyed on quirks-mode too, though for
143     // UA sheets there aren't class / id selectors on those sheets, usually, so
144     // it's probably ok... For the other cache the quirks mode shouldn't differ
145     // so also should be fine.
lookup<'a, S>( &'a mut self, device: &Device, quirks_mode: QuirksMode, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, old_entry: &Entry, ) -> Result<Option<Arc<Entry>>, AllocErr> where S: StylesheetInDocument + PartialEq + 'static,146     fn lookup<'a, S>(
147         &'a mut self,
148         device: &Device,
149         quirks_mode: QuirksMode,
150         collection: SheetCollectionFlusher<S>,
151         guard: &SharedRwLockReadGuard,
152         old_entry: &Entry,
153     ) -> Result<Option<Arc<Entry>>, AllocErr>
154     where
155         S: StylesheetInDocument + PartialEq + 'static,
156     {
157         use std::collections::hash_map::Entry as HashMapEntry;
158         debug!("StyleSheetCache::lookup({})", self.len());
159 
160         if !collection.dirty() {
161             return Ok(None);
162         }
163 
164         let mut key = CascadeDataCacheKey::default();
165         for sheet in collection.sheets() {
166             CascadeData::collect_applicable_media_query_results_into(
167                 device,
168                 sheet,
169                 guard,
170                 &mut key.media_query_results,
171                 &mut key.contents,
172             )
173         }
174 
175         let new_entry;
176         match self.entries.entry(key) {
177             HashMapEntry::Vacant(e) => {
178                 debug!("> Picking the slow path (not in the cache)");
179                 new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
180                 e.insert(new_entry.clone());
181             },
182             HashMapEntry::Occupied(mut e) => {
183                 // Avoid reusing our old entry (this can happen if we get
184                 // invalidated due to CSSOM mutations and our old stylesheet
185                 // contents were already unique, for example).
186                 if !std::ptr::eq(&**e.get(), old_entry) {
187                     if log_enabled!(log::Level::Debug) {
188                         debug!("cache hit for:");
189                         for sheet in collection.sheets() {
190                             debug!(" > {:?}", sheet);
191                         }
192                     }
193                     // The line below ensures the "committed" bit is updated
194                     // properly.
195                     collection.each(|_, _| true);
196                     return Ok(Some(e.get().clone()));
197                 }
198 
199                 debug!("> Picking the slow path due to same entry as old");
200                 new_entry = Entry::rebuild(device, quirks_mode, collection, guard, old_entry)?;
201                 e.insert(new_entry.clone());
202             },
203         }
204 
205         Ok(Some(new_entry))
206     }
207 
208     /// Returns all the cascade datas that are not being used (that is, that are
209     /// held alive just by this cache).
210     ///
211     /// We return them instead of dropping in place because some of them may
212     /// keep alive some other documents (like the SVG documents kept alive by
213     /// URL references), and thus we don't want to drop them while locking the
214     /// cache to not deadlock.
take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]>215     fn take_unused(&mut self) -> SmallVec<[Arc<Entry>; 3]> {
216         let mut unused = SmallVec::new();
217         self.entries.retain(|_key, value| {
218             // is_unique() returns false for static references, but we never
219             // have static references to UserAgentCascadeDatas.  If we did, it
220             // may not make sense to put them in the cache in the first place.
221             if !value.is_unique() {
222                 return true;
223             }
224             unused.push(value.clone());
225             false
226         });
227         unused
228     }
229 
take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>>230     fn take_all(&mut self) -> FxHashMap<CascadeDataCacheKey, Arc<Entry>> {
231         mem::take(&mut self.entries)
232     }
233 
234     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)235     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
236         sizes.mOther += self.entries.shallow_size_of(ops);
237         for (_key, arc) in self.entries.iter() {
238             // These are primary Arc references that can be measured
239             // unconditionally.
240             sizes.mOther += arc.unconditional_shallow_size_of(ops);
241             arc.add_size_of(ops, sizes);
242         }
243     }
244 }
245 
246 /// Measure heap usage of UA_CASCADE_DATA_CACHE.
247 #[cfg(feature = "gecko")]
add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)248 pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
249     UA_CASCADE_DATA_CACHE
250         .lock()
251         .unwrap()
252         .add_size_of(ops, sizes);
253 }
254 
255 lazy_static! {
256     /// A cache of computed user-agent data, to be shared across documents.
257     static ref UA_CASCADE_DATA_CACHE: Mutex<UserAgentCascadeDataCache> =
258         Mutex::new(UserAgentCascadeDataCache::new());
259 }
260 
261 impl CascadeDataCacheEntry for UserAgentCascadeData {
cascade_data(&self) -> &CascadeData262     fn cascade_data(&self) -> &CascadeData {
263         &self.cascade_data
264     }
265 
rebuild<S>( device: &Device, quirks_mode: QuirksMode, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, _old: &Self, ) -> Result<Arc<Self>, AllocErr> where S: StylesheetInDocument + PartialEq + 'static,266     fn rebuild<S>(
267         device: &Device,
268         quirks_mode: QuirksMode,
269         collection: SheetCollectionFlusher<S>,
270         guard: &SharedRwLockReadGuard,
271         _old: &Self,
272     ) -> Result<Arc<Self>, AllocErr>
273     where
274         S: StylesheetInDocument + PartialEq + 'static,
275     {
276         // TODO: Maybe we should support incremental rebuilds, though they seem
277         // uncommon and rebuild() doesn't deal with
278         // precomputed_pseudo_element_decls for now so...
279         let mut new_data = Self {
280             cascade_data: CascadeData::new(),
281             precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations::default(),
282         };
283 
284         for sheet in collection.sheets() {
285             new_data.cascade_data.add_stylesheet(
286                 device,
287                 quirks_mode,
288                 sheet,
289                 guard,
290                 SheetRebuildKind::Full,
291                 Some(&mut new_data.precomputed_pseudo_element_decls),
292             )?;
293         }
294 
295         new_data.cascade_data.did_finish_rebuild();
296 
297         Ok(Arc::new(new_data))
298     }
299 
300     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)301     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
302         self.cascade_data.add_size_of(ops, sizes);
303         sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
304     }
305 }
306 
307 type UserAgentCascadeDataCache = CascadeDataCache<UserAgentCascadeData>;
308 
309 type PrecomputedPseudoElementDeclarations = PerPseudoElementMap<Vec<ApplicableDeclarationBlock>>;
310 
311 #[derive(Default)]
312 struct UserAgentCascadeData {
313     cascade_data: CascadeData,
314 
315     /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
316     ///
317     /// These are eagerly computed once, and then used to resolve the new
318     /// computed values on the fly on layout.
319     ///
320     /// These are only filled from UA stylesheets.
321     precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
322 }
323 
324 /// All the computed information for all the stylesheets that apply to the
325 /// document.
326 #[derive(Default)]
327 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
328 pub struct DocumentCascadeData {
329     #[cfg_attr(
330         feature = "servo",
331         ignore_malloc_size_of = "Arc, owned by UserAgentCascadeDataCache"
332     )]
333     user_agent: Arc<UserAgentCascadeData>,
334     user: CascadeData,
335     author: CascadeData,
336     per_origin: PerOrigin<()>,
337 }
338 
339 /// An iterator over the cascade data of a given document.
340 pub struct DocumentCascadeDataIter<'a> {
341     iter: PerOriginIter<'a, ()>,
342     cascade_data: &'a DocumentCascadeData,
343 }
344 
345 impl<'a> Iterator for DocumentCascadeDataIter<'a> {
346     type Item = (&'a CascadeData, Origin);
347 
next(&mut self) -> Option<Self::Item>348     fn next(&mut self) -> Option<Self::Item> {
349         let (_, origin) = self.iter.next()?;
350         Some((self.cascade_data.borrow_for_origin(origin), origin))
351     }
352 }
353 
354 impl DocumentCascadeData {
355     /// Borrows the cascade data for a given origin.
356     #[inline]
borrow_for_origin(&self, origin: Origin) -> &CascadeData357     pub fn borrow_for_origin(&self, origin: Origin) -> &CascadeData {
358         match origin {
359             Origin::UserAgent => &self.user_agent.cascade_data,
360             Origin::Author => &self.author,
361             Origin::User => &self.user,
362         }
363     }
364 
iter_origins(&self) -> DocumentCascadeDataIter365     fn iter_origins(&self) -> DocumentCascadeDataIter {
366         DocumentCascadeDataIter {
367             iter: self.per_origin.iter_origins(),
368             cascade_data: self,
369         }
370     }
371 
iter_origins_rev(&self) -> DocumentCascadeDataIter372     fn iter_origins_rev(&self) -> DocumentCascadeDataIter {
373         DocumentCascadeDataIter {
374             iter: self.per_origin.iter_origins_rev(),
375             cascade_data: self,
376         }
377     }
378 
379     /// Rebuild the cascade data for the given document stylesheets, and
380     /// optionally with a set of user agent stylesheets.  Returns Err(..)
381     /// to signify OOM.
rebuild<'a, S>( &mut self, device: &Device, quirks_mode: QuirksMode, mut flusher: DocumentStylesheetFlusher<'a, S>, guards: &StylesheetGuards, ) -> Result<(), AllocErr> where S: StylesheetInDocument + PartialEq + 'static,382     fn rebuild<'a, S>(
383         &mut self,
384         device: &Device,
385         quirks_mode: QuirksMode,
386         mut flusher: DocumentStylesheetFlusher<'a, S>,
387         guards: &StylesheetGuards,
388     ) -> Result<(), AllocErr>
389     where
390         S: StylesheetInDocument + PartialEq + 'static,
391     {
392         // First do UA sheets.
393         {
394             let origin_flusher = flusher.flush_origin(Origin::UserAgent);
395             // Dirty check is just a minor optimization (no need to grab the
396             // lock if nothing has changed).
397             if origin_flusher.dirty() {
398                 let mut ua_cache = UA_CASCADE_DATA_CACHE.lock().unwrap();
399                 let new_data = ua_cache.lookup(
400                     device,
401                     quirks_mode,
402                     origin_flusher,
403                     guards.ua_or_user,
404                     &self.user_agent,
405                 )?;
406                 if let Some(new_data) = new_data {
407                     self.user_agent = new_data;
408                 }
409                 let _unused_entries = ua_cache.take_unused();
410                 // See the comments in take_unused() as for why the following
411                 // line.
412                 std::mem::drop(ua_cache);
413             }
414         }
415 
416         // Now do the user sheets.
417         self.user.rebuild(
418             device,
419             quirks_mode,
420             flusher.flush_origin(Origin::User),
421             guards.ua_or_user,
422         )?;
423 
424         // And now the author sheets.
425         self.author.rebuild(
426             device,
427             quirks_mode,
428             flusher.flush_origin(Origin::Author),
429             guards.author,
430         )?;
431 
432         Ok(())
433     }
434 
435     /// Measures heap usage.
436     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)437     pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
438         self.user.add_size_of(ops, sizes);
439         self.author.add_size_of(ops, sizes);
440     }
441 }
442 
443 /// Whether author styles are enabled.
444 ///
445 /// This is used to support Gecko.
446 #[allow(missing_docs)]
447 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
448 pub enum AuthorStylesEnabled {
449     Yes,
450     No,
451 }
452 
453 /// A wrapper over a DocumentStylesheetSet that can be `Sync`, since it's only
454 /// used and exposed via mutable methods in the `Stylist`.
455 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
456 struct StylistStylesheetSet(DocumentStylesheetSet<StylistSheet>);
457 // Read above to see why this is fine.
458 unsafe impl Sync for StylistStylesheetSet {}
459 
460 impl StylistStylesheetSet {
new() -> Self461     fn new() -> Self {
462         StylistStylesheetSet(DocumentStylesheetSet::new())
463     }
464 }
465 
466 impl ops::Deref for StylistStylesheetSet {
467     type Target = DocumentStylesheetSet<StylistSheet>;
468 
deref(&self) -> &Self::Target469     fn deref(&self) -> &Self::Target {
470         &self.0
471     }
472 }
473 
474 impl ops::DerefMut for StylistStylesheetSet {
deref_mut(&mut self) -> &mut Self::Target475     fn deref_mut(&mut self) -> &mut Self::Target {
476         &mut self.0
477     }
478 }
479 
480 /// This structure holds all the selectors and device characteristics
481 /// for a given document. The selectors are converted into `Rule`s
482 /// and sorted into `SelectorMap`s keyed off stylesheet origin and
483 /// pseudo-element (see `CascadeData`).
484 ///
485 /// This structure is effectively created once per pipeline, in the
486 /// LayoutThread corresponding to that pipeline.
487 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
488 pub struct Stylist {
489     /// Device that the stylist is currently evaluating against.
490     ///
491     /// This field deserves a bigger comment due to the different use that Gecko
492     /// and Servo give to it (that we should eventually unify).
493     ///
494     /// With Gecko, the device is never changed. Gecko manually tracks whether
495     /// the device data should be reconstructed, and "resets" the state of the
496     /// device.
497     ///
498     /// On Servo, on the other hand, the device is a really cheap representation
499     /// that is recreated each time some constraint changes and calling
500     /// `set_device`.
501     device: Device,
502 
503     /// Viewport constraints based on the current device.
504     viewport_constraints: Option<ViewportConstraints>,
505 
506     /// The list of stylesheets.
507     stylesheets: StylistStylesheetSet,
508 
509     /// A cache of CascadeDatas for AuthorStylesheetSets (i.e., shadow DOM).
510     author_data_cache: CascadeDataCache<CascadeData>,
511 
512     /// If true, the quirks-mode stylesheet is applied.
513     #[cfg_attr(feature = "servo", ignore_malloc_size_of = "defined in selectors")]
514     quirks_mode: QuirksMode,
515 
516     /// Selector maps for all of the style sheets in the stylist, after
517     /// evalutaing media rules against the current device, split out per
518     /// cascade level.
519     cascade_data: DocumentCascadeData,
520 
521     /// Whether author styles are enabled.
522     author_styles_enabled: AuthorStylesEnabled,
523 
524     /// The rule tree, that stores the results of selector matching.
525     rule_tree: RuleTree,
526 
527     /// The total number of times the stylist has been rebuilt.
528     num_rebuilds: usize,
529 }
530 
531 /// What cascade levels to include when styling elements.
532 #[derive(Clone, Copy, PartialEq)]
533 pub enum RuleInclusion {
534     /// Include rules for style sheets at all cascade levels.  This is the
535     /// normal rule inclusion mode.
536     All,
537     /// Only include rules from UA and user level sheets.  Used to implement
538     /// `getDefaultComputedStyle`.
539     DefaultOnly,
540 }
541 
542 #[cfg(feature = "gecko")]
543 impl From<StyleRuleInclusion> for RuleInclusion {
from(value: StyleRuleInclusion) -> Self544     fn from(value: StyleRuleInclusion) -> Self {
545         match value {
546             StyleRuleInclusion::All => RuleInclusion::All,
547             StyleRuleInclusion::DefaultOnly => RuleInclusion::DefaultOnly,
548         }
549     }
550 }
551 
552 impl Stylist {
553     /// Construct a new `Stylist`, using given `Device` and `QuirksMode`.
554     /// If more members are added here, think about whether they should
555     /// be reset in clear().
556     #[inline]
new(device: Device, quirks_mode: QuirksMode) -> Self557     pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
558         Self {
559             viewport_constraints: None,
560             device,
561             quirks_mode,
562             stylesheets: StylistStylesheetSet::new(),
563             author_data_cache: CascadeDataCache::new(),
564             cascade_data: Default::default(),
565             author_styles_enabled: AuthorStylesEnabled::Yes,
566             rule_tree: RuleTree::new(),
567             num_rebuilds: 0,
568         }
569     }
570 
571     /// Returns the document cascade data.
572     #[inline]
cascade_data(&self) -> &DocumentCascadeData573     pub fn cascade_data(&self) -> &DocumentCascadeData {
574         &self.cascade_data
575     }
576 
577     /// Returns whether author styles are enabled or not.
578     #[inline]
author_styles_enabled(&self) -> AuthorStylesEnabled579     pub fn author_styles_enabled(&self) -> AuthorStylesEnabled {
580         self.author_styles_enabled
581     }
582 
583     /// Iterate through all the cascade datas from the document.
584     #[inline]
iter_origins(&self) -> DocumentCascadeDataIter585     pub fn iter_origins(&self) -> DocumentCascadeDataIter {
586         self.cascade_data.iter_origins()
587     }
588 
589     /// Does what the name says, to prevent author_data_cache to grow without
590     /// bound.
remove_unique_author_data_cache_entries(&mut self)591     pub fn remove_unique_author_data_cache_entries(&mut self) {
592         self.author_data_cache.take_unused();
593     }
594 
595     /// Rebuilds (if needed) the CascadeData given a sheet collection.
rebuild_author_data<S>( &mut self, old_data: &CascadeData, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, ) -> Result<Option<Arc<CascadeData>>, AllocErr> where S: StylesheetInDocument + PartialEq + 'static,596     pub fn rebuild_author_data<S>(
597         &mut self,
598         old_data: &CascadeData,
599         collection: SheetCollectionFlusher<S>,
600         guard: &SharedRwLockReadGuard,
601     ) -> Result<Option<Arc<CascadeData>>, AllocErr>
602     where
603         S: StylesheetInDocument + PartialEq + 'static,
604     {
605         self.author_data_cache
606             .lookup(&self.device, self.quirks_mode, collection, guard, old_data)
607     }
608 
609     /// Iterate over the extra data in origin order.
610     #[inline]
iter_extra_data_origins(&self) -> ExtraStyleDataIterator611     pub fn iter_extra_data_origins(&self) -> ExtraStyleDataIterator {
612         ExtraStyleDataIterator(self.cascade_data.iter_origins())
613     }
614 
615     /// Iterate over the extra data in reverse origin order.
616     #[inline]
iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator617     pub fn iter_extra_data_origins_rev(&self) -> ExtraStyleDataIterator {
618         ExtraStyleDataIterator(self.cascade_data.iter_origins_rev())
619     }
620 
621     /// Returns the number of selectors.
num_selectors(&self) -> usize622     pub fn num_selectors(&self) -> usize {
623         self.cascade_data
624             .iter_origins()
625             .map(|(d, _)| d.num_selectors)
626             .sum()
627     }
628 
629     /// Returns the number of declarations.
num_declarations(&self) -> usize630     pub fn num_declarations(&self) -> usize {
631         self.cascade_data
632             .iter_origins()
633             .map(|(d, _)| d.num_declarations)
634             .sum()
635     }
636 
637     /// Returns the number of times the stylist has been rebuilt.
num_rebuilds(&self) -> usize638     pub fn num_rebuilds(&self) -> usize {
639         self.num_rebuilds
640     }
641 
642     /// Returns the number of revalidation_selectors.
num_revalidation_selectors(&self) -> usize643     pub fn num_revalidation_selectors(&self) -> usize {
644         self.cascade_data
645             .iter_origins()
646             .map(|(data, _)| data.selectors_for_cache_revalidation.len())
647             .sum()
648     }
649 
650     /// Returns the number of entries in invalidation maps.
num_invalidations(&self) -> usize651     pub fn num_invalidations(&self) -> usize {
652         self.cascade_data
653             .iter_origins()
654             .map(|(data, _)| data.invalidation_map.len())
655             .sum()
656     }
657 
658     /// Returns whether the given DocumentState bit is relied upon by a selector
659     /// of some rule.
has_document_state_dependency(&self, state: DocumentState) -> bool660     pub fn has_document_state_dependency(&self, state: DocumentState) -> bool {
661         self.cascade_data
662             .iter_origins()
663             .any(|(d, _)| d.document_state_dependencies.intersects(state))
664     }
665 
666     /// Flush the list of stylesheets if they changed, ensuring the stylist is
667     /// up-to-date.
flush<E>( &mut self, guards: &StylesheetGuards, document_element: Option<E>, snapshots: Option<&SnapshotMap>, ) -> bool where E: TElement,668     pub fn flush<E>(
669         &mut self,
670         guards: &StylesheetGuards,
671         document_element: Option<E>,
672         snapshots: Option<&SnapshotMap>,
673     ) -> bool
674     where
675         E: TElement,
676     {
677         if !self.stylesheets.has_changed() {
678             return false;
679         }
680 
681         self.num_rebuilds += 1;
682 
683         // Update viewport_constraints regardless of which origins'
684         // `CascadeData` we're updating.
685         self.viewport_constraints = None;
686         if viewport_rule::enabled() {
687             // TODO(emilio): This doesn't look so efficient.
688             //
689             // Presumably when we properly implement this we can at least have a
690             // bit on the stylesheet that says whether it contains viewport
691             // rules to skip it entirely?
692             //
693             // Processing it with the rest of rules seems tricky since it
694             // overrides the viewport size which may change the evaluation of
695             // media queries (or may not? how are viewport units in media
696             // queries defined?)
697             let cascaded_rule = ViewportRule {
698                 declarations: viewport_rule::Cascade::from_stylesheets(
699                     self.stylesheets.iter(),
700                     guards,
701                     &self.device,
702                 )
703                 .finish(),
704             };
705 
706             self.viewport_constraints =
707                 ViewportConstraints::maybe_new(&self.device, &cascaded_rule, self.quirks_mode);
708 
709             if let Some(ref constraints) = self.viewport_constraints {
710                 self.device.account_for_viewport_rule(constraints);
711             }
712         }
713 
714         let flusher = self.stylesheets.flush(document_element, snapshots);
715 
716         let had_invalidations = flusher.had_invalidations();
717 
718         self.cascade_data
719             .rebuild(&self.device, self.quirks_mode, flusher, guards)
720             .unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
721 
722         had_invalidations
723     }
724 
725     /// Insert a given stylesheet before another stylesheet in the document.
insert_stylesheet_before( &mut self, sheet: StylistSheet, before_sheet: StylistSheet, guard: &SharedRwLockReadGuard, )726     pub fn insert_stylesheet_before(
727         &mut self,
728         sheet: StylistSheet,
729         before_sheet: StylistSheet,
730         guard: &SharedRwLockReadGuard,
731     ) {
732         self.stylesheets
733             .insert_stylesheet_before(Some(&self.device), sheet, before_sheet, guard)
734     }
735 
736     /// Marks a given stylesheet origin as dirty, due to, for example, changes
737     /// in the declarations that affect a given rule.
738     ///
739     /// FIXME(emilio): Eventually it'd be nice for this to become more
740     /// fine-grained.
force_stylesheet_origins_dirty(&mut self, origins: OriginSet)741     pub fn force_stylesheet_origins_dirty(&mut self, origins: OriginSet) {
742         self.stylesheets.force_dirty(origins)
743     }
744 
745     /// Sets whether author style is enabled or not.
set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled)746     pub fn set_author_styles_enabled(&mut self, enabled: AuthorStylesEnabled) {
747         self.author_styles_enabled = enabled;
748     }
749 
750     /// Returns whether we've recorded any stylesheet change so far.
stylesheets_have_changed(&self) -> bool751     pub fn stylesheets_have_changed(&self) -> bool {
752         self.stylesheets.has_changed()
753     }
754 
755     /// Appends a new stylesheet to the current set.
append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard)756     pub fn append_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
757         self.stylesheets
758             .append_stylesheet(Some(&self.device), sheet, guard)
759     }
760 
761     /// Remove a given stylesheet to the current set.
remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard)762     pub fn remove_stylesheet(&mut self, sheet: StylistSheet, guard: &SharedRwLockReadGuard) {
763         self.stylesheets
764             .remove_stylesheet(Some(&self.device), sheet, guard)
765     }
766 
767     /// Notify of a change of a given rule.
rule_changed( &mut self, sheet: &StylistSheet, rule: &CssRule, guard: &SharedRwLockReadGuard, change_kind: RuleChangeKind, )768     pub fn rule_changed(
769         &mut self,
770         sheet: &StylistSheet,
771         rule: &CssRule,
772         guard: &SharedRwLockReadGuard,
773         change_kind: RuleChangeKind,
774     ) {
775         self.stylesheets
776             .rule_changed(Some(&self.device), sheet, rule, guard, change_kind)
777     }
778 
779     /// Appends a new stylesheet to the current set.
780     #[inline]
sheet_count(&self, origin: Origin) -> usize781     pub fn sheet_count(&self, origin: Origin) -> usize {
782         self.stylesheets.sheet_count(origin)
783     }
784 
785     /// Appends a new stylesheet to the current set.
786     #[inline]
sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet>787     pub fn sheet_at(&self, origin: Origin, index: usize) -> Option<&StylistSheet> {
788         self.stylesheets.get(origin, index)
789     }
790 
791     /// Returns whether for any of the applicable style rule data a given
792     /// condition is true.
any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool where E: TElement, F: FnMut(&CascadeData) -> bool,793     pub fn any_applicable_rule_data<E, F>(&self, element: E, mut f: F) -> bool
794     where
795         E: TElement,
796         F: FnMut(&CascadeData) -> bool,
797     {
798         if f(&self.cascade_data.user_agent.cascade_data) {
799             return true;
800         }
801 
802         let mut maybe = false;
803 
804         let doc_author_rules_apply =
805             element.each_applicable_non_document_style_rule_data(|data, _| {
806                 maybe = maybe || f(&*data);
807             });
808 
809         if maybe || f(&self.cascade_data.user) {
810             return true;
811         }
812 
813         doc_author_rules_apply && f(&self.cascade_data.author)
814     }
815 
816     /// Computes the style for a given "precomputed" pseudo-element, taking the
817     /// universal rules and applying them.
precomputed_values_for_pseudo<E>( &self, guards: &StylesheetGuards, pseudo: &PseudoElement, parent: Option<&ComputedValues>, font_metrics: &dyn FontMetricsProvider, ) -> Arc<ComputedValues> where E: TElement,818     pub fn precomputed_values_for_pseudo<E>(
819         &self,
820         guards: &StylesheetGuards,
821         pseudo: &PseudoElement,
822         parent: Option<&ComputedValues>,
823         font_metrics: &dyn FontMetricsProvider,
824     ) -> Arc<ComputedValues>
825     where
826         E: TElement,
827     {
828         debug_assert!(pseudo.is_precomputed());
829 
830         let rule_node = self.rule_node_for_precomputed_pseudo(guards, pseudo, vec![]);
831 
832         self.precomputed_values_for_pseudo_with_rule_node::<E>(
833             guards,
834             pseudo,
835             parent,
836             font_metrics,
837             rule_node,
838         )
839     }
840 
841     /// Computes the style for a given "precomputed" pseudo-element with
842     /// given rule node.
843     ///
844     /// TODO(emilio): The type parameter could go away with a void type
845     /// implementing TElement.
precomputed_values_for_pseudo_with_rule_node<E>( &self, guards: &StylesheetGuards, pseudo: &PseudoElement, parent: Option<&ComputedValues>, font_metrics: &dyn FontMetricsProvider, rules: StrongRuleNode, ) -> Arc<ComputedValues> where E: TElement,846     pub fn precomputed_values_for_pseudo_with_rule_node<E>(
847         &self,
848         guards: &StylesheetGuards,
849         pseudo: &PseudoElement,
850         parent: Option<&ComputedValues>,
851         font_metrics: &dyn FontMetricsProvider,
852         rules: StrongRuleNode,
853     ) -> Arc<ComputedValues>
854     where
855         E: TElement,
856     {
857         self.compute_pseudo_element_style_with_inputs::<E>(
858             CascadeInputs {
859                 rules: Some(rules),
860                 visited_rules: None,
861             },
862             pseudo,
863             guards,
864             parent,
865             font_metrics,
866             None,
867         )
868     }
869 
870     /// Returns the rule node for a given precomputed pseudo-element.
871     ///
872     /// If we want to include extra declarations to this precomputed
873     /// pseudo-element, we can provide a vector of ApplicableDeclarationBlocks
874     /// to extra_declarations. This is useful for @page rules.
rule_node_for_precomputed_pseudo( &self, guards: &StylesheetGuards, pseudo: &PseudoElement, mut extra_declarations: Vec<ApplicableDeclarationBlock>, ) -> StrongRuleNode875     pub fn rule_node_for_precomputed_pseudo(
876         &self,
877         guards: &StylesheetGuards,
878         pseudo: &PseudoElement,
879         mut extra_declarations: Vec<ApplicableDeclarationBlock>,
880     ) -> StrongRuleNode {
881         let mut declarations_with_extra;
882         let declarations = match self
883             .cascade_data
884             .user_agent
885             .precomputed_pseudo_element_decls
886             .get(pseudo)
887         {
888             Some(declarations) => {
889                 if !extra_declarations.is_empty() {
890                     declarations_with_extra = declarations.clone();
891                     declarations_with_extra.append(&mut extra_declarations);
892                     &*declarations_with_extra
893                 } else {
894                     &**declarations
895                 }
896             },
897             None => &[],
898         };
899 
900         self.rule_tree.insert_ordered_rules_with_important(
901             declarations.into_iter().map(|a| a.clone().for_rule_tree()),
902             guards,
903         )
904     }
905 
906     /// Returns the style for an anonymous box of the given type.
907     ///
908     /// TODO(emilio): The type parameter could go away with a void type
909     /// implementing TElement.
910     #[cfg(feature = "servo")]
style_for_anonymous<E>( &self, guards: &StylesheetGuards, pseudo: &PseudoElement, parent_style: &ComputedValues, ) -> Arc<ComputedValues> where E: TElement,911     pub fn style_for_anonymous<E>(
912         &self,
913         guards: &StylesheetGuards,
914         pseudo: &PseudoElement,
915         parent_style: &ComputedValues,
916     ) -> Arc<ComputedValues>
917     where
918         E: TElement,
919     {
920         use crate::font_metrics::ServoMetricsProvider;
921         self.precomputed_values_for_pseudo::<E>(
922             guards,
923             &pseudo,
924             Some(parent_style),
925             &ServoMetricsProvider,
926         )
927     }
928 
929     /// Computes a pseudo-element style lazily during layout.
930     ///
931     /// This can only be done for a certain set of pseudo-elements, like
932     /// :selection.
933     ///
934     /// Check the documentation on lazy pseudo-elements in
935     /// docs/components/style.md
lazily_compute_pseudo_element_style<E>( &self, guards: &StylesheetGuards, element: E, pseudo: &PseudoElement, rule_inclusion: RuleInclusion, parent_style: &ComputedValues, is_probe: bool, font_metrics: &dyn FontMetricsProvider, matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>, ) -> Option<Arc<ComputedValues>> where E: TElement,936     pub fn lazily_compute_pseudo_element_style<E>(
937         &self,
938         guards: &StylesheetGuards,
939         element: E,
940         pseudo: &PseudoElement,
941         rule_inclusion: RuleInclusion,
942         parent_style: &ComputedValues,
943         is_probe: bool,
944         font_metrics: &dyn FontMetricsProvider,
945         matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
946     ) -> Option<Arc<ComputedValues>>
947     where
948         E: TElement,
949     {
950         let cascade_inputs = self.lazy_pseudo_rules(
951             guards,
952             element,
953             parent_style,
954             pseudo,
955             is_probe,
956             rule_inclusion,
957             matching_fn,
958         )?;
959 
960         Some(self.compute_pseudo_element_style_with_inputs(
961             cascade_inputs,
962             pseudo,
963             guards,
964             Some(parent_style),
965             font_metrics,
966             Some(element),
967         ))
968     }
969 
970     /// Computes a pseudo-element style lazily using the given CascadeInputs.
971     /// This can be used for truly lazy pseudo-elements or to avoid redoing
972     /// selector matching for eager pseudo-elements when we need to recompute
973     /// their style with a new parent style.
compute_pseudo_element_style_with_inputs<E>( &self, inputs: CascadeInputs, pseudo: &PseudoElement, guards: &StylesheetGuards, parent_style: Option<&ComputedValues>, font_metrics: &dyn FontMetricsProvider, element: Option<E>, ) -> Arc<ComputedValues> where E: TElement,974     pub fn compute_pseudo_element_style_with_inputs<E>(
975         &self,
976         inputs: CascadeInputs,
977         pseudo: &PseudoElement,
978         guards: &StylesheetGuards,
979         parent_style: Option<&ComputedValues>,
980         font_metrics: &dyn FontMetricsProvider,
981         element: Option<E>,
982     ) -> Arc<ComputedValues>
983     where
984         E: TElement,
985     {
986         // FIXME(emilio): The lack of layout_parent_style here could be
987         // worrying, but we're probably dropping the display fixup for
988         // pseudos other than before and after, so it's probably ok.
989         //
990         // (Though the flags don't indicate so!)
991         //
992         // It'd be fine to assert that this isn't called with a parent style
993         // where display contents is in effect, but in practice this is hard to
994         // do for stuff like :-moz-fieldset-content with a
995         // <fieldset style="display: contents">. That is, the computed value of
996         // display for the fieldset is "contents", even though it's not the used
997         // value, so we don't need to adjust in a different way anyway.
998         self.cascade_style_and_visited(
999             element,
1000             Some(pseudo),
1001             inputs,
1002             guards,
1003             parent_style,
1004             parent_style,
1005             parent_style,
1006             font_metrics,
1007             /* rule_cache = */ None,
1008             &mut RuleCacheConditions::default(),
1009         )
1010     }
1011 
1012     /// Computes a style using the given CascadeInputs.  This can be used to
1013     /// compute a style any time we know what rules apply and just need to use
1014     /// the given parent styles.
1015     ///
1016     /// parent_style is the style to inherit from for properties affected by
1017     /// first-line ancestors.
1018     ///
1019     /// parent_style_ignoring_first_line is the style to inherit from for
1020     /// properties not affected by first-line ancestors.
1021     ///
1022     /// layout_parent_style is the style used for some property fixups.  It's
1023     /// the style of the nearest ancestor with a layout box.
cascade_style_and_visited<E>( &self, element: Option<E>, pseudo: Option<&PseudoElement>, inputs: CascadeInputs, guards: &StylesheetGuards, parent_style: Option<&ComputedValues>, parent_style_ignoring_first_line: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, font_metrics: &dyn FontMetricsProvider, rule_cache: Option<&RuleCache>, rule_cache_conditions: &mut RuleCacheConditions, ) -> Arc<ComputedValues> where E: TElement,1024     pub fn cascade_style_and_visited<E>(
1025         &self,
1026         element: Option<E>,
1027         pseudo: Option<&PseudoElement>,
1028         inputs: CascadeInputs,
1029         guards: &StylesheetGuards,
1030         parent_style: Option<&ComputedValues>,
1031         parent_style_ignoring_first_line: Option<&ComputedValues>,
1032         layout_parent_style: Option<&ComputedValues>,
1033         font_metrics: &dyn FontMetricsProvider,
1034         rule_cache: Option<&RuleCache>,
1035         rule_cache_conditions: &mut RuleCacheConditions,
1036     ) -> Arc<ComputedValues>
1037     where
1038         E: TElement,
1039     {
1040         debug_assert!(pseudo.is_some() || element.is_some(), "Huh?");
1041 
1042         // We need to compute visited values if we have visited rules or if our
1043         // parent has visited values.
1044         let visited_rules = match inputs.visited_rules.as_ref() {
1045             Some(rules) => Some(rules),
1046             None => {
1047                 if parent_style.and_then(|s| s.visited_style()).is_some() {
1048                     Some(inputs.rules.as_ref().unwrap_or(self.rule_tree.root()))
1049                 } else {
1050                     None
1051                 }
1052             },
1053         };
1054 
1055         // Read the comment on `precomputed_values_for_pseudo` to see why it's
1056         // difficult to assert that display: contents nodes never arrive here
1057         // (tl;dr: It doesn't apply for replaced elements and such, but the
1058         // computed value is still "contents").
1059         //
1060         // FIXME(emilio): We should assert that it holds if pseudo.is_none()!
1061         properties::cascade::<E>(
1062             &self.device,
1063             pseudo,
1064             inputs.rules.as_ref().unwrap_or(self.rule_tree.root()),
1065             guards,
1066             parent_style,
1067             parent_style_ignoring_first_line,
1068             layout_parent_style,
1069             visited_rules,
1070             font_metrics,
1071             self.quirks_mode,
1072             rule_cache,
1073             rule_cache_conditions,
1074             element,
1075         )
1076     }
1077 
1078     /// Computes the cascade inputs for a lazily-cascaded pseudo-element.
1079     ///
1080     /// See the documentation on lazy pseudo-elements in
1081     /// docs/components/style.md
lazy_pseudo_rules<E>( &self, guards: &StylesheetGuards, element: E, parent_style: &ComputedValues, pseudo: &PseudoElement, is_probe: bool, rule_inclusion: RuleInclusion, matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>, ) -> Option<CascadeInputs> where E: TElement,1082     fn lazy_pseudo_rules<E>(
1083         &self,
1084         guards: &StylesheetGuards,
1085         element: E,
1086         parent_style: &ComputedValues,
1087         pseudo: &PseudoElement,
1088         is_probe: bool,
1089         rule_inclusion: RuleInclusion,
1090         matching_fn: Option<&dyn Fn(&PseudoElement) -> bool>,
1091     ) -> Option<CascadeInputs>
1092     where
1093         E: TElement,
1094     {
1095         debug_assert!(pseudo.is_lazy());
1096 
1097         // Apply the selector flags. We should be in sequential mode
1098         // already, so we can directly apply the parent flags.
1099         let mut set_selector_flags = |element: &E, flags: ElementSelectorFlags| {
1100             if cfg!(feature = "servo") {
1101                 // Servo calls this function from the worker, but only for internal
1102                 // pseudos, so we should never generate selector flags here.
1103                 unreachable!("internal pseudo generated slow selector flags?");
1104             }
1105 
1106             // No need to bother setting the selector flags when we're computing
1107             // default styles.
1108             if rule_inclusion == RuleInclusion::DefaultOnly {
1109                 return;
1110             }
1111 
1112             // Gecko calls this from sequential mode, so we can directly apply
1113             // the flags.
1114             debug_assert_eq!(thread_state::get(), ThreadState::LAYOUT);
1115             let self_flags = flags.for_self();
1116             if !self_flags.is_empty() {
1117                 unsafe {
1118                     element.set_selector_flags(self_flags);
1119                 }
1120             }
1121             let parent_flags = flags.for_parent();
1122             if !parent_flags.is_empty() {
1123                 if let Some(p) = element.parent_element() {
1124                     unsafe {
1125                         p.set_selector_flags(parent_flags);
1126                     }
1127                 }
1128             }
1129         };
1130 
1131         let mut declarations = ApplicableDeclarationList::new();
1132         let mut matching_context = MatchingContext::new(
1133             MatchingMode::ForStatelessPseudoElement,
1134             None,
1135             None,
1136             self.quirks_mode,
1137         );
1138 
1139         matching_context.pseudo_element_matching_fn = matching_fn;
1140 
1141         self.push_applicable_declarations(
1142             element,
1143             Some(&pseudo),
1144             None,
1145             None,
1146             /* animation_declarations = */ Default::default(),
1147             rule_inclusion,
1148             &mut declarations,
1149             &mut matching_context,
1150             &mut set_selector_flags,
1151         );
1152 
1153         if declarations.is_empty() && is_probe {
1154             return None;
1155         }
1156 
1157         let rules = self.rule_tree.compute_rule_node(&mut declarations, guards);
1158 
1159         let mut visited_rules = None;
1160         if parent_style.visited_style().is_some() {
1161             let mut declarations = ApplicableDeclarationList::new();
1162             let mut matching_context = MatchingContext::new_for_visited(
1163                 MatchingMode::ForStatelessPseudoElement,
1164                 None,
1165                 None,
1166                 VisitedHandlingMode::RelevantLinkVisited,
1167                 self.quirks_mode,
1168             );
1169             matching_context.pseudo_element_matching_fn = matching_fn;
1170 
1171             self.push_applicable_declarations(
1172                 element,
1173                 Some(&pseudo),
1174                 None,
1175                 None,
1176                 /* animation_declarations = */ Default::default(),
1177                 rule_inclusion,
1178                 &mut declarations,
1179                 &mut matching_context,
1180                 &mut set_selector_flags,
1181             );
1182             if !declarations.is_empty() {
1183                 let rule_node = self.rule_tree.insert_ordered_rules_with_important(
1184                     declarations.drain(..).map(|a| a.for_rule_tree()),
1185                     guards,
1186                 );
1187                 if rule_node != *self.rule_tree.root() {
1188                     visited_rules = Some(rule_node);
1189                 }
1190             }
1191         }
1192 
1193         Some(CascadeInputs {
1194             rules: Some(rules),
1195             visited_rules,
1196         })
1197     }
1198 
1199     /// Set a given device, which may change the styles that apply to the
1200     /// document.
1201     ///
1202     /// Returns the sheet origins that were actually affected.
1203     ///
1204     /// This means that we may need to rebuild style data even if the
1205     /// stylesheets haven't changed.
1206     ///
1207     /// Also, the device that arrives here may need to take the viewport rules
1208     /// into account.
set_device(&mut self, mut device: Device, guards: &StylesheetGuards) -> OriginSet1209     pub fn set_device(&mut self, mut device: Device, guards: &StylesheetGuards) -> OriginSet {
1210         if viewport_rule::enabled() {
1211             let cascaded_rule = {
1212                 let stylesheets = self.stylesheets.iter();
1213 
1214                 ViewportRule {
1215                     declarations: viewport_rule::Cascade::from_stylesheets(
1216                         stylesheets,
1217                         guards,
1218                         &device,
1219                     )
1220                     .finish(),
1221                 }
1222             };
1223 
1224             self.viewport_constraints =
1225                 ViewportConstraints::maybe_new(&device, &cascaded_rule, self.quirks_mode);
1226 
1227             if let Some(ref constraints) = self.viewport_constraints {
1228                 device.account_for_viewport_rule(constraints);
1229             }
1230         }
1231 
1232         self.device = device;
1233         self.media_features_change_changed_style(guards, &self.device)
1234     }
1235 
1236     /// Returns whether, given a media feature change, any previously-applicable
1237     /// style has become non-applicable, or vice-versa for each origin, using
1238     /// `device`.
media_features_change_changed_style( &self, guards: &StylesheetGuards, device: &Device, ) -> OriginSet1239     pub fn media_features_change_changed_style(
1240         &self,
1241         guards: &StylesheetGuards,
1242         device: &Device,
1243     ) -> OriginSet {
1244         debug!("Stylist::media_features_change_changed_style {:?}", device);
1245 
1246         let mut origins = OriginSet::empty();
1247         let stylesheets = self.stylesheets.iter();
1248 
1249         for (stylesheet, origin) in stylesheets {
1250             if origins.contains(origin.into()) {
1251                 continue;
1252             }
1253 
1254             let guard = guards.for_origin(origin);
1255             let origin_cascade_data = self.cascade_data.borrow_for_origin(origin);
1256 
1257             let affected_changed = !origin_cascade_data.media_feature_affected_matches(
1258                 stylesheet,
1259                 guard,
1260                 device,
1261                 self.quirks_mode,
1262             );
1263 
1264             if affected_changed {
1265                 origins |= origin;
1266             }
1267         }
1268 
1269         origins
1270     }
1271 
1272     /// Returns the viewport constraints that apply to this document because of
1273     /// a @viewport rule.
viewport_constraints(&self) -> Option<&ViewportConstraints>1274     pub fn viewport_constraints(&self) -> Option<&ViewportConstraints> {
1275         self.viewport_constraints.as_ref()
1276     }
1277 
1278     /// Returns the Quirks Mode of the document.
quirks_mode(&self) -> QuirksMode1279     pub fn quirks_mode(&self) -> QuirksMode {
1280         self.quirks_mode
1281     }
1282 
1283     /// Sets the quirks mode of the document.
set_quirks_mode(&mut self, quirks_mode: QuirksMode)1284     pub fn set_quirks_mode(&mut self, quirks_mode: QuirksMode) {
1285         if self.quirks_mode == quirks_mode {
1286             return;
1287         }
1288         self.quirks_mode = quirks_mode;
1289         self.force_stylesheet_origins_dirty(OriginSet::all());
1290     }
1291 
1292     /// Returns the applicable CSS declarations for the given element.
push_applicable_declarations<E, F>( &self, element: E, pseudo_element: Option<&PseudoElement>, style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>, smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>, animation_declarations: AnimationDeclarations, rule_inclusion: RuleInclusion, applicable_declarations: &mut ApplicableDeclarationList, context: &mut MatchingContext<E::Impl>, flags_setter: &mut F, ) where E: TElement, F: FnMut(&E, ElementSelectorFlags),1293     pub fn push_applicable_declarations<E, F>(
1294         &self,
1295         element: E,
1296         pseudo_element: Option<&PseudoElement>,
1297         style_attribute: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1298         smil_override: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
1299         animation_declarations: AnimationDeclarations,
1300         rule_inclusion: RuleInclusion,
1301         applicable_declarations: &mut ApplicableDeclarationList,
1302         context: &mut MatchingContext<E::Impl>,
1303         flags_setter: &mut F,
1304     ) where
1305         E: TElement,
1306         F: FnMut(&E, ElementSelectorFlags),
1307     {
1308         RuleCollector::new(
1309             self,
1310             element,
1311             pseudo_element,
1312             style_attribute,
1313             smil_override,
1314             animation_declarations,
1315             rule_inclusion,
1316             applicable_declarations,
1317             context,
1318             flags_setter,
1319         )
1320         .collect_all();
1321     }
1322 
1323     /// Given an id, returns whether there might be any rules for that id in any
1324     /// of our rule maps.
1325     #[inline]
may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool where E: TElement,1326     pub fn may_have_rules_for_id<E>(&self, id: &WeakAtom, element: E) -> bool
1327     where
1328         E: TElement,
1329     {
1330         // If id needs to be compared case-insensitively, the logic below
1331         // wouldn't work. Just conservatively assume it may have such rules.
1332         match self.quirks_mode().classes_and_ids_case_sensitivity() {
1333             CaseSensitivity::AsciiCaseInsensitive => return true,
1334             CaseSensitivity::CaseSensitive => {},
1335         }
1336 
1337         self.any_applicable_rule_data(element, |data| data.mapped_ids.contains(id))
1338     }
1339 
1340     /// Returns the registered `@keyframes` animation for the specified name.
1341     #[inline]
get_animation<'a, E>(&'a self, name: &Atom, element: E) -> Option<&'a KeyframesAnimation> where E: TElement + 'a,1342     pub fn get_animation<'a, E>(&'a self, name: &Atom, element: E) -> Option<&'a KeyframesAnimation>
1343     where
1344         E: TElement + 'a,
1345     {
1346         macro_rules! try_find_in {
1347             ($data:expr) => {
1348                 if let Some(animation) = $data.animations.get(name) {
1349                     return Some(animation);
1350                 }
1351             };
1352         }
1353 
1354         // NOTE(emilio): We implement basically what Blink does for this case,
1355         // which is [1] as of this writing.
1356         //
1357         // See [2] for the spec discussion about what to do about this. WebKit's
1358         // behavior makes a bit more sense off-hand, but it's way more complex
1359         // to implement, and it makes value computation having to thread around
1360         // the cascade level, which is not great. Also, it breaks if you inherit
1361         // animation-name from an element in a different tree.
1362         //
1363         // See [3] for the bug to implement whatever gets resolved, and related
1364         // bugs for a bit more context.
1365         //
1366         // FIXME(emilio): This should probably work for pseudo-elements (i.e.,
1367         // use rule_hash_target().shadow_root() instead of
1368         // element.shadow_root()).
1369         //
1370         // [1]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/
1371         //        core/css/resolver/style_resolver.cc?l=1267&rcl=90f9f8680ebb4a87d177f3b0833372ae4e0c88d8
1372         // [2]: https://github.com/w3c/csswg-drafts/issues/1995
1373         // [3]: https://bugzil.la/1458189
1374         if let Some(shadow) = element.shadow_root() {
1375             if let Some(data) = shadow.style_data() {
1376                 try_find_in!(data);
1377             }
1378         }
1379 
1380         // Use the same rules to look for the containing host as we do for rule
1381         // collection.
1382         if let Some(shadow) = containing_shadow_ignoring_svg_use(element) {
1383             if let Some(data) = shadow.style_data() {
1384                 try_find_in!(data);
1385             }
1386         } else {
1387             try_find_in!(self.cascade_data.author);
1388         }
1389 
1390         try_find_in!(self.cascade_data.user);
1391         try_find_in!(self.cascade_data.user_agent.cascade_data);
1392 
1393         None
1394     }
1395 
1396     /// Computes the match results of a given element against the set of
1397     /// revalidation selectors.
match_revalidation_selectors<E, F>( &self, element: E, bloom: Option<&BloomFilter>, nth_index_cache: &mut NthIndexCache, flags_setter: &mut F, ) -> SmallBitVec where E: TElement, F: FnMut(&E, ElementSelectorFlags),1398     pub fn match_revalidation_selectors<E, F>(
1399         &self,
1400         element: E,
1401         bloom: Option<&BloomFilter>,
1402         nth_index_cache: &mut NthIndexCache,
1403         flags_setter: &mut F,
1404     ) -> SmallBitVec
1405     where
1406         E: TElement,
1407         F: FnMut(&E, ElementSelectorFlags),
1408     {
1409         // NB: `MatchingMode` doesn't really matter, given we don't share style
1410         // between pseudos.
1411         let mut matching_context = MatchingContext::new(
1412             MatchingMode::Normal,
1413             bloom,
1414             Some(nth_index_cache),
1415             self.quirks_mode,
1416         );
1417 
1418         // Note that, by the time we're revalidating, we're guaranteed that the
1419         // candidate and the entry have the same id, classes, and local name.
1420         // This means we're guaranteed to get the same rulehash buckets for all
1421         // the lookups, which means that the bitvecs are comparable. We verify
1422         // this in the caller by asserting that the bitvecs are same-length.
1423         let mut results = SmallBitVec::new();
1424 
1425         let matches_document_rules =
1426             element.each_applicable_non_document_style_rule_data(|data, host| {
1427                 matching_context.with_shadow_host(Some(host), |matching_context| {
1428                     data.selectors_for_cache_revalidation.lookup(
1429                         element,
1430                         self.quirks_mode,
1431                         |selector_and_hashes| {
1432                             results.push(matches_selector(
1433                                 &selector_and_hashes.selector,
1434                                 selector_and_hashes.selector_offset,
1435                                 Some(&selector_and_hashes.hashes),
1436                                 &element,
1437                                 matching_context,
1438                                 flags_setter,
1439                             ));
1440                             true
1441                         },
1442                     );
1443                 })
1444             });
1445 
1446         for (data, origin) in self.cascade_data.iter_origins() {
1447             if origin == Origin::Author && !matches_document_rules {
1448                 continue;
1449             }
1450 
1451             data.selectors_for_cache_revalidation.lookup(
1452                 element,
1453                 self.quirks_mode,
1454                 |selector_and_hashes| {
1455                     results.push(matches_selector(
1456                         &selector_and_hashes.selector,
1457                         selector_and_hashes.selector_offset,
1458                         Some(&selector_and_hashes.hashes),
1459                         &element,
1460                         &mut matching_context,
1461                         flags_setter,
1462                     ));
1463                     true
1464                 },
1465             );
1466         }
1467 
1468         results
1469     }
1470 
1471     /// Computes styles for a given declaration with parent_style.
1472     ///
1473     /// FIXME(emilio): the lack of pseudo / cascade flags look quite dubious,
1474     /// hopefully this is only used for some canvas font stuff.
1475     ///
1476     /// TODO(emilio): The type parameter can go away when
1477     /// https://github.com/rust-lang/rust/issues/35121 is fixed.
compute_for_declarations<E>( &self, guards: &StylesheetGuards, parent_style: &ComputedValues, declarations: Arc<Locked<PropertyDeclarationBlock>>, ) -> Arc<ComputedValues> where E: TElement,1478     pub fn compute_for_declarations<E>(
1479         &self,
1480         guards: &StylesheetGuards,
1481         parent_style: &ComputedValues,
1482         declarations: Arc<Locked<PropertyDeclarationBlock>>,
1483     ) -> Arc<ComputedValues>
1484     where
1485         E: TElement,
1486     {
1487         use crate::font_metrics::get_metrics_provider_for_product;
1488 
1489         let block = declarations.read_with(guards.author);
1490         let metrics = get_metrics_provider_for_product();
1491 
1492         // We don't bother inserting these declarations in the rule tree, since
1493         // it'd be quite useless and slow.
1494         //
1495         // TODO(emilio): Now that we fixed bug 1493420, we should consider
1496         // reversing this as it shouldn't be slow anymore, and should avoid
1497         // generating two instantiations of apply_declarations.
1498         properties::apply_declarations::<E, _>(
1499             &self.device,
1500             /* pseudo = */ None,
1501             self.rule_tree.root(),
1502             guards,
1503             block.declaration_importance_iter().map(|(declaration, _)| {
1504                 (
1505                     declaration,
1506                     CascadePriority::new(
1507                         CascadeLevel::same_tree_author_normal(),
1508                         LayerOrder::root(),
1509                     ),
1510                 )
1511             }),
1512             Some(parent_style),
1513             Some(parent_style),
1514             Some(parent_style),
1515             &metrics,
1516             CascadeMode::Unvisited {
1517                 visited_rules: None,
1518             },
1519             self.quirks_mode,
1520             /* rule_cache = */ None,
1521             &mut Default::default(),
1522             /* element = */ None,
1523         )
1524     }
1525 
1526     /// Accessor for a shared reference to the device.
1527     #[inline]
device(&self) -> &Device1528     pub fn device(&self) -> &Device {
1529         &self.device
1530     }
1531 
1532     /// Accessor for a mutable reference to the device.
1533     #[inline]
device_mut(&mut self) -> &mut Device1534     pub fn device_mut(&mut self) -> &mut Device {
1535         &mut self.device
1536     }
1537 
1538     /// Accessor for a shared reference to the rule tree.
1539     #[inline]
rule_tree(&self) -> &RuleTree1540     pub fn rule_tree(&self) -> &RuleTree {
1541         &self.rule_tree
1542     }
1543 
1544     /// Measures heap usage.
1545     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)1546     pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
1547         self.cascade_data.add_size_of(ops, sizes);
1548         self.author_data_cache.add_size_of(ops, sizes);
1549         sizes.mRuleTree += self.rule_tree.size_of(ops);
1550 
1551         // We may measure other fields in the future if DMD says it's worth it.
1552     }
1553 
1554     /// Shutdown the static data that this module stores.
shutdown()1555     pub fn shutdown() {
1556         let _entries = UA_CASCADE_DATA_CACHE.lock().unwrap().take_all();
1557     }
1558 }
1559 
1560 /// A vector that is sorted in layer order.
1561 #[derive(Clone, Debug, Deref, MallocSizeOf)]
1562 pub struct LayerOrderedVec<T>(Vec<(T, LayerId)>);
1563 impl<T> Default for LayerOrderedVec<T> {
default() -> Self1564     fn default() -> Self {
1565         Self(Default::default())
1566     }
1567 }
1568 
1569 /// A map that is sorted in layer order.
1570 #[derive(Clone, Debug, Deref, MallocSizeOf)]
1571 pub struct LayerOrderedMap<T>(PrecomputedHashMap<Atom, SmallVec<[(T, LayerId); 1]>>);
1572 impl<T> Default for LayerOrderedMap<T> {
default() -> Self1573     fn default() -> Self {
1574         Self(Default::default())
1575     }
1576 }
1577 
1578 impl<T: 'static> LayerOrderedVec<T> {
clear(&mut self)1579     fn clear(&mut self) {
1580         self.0.clear();
1581     }
push(&mut self, v: T, id: LayerId)1582     fn push(&mut self, v: T, id: LayerId) {
1583         self.0.push((v, id));
1584     }
sort(&mut self, layers: &[CascadeLayer])1585     fn sort(&mut self, layers: &[CascadeLayer]) {
1586         self.0
1587             .sort_by_key(|&(_, ref id)| layers[id.0 as usize].order)
1588     }
1589 }
1590 
1591 impl<T: 'static> LayerOrderedMap<T> {
clear(&mut self)1592     fn clear(&mut self) {
1593         self.0.clear();
1594     }
try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr>1595     fn try_insert(&mut self, name: Atom, v: T, id: LayerId) -> Result<(), AllocErr> {
1596         self.try_insert_with(name, v, id, |_, _| Ordering::Equal)
1597     }
try_insert_with( &mut self, name: Atom, v: T, id: LayerId, cmp: impl Fn(&T, &T) -> Ordering, ) -> Result<(), AllocErr>1598     fn try_insert_with(
1599         &mut self,
1600         name: Atom,
1601         v: T,
1602         id: LayerId,
1603         cmp: impl Fn(&T, &T) -> Ordering,
1604     ) -> Result<(), AllocErr> {
1605         self.0.try_reserve(1)?;
1606         let vec = self.0.entry(name).or_default();
1607         if let Some(&mut (ref mut val, ref last_id)) = vec.last_mut() {
1608             if *last_id == id {
1609                 if cmp(&val, &v) != Ordering::Greater {
1610                     *val = v;
1611                 }
1612                 return Ok(());
1613             }
1614         }
1615         vec.push((v, id));
1616         Ok(())
1617     }
sort(&mut self, layers: &[CascadeLayer])1618     fn sort(&mut self, layers: &[CascadeLayer]) {
1619         self.sort_with(layers, |_, _| Ordering::Equal)
1620     }
sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering)1621     fn sort_with(&mut self, layers: &[CascadeLayer], cmp: impl Fn(&T, &T) -> Ordering) {
1622         for (_, v) in self.0.iter_mut() {
1623             v.sort_by(|&(ref v1, ref id1), &(ref v2, ref id2)| {
1624                 let order1 = layers[id1.0 as usize].order;
1625                 let order2 = layers[id2.0 as usize].order;
1626                 order1.cmp(&order2).then_with(|| cmp(v1, v2))
1627             })
1628         }
1629     }
1630     /// Get an entry on the LayerOrderedMap by name.
get(&self, name: &Atom) -> Option<&T>1631     pub fn get(&self, name: &Atom) -> Option<&T> {
1632         let vec = self.0.get(name)?;
1633         Some(&vec.last()?.0)
1634     }
1635 }
1636 
1637 /// Wrapper to allow better tracking of memory usage by page rule lists.
1638 ///
1639 /// This includes the layer ID for use with the named page table.
1640 #[derive(Clone, Debug, MallocSizeOf)]
1641 pub struct PageRuleData {
1642     /// Layer ID for sorting page rules after matching.
1643     pub layer: LayerId,
1644     /// Page rule
1645     #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
1646     pub rule: Arc<Locked<PageRule>>,
1647 }
1648 
1649 /// Wrapper to allow better tracking of memory usage by page rule lists.
1650 ///
1651 /// This is meant to be used by the global page rule list which are already
1652 /// sorted by layer ID, since all global page rules are less specific than all
1653 /// named page rules that match a certain page.
1654 #[derive(Clone, Debug, Deref, MallocSizeOf)]
1655 pub struct PageRuleDataNoLayer(
1656     #[ignore_malloc_size_of = "Arc, stylesheet measures as primary ref"]
1657     pub Arc<Locked<PageRule>>,
1658 );
1659 
1660 /// Stores page rules indexed by page names.
1661 #[derive(Clone, Debug, Default, MallocSizeOf)]
1662 pub struct PageRuleMap {
1663     /// Global, unnamed page rules.
1664     pub global: LayerOrderedVec<PageRuleDataNoLayer>,
1665     /// Named page rules
1666     pub named: PrecomputedHashMap<Atom, SmallVec<[PageRuleData; 1]>>,
1667 }
1668 
1669 impl PageRuleMap {
1670     #[inline]
clear(&mut self)1671     fn clear(&mut self) {
1672         self.global.clear();
1673         self.named.clear();
1674     }
1675 }
1676 
1677 impl MallocShallowSizeOf for PageRuleMap {
shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize1678     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1679         self.global.size_of(ops) + self.named.shallow_size_of(ops)
1680     }
1681 }
1682 
1683 /// This struct holds data which users of Stylist may want to extract
1684 /// from stylesheets which can be done at the same time as updating.
1685 #[derive(Clone, Debug, Default)]
1686 #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
1687 pub struct ExtraStyleData {
1688     /// A list of effective font-face rules and their origin.
1689     #[cfg(feature = "gecko")]
1690     pub font_faces: LayerOrderedVec<Arc<Locked<FontFaceRule>>>,
1691 
1692     /// A list of effective font-feature-values rules.
1693     #[cfg(feature = "gecko")]
1694     pub font_feature_values: LayerOrderedVec<Arc<Locked<FontFeatureValuesRule>>>,
1695 
1696     /// A map of effective counter-style rules.
1697     #[cfg(feature = "gecko")]
1698     pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>,
1699 
1700     /// A map of effective page rules.
1701     #[cfg(feature = "gecko")]
1702     pub pages: PageRuleMap,
1703 
1704     /// A map of effective scroll-timeline rules.
1705     #[cfg(feature = "gecko")]
1706     pub scroll_timelines: LayerOrderedMap<Arc<Locked<ScrollTimelineRule>>>,
1707 }
1708 
1709 #[cfg(feature = "gecko")]
1710 impl ExtraStyleData {
1711     /// Add the given @font-face rule.
add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId)1712     fn add_font_face(&mut self, rule: &Arc<Locked<FontFaceRule>>, layer: LayerId) {
1713         self.font_faces.push(rule.clone(), layer);
1714     }
1715 
1716     /// Add the given @font-feature-values rule.
add_font_feature_values( &mut self, rule: &Arc<Locked<FontFeatureValuesRule>>, layer: LayerId, )1717     fn add_font_feature_values(
1718         &mut self,
1719         rule: &Arc<Locked<FontFeatureValuesRule>>,
1720         layer: LayerId,
1721     ) {
1722         self.font_feature_values.push(rule.clone(), layer);
1723     }
1724 
1725     /// Add the given @counter-style rule.
add_counter_style( &mut self, guard: &SharedRwLockReadGuard, rule: &Arc<Locked<CounterStyleRule>>, layer: LayerId, ) -> Result<(), AllocErr>1726     fn add_counter_style(
1727         &mut self,
1728         guard: &SharedRwLockReadGuard,
1729         rule: &Arc<Locked<CounterStyleRule>>,
1730         layer: LayerId,
1731     ) -> Result<(), AllocErr> {
1732         let name = rule.read_with(guard).name().0.clone();
1733         self.counter_styles.try_insert(name, rule.clone(), layer)
1734     }
1735 
1736     /// Add the given @page rule.
add_page( &mut self, guard: &SharedRwLockReadGuard, rule: &Arc<Locked<PageRule>>, layer: LayerId, ) -> Result<(), AllocErr>1737     fn add_page(
1738         &mut self,
1739         guard: &SharedRwLockReadGuard,
1740         rule: &Arc<Locked<PageRule>>,
1741         layer: LayerId,
1742     ) -> Result<(), AllocErr> {
1743         let page_rule = rule.read_with(guard);
1744         if page_rule.selectors.0.is_empty() {
1745             self.pages.global.push(PageRuleDataNoLayer(rule.clone()), layer);
1746         } else {
1747             // TODO: Handle pseudo-classes
1748             self.pages.named.try_reserve(page_rule.selectors.0.len())?;
1749             for name in page_rule.selectors.as_slice() {
1750                 let vec = self.pages.named.entry(name.0.0.clone()).or_default();
1751                 vec.try_reserve(1)?;
1752                 vec.push(PageRuleData{layer, rule: rule.clone()});
1753             }
1754         }
1755         Ok(())
1756     }
1757 
1758     /// Add the given @scroll-timeline rule.
add_scroll_timeline( &mut self, guard: &SharedRwLockReadGuard, rule: &Arc<Locked<ScrollTimelineRule>>, layer: LayerId, ) -> Result<(), AllocErr>1759     fn add_scroll_timeline(
1760         &mut self,
1761         guard: &SharedRwLockReadGuard,
1762         rule: &Arc<Locked<ScrollTimelineRule>>,
1763         layer: LayerId,
1764     ) -> Result<(), AllocErr> {
1765         let name = rule.read_with(guard).name.as_atom().clone();
1766         self.scroll_timelines.try_insert(name, rule.clone(), layer)
1767     }
1768 
sort_by_layer(&mut self, layers: &[CascadeLayer])1769     fn sort_by_layer(&mut self, layers: &[CascadeLayer]) {
1770         self.font_faces.sort(layers);
1771         self.font_feature_values.sort(layers);
1772         self.counter_styles.sort(layers);
1773         self.pages.global.sort(layers);
1774         self.scroll_timelines.sort(layers);
1775     }
1776 
clear(&mut self)1777     fn clear(&mut self) {
1778         #[cfg(feature = "gecko")]
1779         {
1780             self.font_faces.clear();
1781             self.font_feature_values.clear();
1782             self.counter_styles.clear();
1783             self.pages.clear();
1784             self.scroll_timelines.clear();
1785         }
1786     }
1787 }
1788 
1789 // Don't let a prefixed keyframes animation override
1790 // a non-prefixed one.
compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering1791 fn compare_keyframes_in_same_layer(v1: &KeyframesAnimation, v2: &KeyframesAnimation) -> Ordering {
1792     if v1.vendor_prefix.is_some() == v2.vendor_prefix.is_some() {
1793         Ordering::Equal
1794     } else if v2.vendor_prefix.is_some() {
1795         Ordering::Greater
1796     } else {
1797         Ordering::Less
1798     }
1799 }
1800 
1801 /// An iterator over the different ExtraStyleData.
1802 pub struct ExtraStyleDataIterator<'a>(DocumentCascadeDataIter<'a>);
1803 
1804 impl<'a> Iterator for ExtraStyleDataIterator<'a> {
1805     type Item = (&'a ExtraStyleData, Origin);
1806 
next(&mut self) -> Option<Self::Item>1807     fn next(&mut self) -> Option<Self::Item> {
1808         self.0.next().map(|d| (&d.0.extra_data, d.1))
1809     }
1810 }
1811 
1812 #[cfg(feature = "gecko")]
1813 impl MallocSizeOf for ExtraStyleData {
1814     /// Measure heap usage.
size_of(&self, ops: &mut MallocSizeOfOps) -> usize1815     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1816         let mut n = 0;
1817         n += self.font_faces.shallow_size_of(ops);
1818         n += self.font_feature_values.shallow_size_of(ops);
1819         n += self.counter_styles.shallow_size_of(ops);
1820         n += self.pages.shallow_size_of(ops);
1821         n += self.scroll_timelines.shallow_size_of(ops);
1822         n
1823     }
1824 }
1825 
1826 /// SelectorMapEntry implementation for use in our revalidation selector map.
1827 #[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
1828 #[derive(Clone, Debug)]
1829 struct RevalidationSelectorAndHashes {
1830     #[cfg_attr(
1831         feature = "gecko",
1832         ignore_malloc_size_of = "CssRules have primary refs, we measure there"
1833     )]
1834     selector: Selector<SelectorImpl>,
1835     selector_offset: usize,
1836     hashes: AncestorHashes,
1837 }
1838 
1839 impl RevalidationSelectorAndHashes {
new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self1840     fn new(selector: Selector<SelectorImpl>, hashes: AncestorHashes) -> Self {
1841         let selector_offset = {
1842             // We basically want to check whether the first combinator is a
1843             // pseudo-element combinator.  If it is, we want to use the offset
1844             // one past it.  Otherwise, our offset is 0.
1845             let mut index = 0;
1846             let mut iter = selector.iter();
1847 
1848             // First skip over the first ComplexSelector.
1849             //
1850             // We can't check what sort of what combinator we have until we do
1851             // that.
1852             for _ in &mut iter {
1853                 index += 1; // Simple selector
1854             }
1855 
1856             match iter.next_sequence() {
1857                 Some(Combinator::PseudoElement) => index + 1, // +1 for the combinator
1858                 _ => 0,
1859             }
1860         };
1861 
1862         RevalidationSelectorAndHashes {
1863             selector,
1864             selector_offset,
1865             hashes,
1866         }
1867     }
1868 }
1869 
1870 impl SelectorMapEntry for RevalidationSelectorAndHashes {
selector(&self) -> SelectorIter<SelectorImpl>1871     fn selector(&self) -> SelectorIter<SelectorImpl> {
1872         self.selector.iter_from(self.selector_offset)
1873     }
1874 }
1875 
1876 /// A selector visitor implementation that collects all the state the Stylist
1877 /// cares about a selector.
1878 struct StylistSelectorVisitor<'a> {
1879     /// Whether we've past the rightmost compound selector, not counting
1880     /// pseudo-elements.
1881     passed_rightmost_selector: bool,
1882     /// Whether the selector needs revalidation for the style sharing cache.
1883     needs_revalidation: &'a mut bool,
1884     /// The filter with all the id's getting referenced from rightmost
1885     /// selectors.
1886     mapped_ids: &'a mut PrecomputedHashSet<Atom>,
1887     /// The filter with the local names of attributes there are selectors for.
1888     attribute_dependencies: &'a mut PrecomputedHashSet<LocalName>,
1889     /// All the states selectors in the page reference.
1890     state_dependencies: &'a mut ElementState,
1891     /// All the document states selectors in the page reference.
1892     document_state_dependencies: &'a mut DocumentState,
1893 }
1894 
component_needs_revalidation( c: &Component<SelectorImpl>, passed_rightmost_selector: bool, ) -> bool1895 fn component_needs_revalidation(
1896     c: &Component<SelectorImpl>,
1897     passed_rightmost_selector: bool,
1898 ) -> bool {
1899     match *c {
1900         Component::ID(_) => {
1901             // TODO(emilio): This could also check that the ID is not already in
1902             // the rule hash. In that case, we could avoid making this a
1903             // revalidation selector too.
1904             //
1905             // See https://bugzilla.mozilla.org/show_bug.cgi?id=1369611
1906             passed_rightmost_selector
1907         },
1908         Component::AttributeInNoNamespaceExists { .. } |
1909         Component::AttributeInNoNamespace { .. } |
1910         Component::AttributeOther(_) |
1911         Component::Empty |
1912         Component::FirstChild |
1913         Component::LastChild |
1914         Component::OnlyChild |
1915         Component::NthChild(..) |
1916         Component::NthLastChild(..) |
1917         Component::NthOfType(..) |
1918         Component::NthLastOfType(..) |
1919         Component::FirstOfType |
1920         Component::LastOfType |
1921         Component::OnlyOfType => true,
1922         Component::NonTSPseudoClass(ref p) => p.needs_cache_revalidation(),
1923         _ => false,
1924     }
1925 }
1926 
1927 impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
1928     type Impl = SelectorImpl;
1929 
visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool1930     fn visit_complex_selector(&mut self, combinator: Option<Combinator>) -> bool {
1931         *self.needs_revalidation =
1932             *self.needs_revalidation || combinator.map_or(false, |c| c.is_sibling());
1933 
1934         // NOTE(emilio): this call happens before we visit any of the simple
1935         // selectors in the next ComplexSelector, so we can use this to skip
1936         // looking at them.
1937         self.passed_rightmost_selector = self.passed_rightmost_selector ||
1938             !matches!(combinator, None | Some(Combinator::PseudoElement));
1939 
1940         true
1941     }
1942 
visit_selector_list(&mut self, list: &[Selector<Self::Impl>]) -> bool1943     fn visit_selector_list(&mut self, list: &[Selector<Self::Impl>]) -> bool {
1944         for selector in list {
1945             let mut nested = StylistSelectorVisitor {
1946                 passed_rightmost_selector: false,
1947                 needs_revalidation: &mut *self.needs_revalidation,
1948                 attribute_dependencies: &mut *self.attribute_dependencies,
1949                 state_dependencies: &mut *self.state_dependencies,
1950                 document_state_dependencies: &mut *self.document_state_dependencies,
1951                 mapped_ids: &mut *self.mapped_ids,
1952             };
1953             let _ret = selector.visit(&mut nested);
1954             debug_assert!(_ret, "We never return false");
1955         }
1956         true
1957     }
1958 
visit_attribute_selector( &mut self, _ns: &NamespaceConstraint<&Namespace>, name: &LocalName, lower_name: &LocalName, ) -> bool1959     fn visit_attribute_selector(
1960         &mut self,
1961         _ns: &NamespaceConstraint<&Namespace>,
1962         name: &LocalName,
1963         lower_name: &LocalName,
1964     ) -> bool {
1965         self.attribute_dependencies.insert(name.clone());
1966         self.attribute_dependencies.insert(lower_name.clone());
1967         true
1968     }
1969 
visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool1970     fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
1971         *self.needs_revalidation = *self.needs_revalidation ||
1972             component_needs_revalidation(s, self.passed_rightmost_selector);
1973 
1974         match *s {
1975             Component::NonTSPseudoClass(ref p) => {
1976                 self.state_dependencies.insert(p.state_flag());
1977                 self.document_state_dependencies
1978                     .insert(p.document_state_flag());
1979             },
1980             Component::ID(ref id) if !self.passed_rightmost_selector => {
1981                 // We want to stop storing mapped ids as soon as we've moved off
1982                 // the rightmost ComplexSelector that is not a pseudo-element.
1983                 //
1984                 // That can be detected by a visit_complex_selector call with a
1985                 // combinator other than None and PseudoElement.
1986                 //
1987                 // Importantly, this call happens before we visit any of the
1988                 // simple selectors in that ComplexSelector.
1989                 //
1990                 // NOTE(emilio): See the comment regarding on when this may
1991                 // break in visit_complex_selector.
1992                 self.mapped_ids.insert(id.0.clone());
1993             },
1994             _ => {},
1995         }
1996 
1997         true
1998     }
1999 }
2000 
2001 /// A set of rules for element and pseudo-elements.
2002 #[derive(Clone, Debug, Default, MallocSizeOf)]
2003 struct GenericElementAndPseudoRules<Map> {
2004     /// Rules from stylesheets at this `CascadeData`'s origin.
2005     element_map: Map,
2006 
2007     /// Rules from stylesheets at this `CascadeData`'s origin that correspond
2008     /// to a given pseudo-element.
2009     ///
2010     /// FIXME(emilio): There are a bunch of wasted entries here in practice.
2011     /// Figure out a good way to do a `PerNonAnonBox` and `PerAnonBox` (for
2012     /// `precomputed_values_for_pseudo`) without duplicating a lot of code.
2013     pseudos_map: PerPseudoElementMap<Box<Map>>,
2014 }
2015 
2016 impl<Map: Default + MallocSizeOf> GenericElementAndPseudoRules<Map> {
2017     #[inline(always)]
for_insertion(&mut self, pseudo_element: Option<&PseudoElement>) -> &mut Map2018     fn for_insertion(&mut self, pseudo_element: Option<&PseudoElement>) -> &mut Map {
2019         debug_assert!(
2020             pseudo_element.map_or(true, |pseudo| {
2021                 !pseudo.is_precomputed() && !pseudo.is_unknown_webkit_pseudo_element()
2022             }),
2023             "Precomputed pseudos should end up in precomputed_pseudo_element_decls, \
2024              and unknown webkit pseudos should be discarded before getting here"
2025         );
2026 
2027         match pseudo_element {
2028             None => &mut self.element_map,
2029             Some(pseudo) => self
2030                 .pseudos_map
2031                 .get_or_insert_with(pseudo, || Box::new(Default::default())),
2032         }
2033     }
2034 
2035     #[inline]
rules(&self, pseudo: Option<&PseudoElement>) -> Option<&Map>2036     fn rules(&self, pseudo: Option<&PseudoElement>) -> Option<&Map> {
2037         match pseudo {
2038             Some(pseudo) => self.pseudos_map.get(pseudo).map(|p| &**p),
2039             None => Some(&self.element_map),
2040         }
2041     }
2042 
2043     /// Measures heap usage.
2044     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)2045     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2046         sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
2047 
2048         for elem in self.pseudos_map.iter() {
2049             if let Some(ref elem) = *elem {
2050                 sizes.mElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops);
2051             }
2052         }
2053     }
2054 }
2055 
2056 type ElementAndPseudoRules = GenericElementAndPseudoRules<SelectorMap<Rule>>;
2057 type PartMap = PrecomputedHashMap<Atom, SmallVec<[Rule; 1]>>;
2058 type PartElementAndPseudoRules = GenericElementAndPseudoRules<PartMap>;
2059 
2060 impl ElementAndPseudoRules {
2061     // TODO(emilio): Should we retain storage of these?
clear(&mut self)2062     fn clear(&mut self) {
2063         self.element_map.clear();
2064         self.pseudos_map.clear();
2065     }
2066 
shrink_if_needed(&mut self)2067     fn shrink_if_needed(&mut self) {
2068         self.element_map.shrink_if_needed();
2069         for pseudo in self.pseudos_map.iter_mut() {
2070             if let Some(ref mut pseudo) = pseudo {
2071                 pseudo.shrink_if_needed();
2072             }
2073         }
2074     }
2075 }
2076 
2077 impl PartElementAndPseudoRules {
2078     // TODO(emilio): Should we retain storage of these?
clear(&mut self)2079     fn clear(&mut self) {
2080         self.element_map.clear();
2081         self.pseudos_map.clear();
2082     }
2083 }
2084 
2085 #[derive(Clone, Debug, MallocSizeOf)]
2086 struct CascadeLayer {
2087     id: LayerId,
2088     order: LayerOrder,
2089     children: Vec<LayerId>,
2090 }
2091 
2092 impl CascadeLayer {
root() -> Self2093     const fn root() -> Self {
2094         Self {
2095             id: LayerId::root(),
2096             order: LayerOrder::root(),
2097             children: vec![],
2098         }
2099     }
2100 }
2101 
2102 /// Data resulting from performing the CSS cascade that is specific to a given
2103 /// origin.
2104 ///
2105 /// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
2106 /// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
2107 #[derive(Debug, Clone, MallocSizeOf)]
2108 pub struct CascadeData {
2109     /// The data coming from normal style rules that apply to elements at this
2110     /// cascade level.
2111     normal_rules: ElementAndPseudoRules,
2112 
2113     /// The `:host` pseudo rules that are the rightmost selector (without
2114     /// accounting for pseudo-elements).
2115     host_rules: Option<Box<ElementAndPseudoRules>>,
2116 
2117     /// The data coming from ::slotted() pseudo-element rules.
2118     ///
2119     /// We need to store them separately because an element needs to match
2120     /// ::slotted() pseudo-element rules in different shadow roots.
2121     ///
2122     /// In particular, we need to go through all the style data in all the
2123     /// containing style scopes starting from the closest assigned slot.
2124     slotted_rules: Option<Box<ElementAndPseudoRules>>,
2125 
2126     /// The data coming from ::part() pseudo-element rules.
2127     ///
2128     /// We need to store them separately because an element needs to match
2129     /// ::part() pseudo-element rules in different shadow roots.
2130     part_rules: Option<Box<PartElementAndPseudoRules>>,
2131 
2132     /// The invalidation map for these rules.
2133     invalidation_map: InvalidationMap,
2134 
2135     /// The attribute local names that appear in attribute selectors.  Used
2136     /// to avoid taking element snapshots when an irrelevant attribute changes.
2137     /// (We don't bother storing the namespace, since namespaced attributes are
2138     /// rare.)
2139     attribute_dependencies: PrecomputedHashSet<LocalName>,
2140 
2141     /// The element state bits that are relied on by selectors.  Like
2142     /// `attribute_dependencies`, this is used to avoid taking element snapshots
2143     /// when an irrelevant element state bit changes.
2144     state_dependencies: ElementState,
2145 
2146     /// The document state bits that are relied on by selectors.  This is used
2147     /// to tell whether we need to restyle the entire document when a document
2148     /// state bit changes.
2149     document_state_dependencies: DocumentState,
2150 
2151     /// The ids that appear in the rightmost complex selector of selectors (and
2152     /// hence in our selector maps).  Used to determine when sharing styles is
2153     /// safe: we disallow style sharing for elements whose id matches this
2154     /// filter, and hence might be in one of our selector maps.
2155     mapped_ids: PrecomputedHashSet<Atom>,
2156 
2157     /// Selectors that require explicit cache revalidation (i.e. which depend
2158     /// on state that is not otherwise visible to the cache, like attributes or
2159     /// tree-structural state like child index and pseudos).
2160     #[ignore_malloc_size_of = "Arc"]
2161     selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
2162 
2163     /// A map with all the animations at this `CascadeData`'s origin, indexed
2164     /// by name.
2165     animations: LayerOrderedMap<KeyframesAnimation>,
2166 
2167     /// A map from cascade layer name to layer order.
2168     layer_id: FxHashMap<LayerName, LayerId>,
2169 
2170     /// The list of cascade layers, indexed by their layer id.
2171     layers: SmallVec<[CascadeLayer; 1]>,
2172 
2173     /// Effective media query results cached from the last rebuild.
2174     effective_media_query_results: EffectiveMediaQueryResults,
2175 
2176     /// Extra data, like different kinds of rules, etc.
2177     extra_data: ExtraStyleData,
2178 
2179     /// A monotonically increasing counter to represent the order on which a
2180     /// style rule appears in a stylesheet, needed to sort them by source order.
2181     rules_source_order: u32,
2182 
2183     /// The total number of selectors.
2184     num_selectors: usize,
2185 
2186     /// The total number of declarations.
2187     num_declarations: usize,
2188 }
2189 
2190 impl CascadeData {
2191     /// Creates an empty `CascadeData`.
new() -> Self2192     pub fn new() -> Self {
2193         Self {
2194             normal_rules: ElementAndPseudoRules::default(),
2195             host_rules: None,
2196             slotted_rules: None,
2197             part_rules: None,
2198             invalidation_map: InvalidationMap::new(),
2199             attribute_dependencies: PrecomputedHashSet::default(),
2200             state_dependencies: ElementState::empty(),
2201             document_state_dependencies: DocumentState::empty(),
2202             mapped_ids: PrecomputedHashSet::default(),
2203             // NOTE: We disable attribute bucketing for revalidation because we
2204             // rely on the buckets to match, but we don't want to just not share
2205             // style across elements with different attributes.
2206             //
2207             // An alternative to this would be to perform a style sharing check
2208             // like may_match_different_id_rules which would check that the
2209             // attribute buckets match on all scopes. But that seems
2210             // somewhat gnarly.
2211             selectors_for_cache_revalidation: SelectorMap::new_without_attribute_bucketing(),
2212             animations: Default::default(),
2213             layer_id: Default::default(),
2214             layers: smallvec::smallvec![CascadeLayer::root()],
2215             extra_data: ExtraStyleData::default(),
2216             effective_media_query_results: EffectiveMediaQueryResults::new(),
2217             rules_source_order: 0,
2218             num_selectors: 0,
2219             num_declarations: 0,
2220         }
2221     }
2222 
2223     /// Rebuild the cascade data from a given SheetCollection, incrementally if
2224     /// possible.
rebuild<'a, S>( &mut self, device: &Device, quirks_mode: QuirksMode, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, ) -> Result<(), AllocErr> where S: StylesheetInDocument + PartialEq + 'static,2225     pub fn rebuild<'a, S>(
2226         &mut self,
2227         device: &Device,
2228         quirks_mode: QuirksMode,
2229         collection: SheetCollectionFlusher<S>,
2230         guard: &SharedRwLockReadGuard,
2231     ) -> Result<(), AllocErr>
2232     where
2233         S: StylesheetInDocument + PartialEq + 'static,
2234     {
2235         if !collection.dirty() {
2236             return Ok(());
2237         }
2238 
2239         let validity = collection.data_validity();
2240 
2241         match validity {
2242             DataValidity::Valid => {},
2243             DataValidity::CascadeInvalid => self.clear_cascade_data(),
2244             DataValidity::FullyInvalid => self.clear(),
2245         }
2246 
2247         let mut result = Ok(());
2248 
2249         collection.each(|stylesheet, rebuild_kind| {
2250             result = self.add_stylesheet(
2251                 device,
2252                 quirks_mode,
2253                 stylesheet,
2254                 guard,
2255                 rebuild_kind,
2256                 /* precomputed_pseudo_element_decls = */ None,
2257             );
2258             result.is_ok()
2259         });
2260 
2261         self.did_finish_rebuild();
2262 
2263         result
2264     }
2265 
2266     /// Returns the invalidation map.
invalidation_map(&self) -> &InvalidationMap2267     pub fn invalidation_map(&self) -> &InvalidationMap {
2268         &self.invalidation_map
2269     }
2270 
2271     /// Returns whether the given ElementState bit is relied upon by a selector
2272     /// of some rule.
2273     #[inline]
has_state_dependency(&self, state: ElementState) -> bool2274     pub fn has_state_dependency(&self, state: ElementState) -> bool {
2275         self.state_dependencies.intersects(state)
2276     }
2277 
2278     /// Returns whether the given attribute might appear in an attribute
2279     /// selector of some rule.
2280     #[inline]
might_have_attribute_dependency(&self, local_name: &LocalName) -> bool2281     pub fn might_have_attribute_dependency(&self, local_name: &LocalName) -> bool {
2282         self.attribute_dependencies.contains(local_name)
2283     }
2284 
2285     /// Returns the normal rule map for a given pseudo-element.
2286     #[inline]
normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>>2287     pub fn normal_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2288         self.normal_rules.rules(pseudo)
2289     }
2290 
2291     /// Returns the host pseudo rule map for a given pseudo-element.
2292     #[inline]
host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>>2293     pub fn host_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2294         self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
2295     }
2296 
2297     /// Whether there's any host rule that could match in this scope.
any_host_rules(&self) -> bool2298     pub fn any_host_rules(&self) -> bool {
2299         self.host_rules.is_some()
2300     }
2301 
2302     /// Returns the slotted rule map for a given pseudo-element.
2303     #[inline]
slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>>2304     pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
2305         self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
2306     }
2307 
2308     /// Whether there's any ::slotted rule that could match in this scope.
any_slotted_rule(&self) -> bool2309     pub fn any_slotted_rule(&self) -> bool {
2310         self.slotted_rules.is_some()
2311     }
2312 
2313     /// Returns the parts rule map for a given pseudo-element.
2314     #[inline]
part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap>2315     pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> {
2316         self.part_rules.as_ref().and_then(|d| d.rules(pseudo))
2317     }
2318 
2319     /// Whether there's any ::part rule that could match in this scope.
any_part_rule(&self) -> bool2320     pub fn any_part_rule(&self) -> bool {
2321         self.part_rules.is_some()
2322     }
2323 
2324     #[inline]
layer_order_for(&self, id: LayerId) -> LayerOrder2325     fn layer_order_for(&self, id: LayerId) -> LayerOrder {
2326         self.layers[id.0 as usize].order
2327     }
2328 
did_finish_rebuild(&mut self)2329     fn did_finish_rebuild(&mut self) {
2330         self.shrink_maps_if_needed();
2331         self.compute_layer_order();
2332     }
2333 
shrink_maps_if_needed(&mut self)2334     fn shrink_maps_if_needed(&mut self) {
2335         self.normal_rules.shrink_if_needed();
2336         if let Some(ref mut host_rules) = self.host_rules {
2337             host_rules.shrink_if_needed();
2338         }
2339         if let Some(ref mut slotted_rules) = self.slotted_rules {
2340             slotted_rules.shrink_if_needed();
2341         }
2342         self.invalidation_map.shrink_if_needed();
2343         self.attribute_dependencies.shrink_if_needed();
2344         self.mapped_ids.shrink_if_needed();
2345         self.layer_id.shrink_if_needed();
2346         self.selectors_for_cache_revalidation.shrink_if_needed();
2347 
2348     }
2349 
compute_layer_order(&mut self)2350     fn compute_layer_order(&mut self) {
2351         debug_assert_ne!(
2352             self.layers.len(),
2353             0,
2354             "There should be at least the root layer!"
2355         );
2356         if self.layers.len() == 1 {
2357             return; // Nothing to do
2358         }
2359         let (first, remaining) = self.layers.split_at_mut(1);
2360         let root = &mut first[0];
2361         let mut order = LayerOrder::first();
2362         compute_layer_order_for_subtree(root, remaining, &mut order);
2363 
2364         // NOTE(emilio): This is a bit trickier than it should to avoid having
2365         // to clone() around layer indices.
2366         fn compute_layer_order_for_subtree(
2367             parent: &mut CascadeLayer,
2368             remaining_layers: &mut [CascadeLayer],
2369             order: &mut LayerOrder,
2370         ) {
2371             for child in parent.children.iter() {
2372                 debug_assert!(
2373                     parent.id < *child,
2374                     "Children are always registered after parents"
2375                 );
2376                 let child_index = (child.0 - parent.id.0 - 1) as usize;
2377                 let (first, remaining) = remaining_layers.split_at_mut(child_index + 1);
2378                 let child = &mut first[child_index];
2379                 compute_layer_order_for_subtree(child, remaining, order);
2380             }
2381 
2382             if parent.id != LayerId::root() {
2383                 parent.order = *order;
2384                 order.inc();
2385             }
2386         }
2387         self.extra_data.sort_by_layer(&self.layers);
2388         self.animations
2389             .sort_with(&self.layers, compare_keyframes_in_same_layer);
2390     }
2391 
2392     /// Collects all the applicable media query results into `results`.
2393     ///
2394     /// This duplicates part of the logic in `add_stylesheet`, which is
2395     /// a bit unfortunate.
2396     ///
2397     /// FIXME(emilio): With a bit of smartness in
2398     /// `media_feature_affected_matches`, we could convert
2399     /// `EffectiveMediaQueryResults` into a vector without too much effort.
collect_applicable_media_query_results_into<S>( device: &Device, stylesheet: &S, guard: &SharedRwLockReadGuard, results: &mut Vec<MediaListKey>, contents_list: &mut StyleSheetContentList, ) where S: StylesheetInDocument + 'static,2400     fn collect_applicable_media_query_results_into<S>(
2401         device: &Device,
2402         stylesheet: &S,
2403         guard: &SharedRwLockReadGuard,
2404         results: &mut Vec<MediaListKey>,
2405         contents_list: &mut StyleSheetContentList,
2406     ) where
2407         S: StylesheetInDocument + 'static,
2408     {
2409         if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
2410             return;
2411         }
2412 
2413         debug!(" + {:?}", stylesheet);
2414         let contents = stylesheet.contents();
2415         results.push(contents.to_media_list_key());
2416 
2417         // Safety: StyleSheetContents are reference-counted with Arc.
2418         contents_list.push(StylesheetContentsPtr(unsafe {
2419             Arc::from_raw_addrefed(contents)
2420         }));
2421 
2422         for rule in stylesheet.effective_rules(device, guard) {
2423             match *rule {
2424                 CssRule::Import(ref lock) => {
2425                     let import_rule = lock.read_with(guard);
2426                     debug!(" + {:?}", import_rule.stylesheet.media(guard));
2427                     results.push(import_rule.to_media_list_key());
2428                 },
2429                 CssRule::Media(ref lock) => {
2430                     let media_rule = lock.read_with(guard);
2431                     debug!(" + {:?}", media_rule.media_queries.read_with(guard));
2432                     results.push(media_rule.to_media_list_key());
2433                 },
2434                 _ => {},
2435             }
2436         }
2437     }
2438 
add_rule_list<S>( &mut self, rules: std::slice::Iter<'_, CssRule>, device: &Device, quirks_mode: QuirksMode, stylesheet: &S, guard: &SharedRwLockReadGuard, rebuild_kind: SheetRebuildKind, mut current_layer: &mut LayerName, current_layer_id: LayerId, mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>, ) -> Result<(), AllocErr> where S: StylesheetInDocument + 'static,2439     fn add_rule_list<S>(
2440         &mut self,
2441         rules: std::slice::Iter<'_, CssRule>,
2442         device: &Device,
2443         quirks_mode: QuirksMode,
2444         stylesheet: &S,
2445         guard: &SharedRwLockReadGuard,
2446         rebuild_kind: SheetRebuildKind,
2447         mut current_layer: &mut LayerName,
2448         current_layer_id: LayerId,
2449         mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
2450     ) -> Result<(), AllocErr>
2451     where
2452         S: StylesheetInDocument + 'static,
2453     {
2454         for rule in rules {
2455             // Handle leaf rules first, as those are by far the most common
2456             // ones, and are always effective, so we can skip some checks.
2457             let mut handled = true;
2458             match *rule {
2459                 CssRule::Style(ref locked) => {
2460                     let style_rule = locked.read_with(&guard);
2461                     self.num_declarations += style_rule.block.read_with(&guard).len();
2462                     for selector in &style_rule.selectors.0 {
2463                         self.num_selectors += 1;
2464 
2465                         let pseudo_element = selector.pseudo_element();
2466 
2467                         if let Some(pseudo) = pseudo_element {
2468                             if pseudo.is_precomputed() {
2469                                 debug_assert!(selector.is_universal());
2470                                 debug_assert_eq!(stylesheet.contents().origin, Origin::UserAgent);
2471                                 debug_assert_eq!(current_layer_id, LayerId::root());
2472 
2473                                 precomputed_pseudo_element_decls
2474                                     .as_mut()
2475                                     .expect("Expected precomputed declarations for the UA level")
2476                                     .get_or_insert_with(pseudo, Vec::new)
2477                                     .push(ApplicableDeclarationBlock::new(
2478                                         StyleSource::from_rule(locked.clone()),
2479                                         self.rules_source_order,
2480                                         CascadeLevel::UANormal,
2481                                         selector.specificity(),
2482                                         LayerOrder::root(),
2483                                     ));
2484                                 continue;
2485                             }
2486                             if pseudo.is_unknown_webkit_pseudo_element() {
2487                                 continue;
2488                             }
2489                         }
2490 
2491                         let hashes = AncestorHashes::new(&selector, quirks_mode);
2492 
2493                         let rule = Rule::new(
2494                             selector.clone(),
2495                             hashes,
2496                             locked.clone(),
2497                             self.rules_source_order,
2498                             current_layer_id,
2499                         );
2500 
2501                         if rebuild_kind.should_rebuild_invalidation() {
2502                             self.invalidation_map.note_selector(selector, quirks_mode)?;
2503                             let mut needs_revalidation = false;
2504                             let mut visitor = StylistSelectorVisitor {
2505                                 needs_revalidation: &mut needs_revalidation,
2506                                 passed_rightmost_selector: false,
2507                                 attribute_dependencies: &mut self.attribute_dependencies,
2508                                 state_dependencies: &mut self.state_dependencies,
2509                                 document_state_dependencies: &mut self.document_state_dependencies,
2510                                 mapped_ids: &mut self.mapped_ids,
2511                             };
2512 
2513                             rule.selector.visit(&mut visitor);
2514 
2515                             if needs_revalidation {
2516                                 self.selectors_for_cache_revalidation.insert(
2517                                     RevalidationSelectorAndHashes::new(
2518                                         rule.selector.clone(),
2519                                         rule.hashes.clone(),
2520                                     ),
2521                                     quirks_mode,
2522                                 )?;
2523                             }
2524                         }
2525 
2526                         // Part is special, since given it doesn't have any
2527                         // selectors inside, it's not worth using a whole
2528                         // SelectorMap for it.
2529                         if let Some(parts) = selector.parts() {
2530                             // ::part() has all semantics, so we just need to
2531                             // put any of them in the selector map.
2532                             //
2533                             // We choose the last one quite arbitrarily,
2534                             // expecting it's slightly more likely to be more
2535                             // specific.
2536                             let map = self
2537                                 .part_rules
2538                                 .get_or_insert_with(|| Box::new(Default::default()))
2539                                 .for_insertion(pseudo_element);
2540                             map.try_reserve(1)?;
2541                             let vec = map.entry(parts.last().unwrap().clone().0).or_default();
2542                             vec.try_reserve(1)?;
2543                             vec.push(rule);
2544                         } else {
2545                             // NOTE(emilio): It's fine to look at :host and then at
2546                             // ::slotted(..), since :host::slotted(..) could never
2547                             // possibly match, as <slot> is not a valid shadow host.
2548                             let rules =
2549                                 if selector.is_featureless_host_selector_or_pseudo_element() {
2550                                     self.host_rules
2551                                         .get_or_insert_with(|| Box::new(Default::default()))
2552                                 } else if selector.is_slotted() {
2553                                     self.slotted_rules
2554                                         .get_or_insert_with(|| Box::new(Default::default()))
2555                                 } else {
2556                                     &mut self.normal_rules
2557                                 }
2558                                 .for_insertion(pseudo_element);
2559                             rules.insert(rule, quirks_mode)?;
2560                         }
2561                     }
2562                     self.rules_source_order += 1;
2563                 },
2564                 CssRule::Keyframes(ref keyframes_rule) => {
2565                     debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
2566                     let keyframes_rule = keyframes_rule.read_with(guard);
2567                     let name = keyframes_rule.name.as_atom().clone();
2568                     let animation = KeyframesAnimation::from_keyframes(
2569                         &keyframes_rule.keyframes,
2570                         keyframes_rule.vendor_prefix.clone(),
2571                         guard,
2572                     );
2573                     self.animations.try_insert_with(
2574                         name,
2575                         animation,
2576                         current_layer_id,
2577                         compare_keyframes_in_same_layer,
2578                     )?;
2579                 },
2580                 #[cfg(feature = "gecko")]
2581                 CssRule::ScrollTimeline(ref rule) => {
2582                     // Note: Bug 1733260: we may drop @scroll-timeline rule once this spec issue
2583                     // https://github.com/w3c/csswg-drafts/issues/6674 gets landed.
2584                     self.extra_data
2585                         .add_scroll_timeline(guard, rule, current_layer_id)?;
2586                 },
2587                 #[cfg(feature = "gecko")]
2588                 CssRule::FontFace(ref rule) => {
2589                     self.extra_data.add_font_face(rule, current_layer_id);
2590                 },
2591                 #[cfg(feature = "gecko")]
2592                 CssRule::FontFeatureValues(ref rule) => {
2593                     self.extra_data
2594                         .add_font_feature_values(rule, current_layer_id);
2595                 },
2596                 #[cfg(feature = "gecko")]
2597                 CssRule::CounterStyle(ref rule) => {
2598                     self.extra_data
2599                         .add_counter_style(guard, rule, current_layer_id)?;
2600                 },
2601                 #[cfg(feature = "gecko")]
2602                 CssRule::Page(ref rule) => {
2603                     self.extra_data.add_page(guard, rule, current_layer_id)?;
2604                 },
2605                 CssRule::Viewport(..) => {},
2606                 _ => {
2607                     handled = false;
2608                 },
2609             }
2610 
2611             if handled {
2612                 // Assert that there are no children, and that the rule is
2613                 // effective.
2614                 if cfg!(debug_assertions) {
2615                     let mut effective = false;
2616                     let children = EffectiveRulesIterator::children(
2617                         rule,
2618                         device,
2619                         quirks_mode,
2620                         guard,
2621                         &mut effective,
2622                     );
2623                     debug_assert!(children.is_none());
2624                     debug_assert!(effective);
2625                 }
2626                 continue;
2627             }
2628 
2629             let mut effective = false;
2630             let children =
2631                 EffectiveRulesIterator::children(rule, device, quirks_mode, guard, &mut effective);
2632 
2633             if !effective {
2634                 continue;
2635             }
2636 
2637             fn maybe_register_layer(data: &mut CascadeData, layer: &LayerName) -> LayerId {
2638                 // TODO: Measure what's more common / expensive, if
2639                 // layer.clone() or the double hash lookup in the insert
2640                 // case.
2641                 if let Some(id) = data.layer_id.get(layer) {
2642                     return *id;
2643                 }
2644                 let id = LayerId(data.layers.len() as u32);
2645 
2646                 let parent_layer_id = if layer.layer_names().len() > 1 {
2647                     let mut parent = layer.clone();
2648                     parent.0.pop();
2649 
2650                     *data
2651                         .layer_id
2652                         .get_mut(&parent)
2653                         .expect("Parent layers should be registered before child layers")
2654                 } else {
2655                     LayerId::root()
2656                 };
2657 
2658                 data.layers[parent_layer_id.0 as usize].children.push(id);
2659                 data.layers.push(CascadeLayer {
2660                     id,
2661                     // NOTE(emilio): Order is evaluated after rebuild in
2662                     // compute_layer_order.
2663                     order: LayerOrder::first(),
2664                     children: vec![],
2665                 });
2666 
2667                 data.layer_id.insert(layer.clone(), id);
2668 
2669                 id
2670             }
2671 
2672             fn maybe_register_layers(
2673                 data: &mut CascadeData,
2674                 name: Option<&LayerName>,
2675                 current_layer: &mut LayerName,
2676                 pushed_layers: &mut usize,
2677             ) -> LayerId {
2678                 let anon_name;
2679                 let name = match name {
2680                     Some(name) => name,
2681                     None => {
2682                         anon_name = LayerName::new_anonymous();
2683                         &anon_name
2684                     },
2685                 };
2686 
2687                 let mut id = LayerId::root();
2688                 for name in name.layer_names() {
2689                     current_layer.0.push(name.clone());
2690                     id = maybe_register_layer(data, &current_layer);
2691                     *pushed_layers += 1;
2692                 }
2693                 debug_assert_ne!(id, LayerId::root());
2694                 id
2695             }
2696 
2697             let mut layer_names_to_pop = 0;
2698             let mut children_layer_id = current_layer_id;
2699             match *rule {
2700                 CssRule::Import(ref lock) => {
2701                     let import_rule = lock.read_with(guard);
2702                     if rebuild_kind.should_rebuild_invalidation() {
2703                         self.effective_media_query_results
2704                             .saw_effective(import_rule);
2705                     }
2706                     if let Some(ref layer) = import_rule.layer {
2707                         children_layer_id = maybe_register_layers(
2708                             self,
2709                             layer.name.as_ref(),
2710                             &mut current_layer,
2711                             &mut layer_names_to_pop,
2712                         );
2713                     }
2714                 },
2715                 CssRule::Media(ref lock) => {
2716                     if rebuild_kind.should_rebuild_invalidation() {
2717                         let media_rule = lock.read_with(guard);
2718                         self.effective_media_query_results.saw_effective(media_rule);
2719                     }
2720                 },
2721                 CssRule::LayerBlock(ref lock) => {
2722                     let layer_rule = lock.read_with(guard);
2723                     children_layer_id = maybe_register_layers(
2724                         self,
2725                         layer_rule.name.as_ref(),
2726                         &mut current_layer,
2727                         &mut layer_names_to_pop,
2728                     );
2729                 },
2730                 CssRule::LayerStatement(ref lock) => {
2731                     let layer_rule = lock.read_with(guard);
2732                     for name in &*layer_rule.names {
2733                         let mut pushed = 0;
2734                         // There are no children, so we can ignore the
2735                         // return value.
2736                         maybe_register_layers(self, Some(name), &mut current_layer, &mut pushed);
2737                         for _ in 0..pushed {
2738                             current_layer.0.pop();
2739                         }
2740                     }
2741                 },
2742                 // We don't care about any other rule.
2743                 _ => {},
2744             }
2745 
2746             if let Some(children) = children {
2747                 self.add_rule_list(
2748                     children,
2749                     device,
2750                     quirks_mode,
2751                     stylesheet,
2752                     guard,
2753                     rebuild_kind,
2754                     current_layer,
2755                     children_layer_id,
2756                     precomputed_pseudo_element_decls.as_deref_mut(),
2757                 )?;
2758             }
2759 
2760             for _ in 0..layer_names_to_pop {
2761                 current_layer.0.pop();
2762             }
2763         }
2764 
2765         Ok(())
2766     }
2767 
2768     // Returns Err(..) to signify OOM
add_stylesheet<S>( &mut self, device: &Device, quirks_mode: QuirksMode, stylesheet: &S, guard: &SharedRwLockReadGuard, rebuild_kind: SheetRebuildKind, mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>, ) -> Result<(), AllocErr> where S: StylesheetInDocument + 'static,2769     fn add_stylesheet<S>(
2770         &mut self,
2771         device: &Device,
2772         quirks_mode: QuirksMode,
2773         stylesheet: &S,
2774         guard: &SharedRwLockReadGuard,
2775         rebuild_kind: SheetRebuildKind,
2776         mut precomputed_pseudo_element_decls: Option<&mut PrecomputedPseudoElementDeclarations>,
2777     ) -> Result<(), AllocErr>
2778     where
2779         S: StylesheetInDocument + 'static,
2780     {
2781         if !stylesheet.enabled() || !stylesheet.is_effective_for_device(device, guard) {
2782             return Ok(());
2783         }
2784 
2785         let contents = stylesheet.contents();
2786 
2787         if rebuild_kind.should_rebuild_invalidation() {
2788             self.effective_media_query_results.saw_effective(contents);
2789         }
2790 
2791         let mut current_layer = LayerName::new_empty();
2792         self.add_rule_list(
2793             contents.rules(guard).iter(),
2794             device,
2795             quirks_mode,
2796             stylesheet,
2797             guard,
2798             rebuild_kind,
2799             &mut current_layer,
2800             LayerId::root(),
2801             precomputed_pseudo_element_decls.as_deref_mut(),
2802         )?;
2803 
2804         Ok(())
2805     }
2806 
2807     /// Returns whether all the media-feature affected values matched before and
2808     /// match now in the given stylesheet.
media_feature_affected_matches<S>( &self, stylesheet: &S, guard: &SharedRwLockReadGuard, device: &Device, quirks_mode: QuirksMode, ) -> bool where S: StylesheetInDocument + 'static,2809     pub fn media_feature_affected_matches<S>(
2810         &self,
2811         stylesheet: &S,
2812         guard: &SharedRwLockReadGuard,
2813         device: &Device,
2814         quirks_mode: QuirksMode,
2815     ) -> bool
2816     where
2817         S: StylesheetInDocument + 'static,
2818     {
2819         use crate::invalidation::media_queries::PotentiallyEffectiveMediaRules;
2820 
2821         let effective_now = stylesheet.is_effective_for_device(device, guard);
2822 
2823         let effective_then = self
2824             .effective_media_query_results
2825             .was_effective(stylesheet.contents());
2826 
2827         if effective_now != effective_then {
2828             debug!(
2829                 " > Stylesheet {:?} changed -> {}, {}",
2830                 stylesheet.media(guard),
2831                 effective_then,
2832                 effective_now
2833             );
2834             return false;
2835         }
2836 
2837         if !effective_now {
2838             return true;
2839         }
2840 
2841         let mut iter = stylesheet.iter_rules::<PotentiallyEffectiveMediaRules>(device, guard);
2842 
2843         while let Some(rule) = iter.next() {
2844             match *rule {
2845                 CssRule::Style(..) |
2846                 CssRule::Namespace(..) |
2847                 CssRule::FontFace(..) |
2848                 CssRule::CounterStyle(..) |
2849                 CssRule::Supports(..) |
2850                 CssRule::Keyframes(..) |
2851                 CssRule::ScrollTimeline(..) |
2852                 CssRule::Page(..) |
2853                 CssRule::Viewport(..) |
2854                 CssRule::Document(..) |
2855                 CssRule::LayerBlock(..) |
2856                 CssRule::LayerStatement(..) |
2857                 CssRule::FontFeatureValues(..) => {
2858                     // Not affected by device changes.
2859                     continue;
2860                 },
2861                 CssRule::Import(ref lock) => {
2862                     let import_rule = lock.read_with(guard);
2863                     let effective_now = match import_rule.stylesheet.media(guard) {
2864                         Some(m) => m.evaluate(device, quirks_mode),
2865                         None => true,
2866                     };
2867                     let effective_then = self
2868                         .effective_media_query_results
2869                         .was_effective(import_rule);
2870                     if effective_now != effective_then {
2871                         debug!(
2872                             " > @import rule {:?} changed {} -> {}",
2873                             import_rule.stylesheet.media(guard),
2874                             effective_then,
2875                             effective_now
2876                         );
2877                         return false;
2878                     }
2879 
2880                     if !effective_now {
2881                         iter.skip_children();
2882                     }
2883                 },
2884                 CssRule::Media(ref lock) => {
2885                     let media_rule = lock.read_with(guard);
2886                     let mq = media_rule.media_queries.read_with(guard);
2887                     let effective_now = mq.evaluate(device, quirks_mode);
2888                     let effective_then =
2889                         self.effective_media_query_results.was_effective(media_rule);
2890 
2891                     if effective_now != effective_then {
2892                         debug!(
2893                             " > @media rule {:?} changed {} -> {}",
2894                             mq, effective_then, effective_now
2895                         );
2896                         return false;
2897                     }
2898 
2899                     if !effective_now {
2900                         iter.skip_children();
2901                     }
2902                 },
2903             }
2904         }
2905 
2906         true
2907     }
2908 
2909     /// Clears the cascade data, but not the invalidation data.
clear_cascade_data(&mut self)2910     fn clear_cascade_data(&mut self) {
2911         self.normal_rules.clear();
2912         if let Some(ref mut slotted_rules) = self.slotted_rules {
2913             slotted_rules.clear();
2914         }
2915         if let Some(ref mut part_rules) = self.part_rules {
2916             part_rules.clear();
2917         }
2918         if let Some(ref mut host_rules) = self.host_rules {
2919             host_rules.clear();
2920         }
2921         self.animations.clear();
2922         self.layer_id.clear();
2923         self.layers.clear();
2924         self.layers.push(CascadeLayer::root());
2925         self.extra_data.clear();
2926         self.rules_source_order = 0;
2927         self.num_selectors = 0;
2928         self.num_declarations = 0;
2929     }
2930 
clear(&mut self)2931     fn clear(&mut self) {
2932         self.clear_cascade_data();
2933         self.invalidation_map.clear();
2934         self.attribute_dependencies.clear();
2935         self.state_dependencies = ElementState::empty();
2936         self.document_state_dependencies = DocumentState::empty();
2937         self.mapped_ids.clear();
2938         self.selectors_for_cache_revalidation.clear();
2939         self.effective_media_query_results.clear();
2940     }
2941 }
2942 
2943 impl CascadeDataCacheEntry for CascadeData {
cascade_data(&self) -> &CascadeData2944     fn cascade_data(&self) -> &CascadeData {
2945         self
2946     }
2947 
rebuild<S>( device: &Device, quirks_mode: QuirksMode, collection: SheetCollectionFlusher<S>, guard: &SharedRwLockReadGuard, old: &Self, ) -> Result<Arc<Self>, AllocErr> where S: StylesheetInDocument + PartialEq + 'static,2948     fn rebuild<S>(
2949         device: &Device,
2950         quirks_mode: QuirksMode,
2951         collection: SheetCollectionFlusher<S>,
2952         guard: &SharedRwLockReadGuard,
2953         old: &Self,
2954     ) -> Result<Arc<Self>, AllocErr>
2955     where
2956         S: StylesheetInDocument + PartialEq + 'static,
2957     {
2958         debug_assert!(collection.dirty(), "We surely need to do something?");
2959         // If we're doing a full rebuild anyways, don't bother cloning the data.
2960         let mut updatable_entry = match collection.data_validity() {
2961             DataValidity::Valid | DataValidity::CascadeInvalid => old.clone(),
2962             DataValidity::FullyInvalid => Self::new(),
2963         };
2964         updatable_entry.rebuild(device, quirks_mode, collection, guard)?;
2965         Ok(Arc::new(updatable_entry))
2966     }
2967 
2968     #[cfg(feature = "gecko")]
add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes)2969     fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
2970         self.normal_rules.add_size_of(ops, sizes);
2971         if let Some(ref slotted_rules) = self.slotted_rules {
2972             slotted_rules.add_size_of(ops, sizes);
2973         }
2974         if let Some(ref part_rules) = self.part_rules {
2975             part_rules.add_size_of(ops, sizes);
2976         }
2977         if let Some(ref host_rules) = self.host_rules {
2978             host_rules.add_size_of(ops, sizes);
2979         }
2980         sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
2981         sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
2982         sizes.mOther += self.animations.size_of(ops);
2983         sizes.mOther += self.effective_media_query_results.size_of(ops);
2984         sizes.mOther += self.extra_data.size_of(ops);
2985     }
2986 }
2987 
2988 impl Default for CascadeData {
default() -> Self2989     fn default() -> Self {
2990         CascadeData::new()
2991     }
2992 }
2993 
2994 /// A rule, that wraps a style rule, but represents a single selector of the
2995 /// rule.
2996 #[derive(Clone, Debug, MallocSizeOf)]
2997 pub struct Rule {
2998     /// The selector this struct represents. We store this and the
2999     /// any_{important,normal} booleans inline in the Rule to avoid
3000     /// pointer-chasing when gathering applicable declarations, which
3001     /// can ruin performance when there are a lot of rules.
3002     #[ignore_malloc_size_of = "CssRules have primary refs, we measure there"]
3003     pub selector: Selector<SelectorImpl>,
3004 
3005     /// The ancestor hashes associated with the selector.
3006     pub hashes: AncestorHashes,
3007 
3008     /// The source order this style rule appears in. Note that we only use
3009     /// three bytes to store this value in ApplicableDeclarationsBlock, so
3010     /// we could repurpose that storage here if we needed to.
3011     pub source_order: u32,
3012 
3013     /// The current layer id of this style rule.
3014     pub layer_id: LayerId,
3015 
3016     /// The actual style rule.
3017     #[cfg_attr(
3018         feature = "gecko",
3019         ignore_malloc_size_of = "Secondary ref. Primary ref is in StyleRule under Stylesheet."
3020     )]
3021     #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
3022     pub style_rule: Arc<Locked<StyleRule>>,
3023 }
3024 
3025 impl SelectorMapEntry for Rule {
selector(&self) -> SelectorIter<SelectorImpl>3026     fn selector(&self) -> SelectorIter<SelectorImpl> {
3027         self.selector.iter()
3028     }
3029 }
3030 
3031 impl Rule {
3032     /// Returns the specificity of the rule.
specificity(&self) -> u323033     pub fn specificity(&self) -> u32 {
3034         self.selector.specificity()
3035     }
3036 
3037     /// Turns this rule into an `ApplicableDeclarationBlock` for the given
3038     /// cascade level.
to_applicable_declaration_block( &self, level: CascadeLevel, cascade_data: &CascadeData, ) -> ApplicableDeclarationBlock3039     pub fn to_applicable_declaration_block(
3040         &self,
3041         level: CascadeLevel,
3042         cascade_data: &CascadeData,
3043     ) -> ApplicableDeclarationBlock {
3044         let source = StyleSource::from_rule(self.style_rule.clone());
3045         ApplicableDeclarationBlock::new(
3046             source,
3047             self.source_order,
3048             level,
3049             self.specificity(),
3050             cascade_data.layer_order_for(self.layer_id),
3051         )
3052     }
3053 
3054     /// Creates a new Rule.
new( selector: Selector<SelectorImpl>, hashes: AncestorHashes, style_rule: Arc<Locked<StyleRule>>, source_order: u32, layer_id: LayerId, ) -> Self3055     pub fn new(
3056         selector: Selector<SelectorImpl>,
3057         hashes: AncestorHashes,
3058         style_rule: Arc<Locked<StyleRule>>,
3059         source_order: u32,
3060         layer_id: LayerId,
3061     ) -> Self {
3062         Rule {
3063             selector,
3064             hashes,
3065             style_rule,
3066             source_order,
3067             layer_id,
3068         }
3069     }
3070 }
3071 
3072 /// A function to be able to test the revalidation stuff.
needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool3073 pub fn needs_revalidation_for_testing(s: &Selector<SelectorImpl>) -> bool {
3074     let mut attribute_dependencies = Default::default();
3075     let mut mapped_ids = Default::default();
3076     let mut state_dependencies = ElementState::empty();
3077     let mut document_state_dependencies = DocumentState::empty();
3078     let mut needs_revalidation = false;
3079     let mut visitor = StylistSelectorVisitor {
3080         passed_rightmost_selector: false,
3081         needs_revalidation: &mut needs_revalidation,
3082         attribute_dependencies: &mut attribute_dependencies,
3083         state_dependencies: &mut state_dependencies,
3084         document_state_dependencies: &mut document_state_dependencies,
3085         mapped_ids: &mut mapped_ids,
3086     };
3087     s.visit(&mut visitor);
3088     needs_revalidation
3089 }
3090