style/invalidation/
media_queries.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Code related to the invalidation of media-query-affected rules.
6
7use crate::context::QuirksMode;
8use crate::derives::*;
9use crate::media_queries::Device;
10use crate::shared_lock::SharedRwLockReadGuard;
11use crate::stylesheets::{CustomMediaMap, DocumentRule, ImportRule, MediaRule};
12use crate::stylesheets::{NestedRuleIterationCondition, StylesheetContents, SupportsRule};
13use rustc_hash::FxHashSet;
14
15/// A key for a given media query result.
16///
17/// NOTE: It happens to be the case that all the media lists we care about
18/// happen to have a stable address, so we can just use an opaque pointer to
19/// represent them.
20///
21/// Also, note that right now when a rule or stylesheet is removed, we do a full
22/// style flush, so there's no need to worry about other item created with the
23/// same pointer address.
24///
25/// If this changes, though, we may need to remove the item from the cache if
26/// present before it goes away.
27#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
28pub struct MediaListKey(usize);
29
30impl MediaListKey {
31    /// Create a MediaListKey from a raw usize.
32    pub fn from_raw(k: usize) -> Self {
33        MediaListKey(k)
34    }
35}
36
37/// A trait to get a given `MediaListKey` for a given item that can hold a
38/// `MediaList`.
39pub trait ToMediaListKey: Sized {
40    /// Get a `MediaListKey` for this item. This key needs to uniquely identify
41    /// the item.
42    fn to_media_list_key(&self) -> MediaListKey {
43        MediaListKey(self as *const Self as usize)
44    }
45}
46
47impl ToMediaListKey for StylesheetContents {}
48impl ToMediaListKey for ImportRule {}
49impl ToMediaListKey for MediaRule {}
50
51/// A struct that holds the result of a media query evaluation pass for the
52/// media queries that evaluated successfully.
53#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
54pub struct EffectiveMediaQueryResults {
55    /// The set of media lists that matched last time.
56    set: FxHashSet<MediaListKey>,
57}
58
59impl EffectiveMediaQueryResults {
60    /// Trivially constructs an empty `EffectiveMediaQueryResults`.
61    pub fn new() -> Self {
62        Self {
63            set: FxHashSet::default(),
64        }
65    }
66
67    /// Resets the results, using an empty key.
68    pub fn clear(&mut self) {
69        self.set.clear()
70    }
71
72    /// Returns whether a given item was known to be effective when the results
73    /// were cached.
74    pub fn was_effective<T>(&self, item: &T) -> bool
75    where
76        T: ToMediaListKey,
77    {
78        self.set.contains(&item.to_media_list_key())
79    }
80
81    /// Notices that an effective item has been seen, and caches it as matching.
82    pub fn saw_effective<T>(&mut self, item: &T)
83    where
84        T: ToMediaListKey,
85    {
86        // NOTE(emilio): We can't assert that we don't cache the same item twice
87        // because of stylesheet reusing... shrug.
88        self.set.insert(item.to_media_list_key());
89    }
90}
91
92/// A filter that filters over effective rules, but allowing all potentially
93/// effective `@media` rules.
94pub struct PotentiallyEffectiveMediaRules;
95
96impl NestedRuleIterationCondition for PotentiallyEffectiveMediaRules {
97    fn process_import(
98        _: &SharedRwLockReadGuard,
99        _: &Device,
100        _: QuirksMode,
101        _: &CustomMediaMap,
102        _: &ImportRule,
103    ) -> bool {
104        true
105    }
106
107    fn process_media(
108        _: &SharedRwLockReadGuard,
109        _: &Device,
110        _: QuirksMode,
111        _: &CustomMediaMap,
112        _: &MediaRule,
113    ) -> bool {
114        true
115    }
116
117    /// Whether we should process the nested rules in a given `@-moz-document` rule.
118    fn process_document(
119        guard: &SharedRwLockReadGuard,
120        device: &Device,
121        quirks_mode: QuirksMode,
122        rule: &DocumentRule,
123    ) -> bool {
124        use crate::stylesheets::EffectiveRules;
125        EffectiveRules::process_document(guard, device, quirks_mode, rule)
126    }
127
128    /// Whether we should process the nested rules in a given `@supports` rule.
129    fn process_supports(
130        guard: &SharedRwLockReadGuard,
131        device: &Device,
132        quirks_mode: QuirksMode,
133        rule: &SupportsRule,
134    ) -> bool {
135        use crate::stylesheets::EffectiveRules;
136        EffectiveRules::process_supports(guard, device, quirks_mode, rule)
137    }
138}