mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
This should be both a memory and speed win for pages using a lot of Shadow DOM. In order to make the cache properly work we need to start keying media query results on the actual StyleSheetContents, as that's what we share on Gecko, but that should all be fine. Differential Revision: https://phabricator.services.mozilla.com/D107266
130 lines
4.2 KiB
Rust
130 lines
4.2 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Code related to the invalidation of media-query-affected rules.
|
|
|
|
use crate::context::QuirksMode;
|
|
use crate::media_queries::Device;
|
|
use crate::shared_lock::SharedRwLockReadGuard;
|
|
use crate::stylesheets::{DocumentRule, ImportRule, MediaRule};
|
|
use crate::stylesheets::{NestedRuleIterationCondition, StylesheetContents, SupportsRule};
|
|
use fxhash::FxHashSet;
|
|
|
|
/// A key for a given media query result.
|
|
///
|
|
/// NOTE: It happens to be the case that all the media lists we care about
|
|
/// happen to have a stable address, so we can just use an opaque pointer to
|
|
/// represent them.
|
|
///
|
|
/// Also, note that right now when a rule or stylesheet is removed, we do a full
|
|
/// style flush, so there's no need to worry about other item created with the
|
|
/// same pointer address.
|
|
///
|
|
/// If this changes, though, we may need to remove the item from the cache if
|
|
/// present before it goes away.
|
|
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
|
pub struct MediaListKey(usize);
|
|
|
|
impl MediaListKey {
|
|
/// Create a MediaListKey from a raw usize.
|
|
pub fn from_raw(k: usize) -> Self {
|
|
MediaListKey(k)
|
|
}
|
|
}
|
|
|
|
/// A trait to get a given `MediaListKey` for a given item that can hold a
|
|
/// `MediaList`.
|
|
pub trait ToMediaListKey: Sized {
|
|
/// Get a `MediaListKey` for this item. This key needs to uniquely identify
|
|
/// the item.
|
|
fn to_media_list_key(&self) -> MediaListKey {
|
|
MediaListKey(self as *const Self as usize)
|
|
}
|
|
}
|
|
|
|
impl ToMediaListKey for StylesheetContents {}
|
|
impl ToMediaListKey for ImportRule {}
|
|
impl ToMediaListKey for MediaRule {}
|
|
|
|
/// A struct that holds the result of a media query evaluation pass for the
|
|
/// media queries that evaluated successfully.
|
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
|
pub struct EffectiveMediaQueryResults {
|
|
/// The set of media lists that matched last time.
|
|
set: FxHashSet<MediaListKey>,
|
|
}
|
|
|
|
impl EffectiveMediaQueryResults {
|
|
/// Trivially constructs an empty `EffectiveMediaQueryResults`.
|
|
pub fn new() -> Self {
|
|
Self {
|
|
set: FxHashSet::default(),
|
|
}
|
|
}
|
|
|
|
/// Resets the results, using an empty key.
|
|
pub fn clear(&mut self) {
|
|
self.set.clear()
|
|
}
|
|
|
|
/// Returns whether a given item was known to be effective when the results
|
|
/// were cached.
|
|
pub fn was_effective<T>(&self, item: &T) -> bool
|
|
where
|
|
T: ToMediaListKey,
|
|
{
|
|
self.set.contains(&item.to_media_list_key())
|
|
}
|
|
|
|
/// Notices that an effective item has been seen, and caches it as matching.
|
|
pub fn saw_effective<T>(&mut self, item: &T)
|
|
where
|
|
T: ToMediaListKey,
|
|
{
|
|
// NOTE(emilio): We can't assert that we don't cache the same item twice
|
|
// because of stylesheet reusing... shrug.
|
|
self.set.insert(item.to_media_list_key());
|
|
}
|
|
}
|
|
|
|
/// A filter that filters over effective rules, but allowing all potentially
|
|
/// effective `@media` rules.
|
|
pub struct PotentiallyEffectiveMediaRules;
|
|
|
|
impl NestedRuleIterationCondition for PotentiallyEffectiveMediaRules {
|
|
fn process_import(
|
|
_: &SharedRwLockReadGuard,
|
|
_: &Device,
|
|
_: QuirksMode,
|
|
_: &ImportRule,
|
|
) -> bool {
|
|
true
|
|
}
|
|
|
|
fn process_media(_: &SharedRwLockReadGuard, _: &Device, _: QuirksMode, _: &MediaRule) -> bool {
|
|
true
|
|
}
|
|
|
|
/// Whether we should process the nested rules in a given `@-moz-document` rule.
|
|
fn process_document(
|
|
guard: &SharedRwLockReadGuard,
|
|
device: &Device,
|
|
quirks_mode: QuirksMode,
|
|
rule: &DocumentRule,
|
|
) -> bool {
|
|
use crate::stylesheets::EffectiveRules;
|
|
EffectiveRules::process_document(guard, device, quirks_mode, rule)
|
|
}
|
|
|
|
/// Whether we should process the nested rules in a given `@supports` rule.
|
|
fn process_supports(
|
|
guard: &SharedRwLockReadGuard,
|
|
device: &Device,
|
|
quirks_mode: QuirksMode,
|
|
rule: &SupportsRule,
|
|
) -> bool {
|
|
use crate::stylesheets::EffectiveRules;
|
|
EffectiveRules::process_supports(guard, device, quirks_mode, rule)
|
|
}
|
|
}
|