--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -69,19 +69,16 @@ pub struct Stylist {
/// On Servo, on the other hand, the device is a really cheap representation
/// that is recreated each time some constraint changes and calling
/// `set_device`.
device: Device,
/// Viewport constraints based on the current device.
viewport_constraints: Option<ViewportConstraints>,
- /// Effective media query results cached from the last rebuild.
- effective_media_query_results: EffectiveMediaQueryResults,
-
/// If true, the quirks-mode stylesheet is applied.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "defined in selectors")]
quirks_mode: QuirksMode,
/// If true, the device has changed, and the stylist needs to be updated.
is_device_dirty: bool,
/// If true, the stylist is in a cleared state (e.g. just-constructed, or
@@ -139,17 +136,16 @@ impl Stylist {
#[inline]
pub fn new(device: Device, quirks_mode: QuirksMode) -> Self {
Stylist {
viewport_constraints: None,
device: device,
is_device_dirty: true,
is_cleared: true,
quirks_mode: quirks_mode,
- effective_media_query_results: EffectiveMediaQueryResults::new(),
cascade_data: Default::default(),
precomputed_pseudo_element_decls: PerPseudoElementMap::default(),
rules_source_order: 0,
rule_tree: RuleTree::new(),
num_rebuilds: 0,
}
@@ -210,17 +206,16 @@ impl Stylist {
/// Stylist::new.
pub fn clear(&mut self) {
if self.is_cleared {
return
}
self.is_cleared = true;
- self.effective_media_query_results.clear();
self.viewport_constraints = None;
// preserve current device
self.is_device_dirty = true;
// preserve current quirks_mode value
self.cascade_data.clear();
self.precomputed_pseudo_element_decls.clear();
self.rules_source_order = 0;
// We want to keep rule_tree around across stylist rebuilds.
@@ -348,23 +343,24 @@ impl Stylist {
where
S: StylesheetInDocument + ToMediaListKey + 'static,
{
if !stylesheet.enabled() ||
!stylesheet.is_effective_for_device(&self.device, guard) {
return;
}
- self.effective_media_query_results.saw_effective(stylesheet);
-
let origin = stylesheet.origin(guard);
-
let origin_cascade_data =
self.cascade_data.borrow_mut_for_origin(&origin);
+ origin_cascade_data
+ .effective_media_query_results
+ .saw_effective(stylesheet);
+
for rule in stylesheet.effective_rules(&self.device, guard) {
match *rule {
CssRule::Style(ref locked) => {
let style_rule = locked.read_with(&guard);
origin_cascade_data.num_declarations +=
style_rule.block.read_with(&guard).len();
for selector in &style_rule.selectors.0 {
origin_cascade_data.num_selectors += 1;
@@ -431,24 +427,28 @@ impl Stylist {
RevalidationSelectorAndHashes::new(selector.clone(), hashes),
self.quirks_mode);
}
}
self.rules_source_order += 1;
}
CssRule::Import(ref lock) => {
let import_rule = lock.read_with(guard);
- self.effective_media_query_results.saw_effective(import_rule);
+ origin_cascade_data
+ .effective_media_query_results
+ .saw_effective(import_rule);
// NOTE: effective_rules visits the inner stylesheet if
// appropriate.
}
CssRule::Media(ref lock) => {
let media_rule = lock.read_with(guard);
- self.effective_media_query_results.saw_effective(media_rule);
+ origin_cascade_data
+ .effective_media_query_results
+ .saw_effective(media_rule);
}
CssRule::Keyframes(ref keyframes_rule) => {
let keyframes_rule = keyframes_rule.read_with(guard);
debug!("Found valid keyframes rule: {:?}", *keyframes_rule);
// Don't let a prefixed keyframes animation override a non-prefixed one.
let needs_insertion =
keyframes_rule.vendor_prefix.is_none() ||
@@ -949,18 +949,24 @@ impl Stylist {
use invalidation::media_queries::PotentiallyEffectiveMediaRules;
debug!("Stylist::media_features_change_changed_style");
for stylesheet in stylesheets {
let effective_now =
stylesheet.is_effective_for_device(&self.device, guard);
+ let origin = stylesheet.origin(guard);
+ let origin_cascade_data =
+ self.cascade_data.borrow_for_origin(&origin);
+
let effective_then =
- self.effective_media_query_results.was_effective(stylesheet);
+ origin_cascade_data
+ .effective_media_query_results
+ .was_effective(stylesheet);
if effective_now != effective_then {
debug!(" > Stylesheet changed -> {}, {}",
effective_then, effective_now);
return true
}
if !effective_now {
@@ -989,34 +995,38 @@ impl Stylist {
continue;
}
CssRule::Import(ref lock) => {
let import_rule = lock.read_with(guard);
let effective_now =
import_rule.stylesheet
.is_effective_for_device(&self.device, guard);
let effective_then =
- self.effective_media_query_results.was_effective(import_rule);
+ origin_cascade_data
+ .effective_media_query_results
+ .was_effective(import_rule);
if effective_now != effective_then {
debug!(" > @import rule changed {} -> {}",
effective_then, effective_now);
return true;
}
if !effective_now {
iter.skip_children();
}
}
CssRule::Media(ref lock) => {
let media_rule = lock.read_with(guard);
let mq = media_rule.media_queries.read_with(guard);
let effective_now =
mq.evaluate(&self.device, self.quirks_mode);
let effective_then =
- self.effective_media_query_results.was_effective(media_rule);
+ origin_cascade_data
+ .effective_media_query_results
+ .was_effective(media_rule);
if effective_now != effective_then {
debug!(" > @media rule changed {} -> {}",
effective_then, effective_now);
return true;
}
if !effective_now {
iter.skip_children();
@@ -1607,16 +1617,19 @@ struct CascadeData {
mapped_ids: NonCountingBloomFilter,
/// Selectors that require explicit cache revalidation (i.e. which depend
/// on state that is not otherwise visible to the cache, like attributes or
/// tree-structural state like child index and pseudos).
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
selectors_for_cache_revalidation: SelectorMap<RevalidationSelectorAndHashes>,
+ /// Effective media query results cached from the last rebuild.
+ effective_media_query_results: EffectiveMediaQueryResults,
+
/// The total number of selectors.
num_selectors: usize,
/// The total number of declarations.
num_declarations: usize,
}
impl CascadeData {
@@ -1626,16 +1639,17 @@ impl CascadeData {
pseudos_map: PerPseudoElementMap::default(),
animations: Default::default(),
invalidation_map: InvalidationMap::new(),
attribute_dependencies: NonCountingBloomFilter::new(),
style_attribute_dependency: false,
state_dependencies: ElementState::empty(),
mapped_ids: NonCountingBloomFilter::new(),
selectors_for_cache_revalidation: SelectorMap::new(),
+ effective_media_query_results: EffectiveMediaQueryResults::new(),
num_selectors: 0,
num_declarations: 0,
}
}
#[inline]
fn borrow_for_pseudo(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
match pseudo {
@@ -1655,16 +1669,17 @@ impl PerOriginClear for CascadeData {
self.pseudos_map = Default::default();
self.animations = Default::default();
self.invalidation_map.clear();
self.attribute_dependencies.clear();
self.style_attribute_dependency = false;
self.state_dependencies = ElementState::empty();
self.mapped_ids.clear();
self.selectors_for_cache_revalidation = SelectorMap::new();
+ self.effective_media_query_results.clear();
self.num_selectors = 0;
self.num_declarations = 0;
}
}
impl Default for CascadeData {
fn default() -> Self {
CascadeData::new()