aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/stylesheet_set.rs303
-rw-r--r--components/style/stylesheets/origin.rs1
-rw-r--r--components/style/stylist.rs212
3 files changed, 356 insertions, 160 deletions
diff --git a/components/style/stylesheet_set.rs b/components/style/stylesheet_set.rs
index 8548ac53f01..01e8bedc133 100644
--- a/components/style/stylesheet_set.rs
+++ b/components/style/stylesheet_set.rs
@@ -9,16 +9,25 @@ use invalidation::stylesheets::StylesheetInvalidationSet;
use media_queries::Device;
use shared_lock::SharedRwLockReadGuard;
use std::slice;
-use stylesheets::{OriginSet, PerOrigin, StylesheetInDocument};
+use stylesheets::{Origin, OriginSet, PerOrigin, StylesheetInDocument};
-/// Entry for a StylesheetSet. We don't bother creating a constructor, because
-/// there's no sensible defaults for the member variables.
+/// Entry for a StylesheetSet.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct StylesheetSetEntry<S>
+struct StylesheetSetEntry<S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
sheet: S,
+ dirty: bool,
+}
+
+impl<S> StylesheetSetEntry<S>
+where
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ fn new(sheet: S) -> Self {
+ Self { sheet, dirty: true }
+ }
}
/// A iterator over the stylesheets of a list of entries in the StylesheetSet.
@@ -38,6 +47,136 @@ where
}
}
+/// The validity of the data in a given cascade origin.
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum OriginValidity {
+ /// The origin is clean, all the data already there is valid, though we may
+ /// have new sheets at the end.
+ Valid = 0,
+
+ /// The cascade data is invalid, but not the invalidation data (which is
+ /// order-independent), and thus only the cascade data should be inserted.
+ CascadeInvalid = 1,
+
+ /// Everything needs to be rebuilt.
+ FullyInvalid = 2,
+}
+
+impl Default for OriginValidity {
+ fn default() -> Self {
+ OriginValidity::Valid
+ }
+}
+
+/// A struct to iterate over the different stylesheets to be flushed.
+pub struct StylesheetFlusher<'a, 'b, S>
+where
+ 'b: 'a,
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ iter: slice::IterMut<'a, StylesheetSetEntry<S>>,
+ guard: &'a SharedRwLockReadGuard<'b>,
+ origins_dirty: OriginSet,
+ origin_data_validity: PerOrigin<OriginValidity>,
+ author_style_disabled: bool,
+ had_invalidations: bool,
+}
+
+/// The type of rebuild that we need to do for a given stylesheet.
+pub enum SheetRebuildKind {
+ /// A full rebuild, of both cascade data and invalidation data.
+ Full,
+ /// A partial rebuild, of only the cascade data.
+ CascadeOnly,
+}
+
+impl SheetRebuildKind {
+ /// Whether the stylesheet invalidation data should be rebuilt.
+ pub fn should_rebuild_invalidation(&self) -> bool {
+ matches!(*self, SheetRebuildKind::Full)
+ }
+}
+
+impl<'a, 'b, S> StylesheetFlusher<'a, 'b, S>
+where
+ 'b: 'a,
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ /// The data validity for a given origin.
+ pub fn origin_validity(&self, origin: Origin) -> OriginValidity {
+ *self.origin_data_validity.borrow_for_origin(&origin)
+ }
+
+ /// Returns whether running the whole flushing process would be a no-op.
+ pub fn nothing_to_do(&self) -> bool {
+ self.origins_dirty.is_empty()
+ }
+
+ /// Returns whether any DOM invalidations were processed as a result of the
+ /// stylesheet flush.
+ pub fn had_invalidations(&self) -> bool {
+ self.had_invalidations
+ }
+}
+
+#[cfg(debug_assertions)]
+impl<'a, 'b, S> Drop for StylesheetFlusher<'a, 'b, S>
+where
+ 'b: 'a,
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ fn drop(&mut self) {
+ debug_assert!(
+ self.iter.next().is_none(),
+ "You're supposed to fully consume the flusher"
+ );
+ }
+}
+
+impl<'a, 'b, S> Iterator for StylesheetFlusher<'a, 'b, S>
+where
+ 'b: 'a,
+ S: StylesheetInDocument + PartialEq + 'static,
+{
+ type Item = (&'a S, SheetRebuildKind);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ use std::mem;
+
+ loop {
+ let potential_sheet = match self.iter.next() {
+ None => return None,
+ Some(s) => s,
+ };
+
+ let dirty = mem::replace(&mut potential_sheet.dirty, false);
+
+ if dirty {
+ // If the sheet was dirty, we need to do a full rebuild anyway.
+ return Some((&potential_sheet.sheet, SheetRebuildKind::Full))
+ }
+
+ let origin = potential_sheet.sheet.contents(self.guard).origin;
+ if !self.origins_dirty.contains(origin.into()) {
+ continue;
+ }
+
+ if self.author_style_disabled && matches!(origin, Origin::Author) {
+ continue;
+ }
+
+ let rebuild_kind = match self.origin_validity(origin) {
+ OriginValidity::Valid => continue,
+ OriginValidity::CascadeInvalid => SheetRebuildKind::CascadeOnly,
+ OriginValidity::FullyInvalid => SheetRebuildKind::Full,
+ };
+
+ return Some((&potential_sheet.sheet, rebuild_kind));
+ }
+ }
+}
+
/// The set of stylesheets effective for a given document.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct StylesheetSet<S>
@@ -51,8 +190,19 @@ where
/// include recursive `@import` rules.
entries: Vec<StylesheetSetEntry<S>>,
- /// Per-origin stylesheet invalidation data.
- invalidation_data: PerOrigin<InvalidationData>,
+ /// The invalidations for stylesheets added or removed from this document.
+ invalidations: StylesheetInvalidationSet,
+
+ /// The origins whose stylesheets have changed so far.
+ origins_dirty: OriginSet,
+
+ /// The validity of the data that was already there for a given origin.
+ ///
+ /// Note that an origin may appear on `origins_dirty`, but still have
+ /// `OriginValidity::Valid`, if only sheets have been appended into it (in
+ /// which case the existing data is valid, but the origin needs to be
+ /// rebuilt).
+ origin_data_validity: PerOrigin<OriginValidity>,
/// Has author style been disabled?
author_style_disabled: bool,
@@ -66,7 +216,9 @@ where
pub fn new() -> Self {
StylesheetSet {
entries: vec![],
- invalidation_data: Default::default(),
+ invalidations: StylesheetInvalidationSet::new(),
+ origins_dirty: OriginSet::empty(),
+ origin_data_validity: Default::default(),
author_style_disabled: false,
}
}
@@ -97,12 +249,28 @@ where
sheet: &S,
guard: &SharedRwLockReadGuard,
) {
- let origin = sheet.contents(guard).origin;
- let data = self.invalidation_data.borrow_mut_for_origin(&origin);
if let Some(device) = device {
- data.invalidations.collect_invalidations_for(device, sheet, guard);
+ self.invalidations.collect_invalidations_for(device, sheet, guard);
}
- data.dirty = true;
+ self.origins_dirty |= sheet.contents(guard).origin;
+ }
+
+ fn set_data_validity_at_least(
+ &mut self,
+ origin: Origin,
+ validity: OriginValidity,
+ ) {
+ use std::cmp;
+
+ debug_assert!(
+ self.origins_dirty.contains(origin.into()),
+ "data_validity should be a subset of origins_dirty"
+ );
+
+ let existing_validity =
+ self.origin_data_validity.borrow_mut_for_origin(&origin);
+
+ *existing_validity = cmp::max(*existing_validity, validity);
}
/// Appends a new stylesheet to the current set.
@@ -117,7 +285,9 @@ where
debug!("StylesheetSet::append_stylesheet");
self.remove_stylesheet_if_present(&sheet);
self.collect_invalidations_for(device, &sheet, guard);
- self.entries.push(StylesheetSetEntry { sheet });
+ // Appending sheets doesn't alter the validity of the existing data, so
+ // we don't need to change `origin_data_validity` here.
+ self.entries.push(StylesheetSetEntry::new(sheet));
}
/// Prepend a new stylesheet to the current set.
@@ -130,7 +300,12 @@ where
debug!("StylesheetSet::prepend_stylesheet");
self.remove_stylesheet_if_present(&sheet);
self.collect_invalidations_for(device, &sheet, guard);
- self.entries.insert(0, StylesheetSetEntry { sheet });
+
+ // Inserting stylesheets somewhere but at the end changes the validity
+ // of the cascade data, but not the invalidation data.
+ self.set_data_validity_at_least(sheet.contents(guard).origin, OriginValidity::CascadeInvalid);
+
+ self.entries.insert(0, StylesheetSetEntry::new(sheet));
}
/// Insert a given stylesheet before another stylesheet in the document.
@@ -147,7 +322,11 @@ where
entry.sheet == before_sheet
}).expect("`before_sheet` stylesheet not found");
self.collect_invalidations_for(device, &sheet, guard);
- self.entries.insert(index, StylesheetSetEntry { sheet });
+
+ // Inserting stylesheets somewhere but at the end changes the validity
+ // of the cascade data, but not the invalidation data.
+ self.set_data_validity_at_least(sheet.contents(guard).origin, OriginValidity::CascadeInvalid);
+ self.entries.insert(index, StylesheetSetEntry::new(sheet));
}
/// Remove a given stylesheet from the set.
@@ -159,7 +338,12 @@ where
) {
debug!("StylesheetSet::remove_stylesheet");
self.remove_stylesheet_if_present(&sheet);
+
self.collect_invalidations_for(device, &sheet, guard);
+
+ // Removing sheets makes us tear down the whole cascade and invalidation
+ // data.
+ self.set_data_validity_at_least(sheet.contents(guard).origin, OriginValidity::FullyInvalid);
}
/// Notes that the author style has been disabled for this document.
@@ -169,61 +353,53 @@ where
return;
}
self.author_style_disabled = disabled;
- self.invalidation_data.author.invalidations.invalidate_fully();
- self.invalidation_data.author.dirty = true;
+ self.invalidations.invalidate_fully();
+ self.origins_dirty |= Origin::Author;
}
/// Returns whether the given set has changed from the last flush.
pub fn has_changed(&self) -> bool {
- self.invalidation_data
- .iter_origins()
- .any(|(d, _)| d.dirty)
+ !self.origins_dirty.is_empty()
}
- /// Flush the current set, unmarking it as dirty, and returns an iterator
- /// over the new stylesheet list.
- ///
- /// Returns true if any elements were invalidated.
- pub fn flush<E>(
- &mut self,
+ /// Flush the current set, unmarking it as dirty, and returns a
+ /// `StylesheetFlusher` in order to rebuild the stylist.
+ pub fn flush<'a, 'b, E>(
+ &'a mut self,
document_element: Option<E>,
- ) -> (StylesheetIterator<S>, OriginSet, bool)
+ guard: &'a SharedRwLockReadGuard<'b>,
+ ) -> StylesheetFlusher<'a, 'b, S>
where
E: TElement,
{
+ use std::mem;
+
debug!("StylesheetSet::flush");
- let mut origins = OriginSet::empty();
- let mut have_invalidations = false;
- for (data, origin) in self.invalidation_data.iter_mut_origins() {
- if data.dirty {
- have_invalidations |= data.invalidations.flush(document_element);
- data.dirty = false;
- origins |= origin;
- }
+ let had_invalidations = self.invalidations.flush(document_element);
+ let origins_dirty = mem::replace(&mut self.origins_dirty, OriginSet::empty());
+ let origin_data_validity =
+ mem::replace(&mut self.origin_data_validity, Default::default());
+
+ StylesheetFlusher {
+ iter: self.entries.iter_mut(),
+ author_style_disabled: self.author_style_disabled,
+ had_invalidations,
+ origins_dirty,
+ origin_data_validity,
+ guard,
}
-
- (self.iter(), origins, have_invalidations)
}
/// Flush stylesheets, but without running any of the invalidation passes.
- ///
- /// FIXME(emilio): This should eventually disappear. Please keep this
- /// Servo-only.
#[cfg(feature = "servo")]
- pub fn flush_without_invalidation(&mut self) -> (StylesheetIterator<S>, OriginSet) {
- debug!("StylesheetSet::flush_without_invalidation");
+ pub fn flush_without_invalidation(&mut self) -> OriginSet {
+ use std::mem;
- let mut origins = OriginSet::empty();
- for (data, origin) in self.invalidation_data.iter_mut_origins() {
- if data.dirty {
- data.invalidations.clear();
- data.dirty = false;
- origins |= origin;
- }
- }
+ debug!("StylesheetSet::flush_without_invalidation");
- (self.iter(), origins)
+ self.invalidations.clear();
+ mem::replace(&mut self.origins_dirty, OriginSet::empty())
}
/// Returns an iterator over the current list of stylesheets.
@@ -234,30 +410,11 @@ where
/// Mark the stylesheets for the specified origin as dirty, because
/// something external may have invalidated it.
pub fn force_dirty(&mut self, origins: OriginSet) {
+ self.invalidations.invalidate_fully();
+ self.origins_dirty |= origins;
for origin in origins.iter() {
- let data = self.invalidation_data.borrow_mut_for_origin(&origin);
- data.invalidations.invalidate_fully();
- data.dirty = true;
- }
- }
-}
-
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-struct InvalidationData {
- /// The stylesheet invalidations for this origin that we still haven't
- /// processed.
- invalidations: StylesheetInvalidationSet,
-
- /// Whether the sheets for this origin in the `StylesheetSet`'s entry list
- /// has changed since the last restyle.
- dirty: bool,
-}
-
-impl Default for InvalidationData {
- fn default() -> Self {
- InvalidationData {
- invalidations: StylesheetInvalidationSet::new(),
- dirty: false,
+ // We don't know what happened, assume the worse.
+ self.set_data_validity_at_least(origin, OriginValidity::FullyInvalid);
}
}
}
diff --git a/components/style/stylesheets/origin.rs b/components/style/stylesheets/origin.rs
index 1eb3c4932f1..29f5fdae16b 100644
--- a/components/style/stylesheets/origin.rs
+++ b/components/style/stylesheets/origin.rs
@@ -40,6 +40,7 @@ impl Origin {
bitflags! {
/// A set of origins. This is equivalent to Gecko's OriginFlags.
+ #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub flags OriginSet: u8 {
/// https://drafts.csswg.org/css-cascade/#cascade-origin-user-agent
const ORIGIN_USER_AGENT = Origin::UserAgent as u8,
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index 2ea8d5313ac..bd3c30cce05 100644
--- a/components/style/stylist.rs
+++ b/components/style/stylist.rs
@@ -38,7 +38,7 @@ use smallvec::VecLike;
use std::fmt::Debug;
use std::ops;
use style_traits::viewport::ViewportConstraints;
-use stylesheet_set::{StylesheetSet, StylesheetIterator};
+use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, StylesheetIterator, StylesheetFlusher};
#[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule};
use stylesheets::{CssRule, StyleRule};
@@ -83,33 +83,44 @@ impl DocumentCascadeData {
/// Rebuild the cascade data for the given document stylesheets, and
/// optionally with a set of user agent stylesheets.
- fn rebuild<'a, I, S>(
+ fn rebuild<'a, 'b, S>(
&mut self,
device: &Device,
quirks_mode: QuirksMode,
- doc_stylesheets: I,
+ flusher: StylesheetFlusher<'a, 'b, S>,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
- author_style_disabled: bool,
extra_data: &mut PerOrigin<ExtraStyleData>,
- origins_to_rebuild: OriginSet,
)
where
- I: Iterator<Item = &'a S> + Clone,
- S: StylesheetInDocument + ToMediaListKey + 'static,
+ 'b: 'a,
+ S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
{
- debug_assert!(!origins_to_rebuild.is_empty());
+ debug_assert!(!flusher.nothing_to_do());
- for origin in origins_to_rebuild.iter() {
- extra_data.borrow_mut_for_origin(&origin).clear();
- self.per_origin.borrow_mut_for_origin(&origin).clear();
- }
+ for (cascade_data, origin) in self.per_origin.iter_mut_origins() {
+ let validity = flusher.origin_validity(origin);
- if origins_to_rebuild.contains(Origin::UserAgent.into()) {
- self.precomputed_pseudo_element_decls.clear();
+ if validity == OriginValidity::Valid {
+ continue;
+ }
+
+ if origin == Origin::UserAgent {
+ self.precomputed_pseudo_element_decls.clear();
+ }
+
+ extra_data.borrow_mut_for_origin(&origin).clear();
+ if validity == OriginValidity::CascadeInvalid {
+ cascade_data.clear_cascade_data()
+ } else {
+ debug_assert_eq!(validity, OriginValidity::FullyInvalid);
+ cascade_data.clear();
+ }
}
if let Some(ua_stylesheets) = ua_stylesheets {
+ debug_assert!(cfg!(feature = "servo"));
+
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
let sheet_origin =
stylesheet.contents(guards.ua_or_user).origin;
@@ -119,15 +130,26 @@ impl DocumentCascadeData {
Origin::UserAgent | Origin::User
));
- if origins_to_rebuild.contains(sheet_origin.into()) {
- self.add_stylesheet(
- device,
- quirks_mode,
- stylesheet,
- guards.ua_or_user,
- extra_data,
- );
+ let validity = flusher.origin_validity(sheet_origin);
+
+ // Servo doesn't support to incrementally mutate UA sheets.
+ debug_assert!(matches!(
+ validity,
+ OriginValidity::Valid | OriginValidity::FullyInvalid
+ ));
+
+ if validity == OriginValidity::Valid {
+ continue;
}
+
+ self.add_stylesheet(
+ device,
+ quirks_mode,
+ stylesheet,
+ guards.ua_or_user,
+ extra_data,
+ SheetRebuildKind::Full,
+ );
}
if quirks_mode != QuirksMode::NoQuirks {
@@ -140,34 +162,35 @@ impl DocumentCascadeData {
Origin::UserAgent | Origin::User
));
- if origins_to_rebuild.contains(sheet_origin.into()) {
+ let validity = flusher.origin_validity(sheet_origin);
+
+ // Servo doesn't support to incrementally mutate UA sheets.
+ debug_assert!(matches!(
+ validity,
+ OriginValidity::Valid | OriginValidity::FullyInvalid
+ ));
+
+ if validity != OriginValidity::Valid {
self.add_stylesheet(
device,
quirks_mode,
&ua_stylesheets.quirks_mode_stylesheet,
guards.ua_or_user,
- extra_data
+ extra_data,
+ SheetRebuildKind::Full,
);
}
}
}
- // Only add stylesheets for origins we are updating, and only add
- // Author level sheets if author style is not disabled.
- let sheets_to_add = doc_stylesheets.filter(|s| {
- let sheet_origin = s.contents(guards.author).origin;
-
- origins_to_rebuild.contains(sheet_origin.into()) &&
- (!matches!(sheet_origin, Origin::Author) || !author_style_disabled)
- });
-
- for stylesheet in sheets_to_add {
+ for (stylesheet, rebuild_kind) in flusher {
self.add_stylesheet(
device,
quirks_mode,
stylesheet,
guards.author,
- extra_data
+ extra_data,
+ rebuild_kind,
);
}
}
@@ -178,7 +201,8 @@ impl DocumentCascadeData {
quirks_mode: QuirksMode,
stylesheet: &S,
guard: &SharedRwLockReadGuard,
- _extra_data: &mut PerOrigin<ExtraStyleData>
+ _extra_data: &mut PerOrigin<ExtraStyleData>,
+ rebuild_kind: SheetRebuildKind,
)
where
S: StylesheetInDocument + ToMediaListKey + 'static,
@@ -192,9 +216,11 @@ impl DocumentCascadeData {
let origin_cascade_data =
self.per_origin.borrow_mut_for_origin(&origin);
- origin_cascade_data
- .effective_media_query_results
- .saw_effective(stylesheet);
+ if rebuild_kind.should_rebuild_invalidation() {
+ origin_cascade_data
+ .effective_media_query_results
+ .saw_effective(stylesheet);
+ }
for rule in stylesheet.effective_rules(device, guard) {
match *rule {
@@ -248,43 +274,49 @@ impl DocumentCascadeData {
map.insert(rule, quirks_mode);
- origin_cascade_data
- .invalidation_map
- .note_selector(selector, quirks_mode);
- let mut visitor = StylistSelectorVisitor {
- needs_revalidation: false,
- passed_rightmost_selector: false,
- attribute_dependencies: &mut origin_cascade_data.attribute_dependencies,
- style_attribute_dependency: &mut origin_cascade_data.style_attribute_dependency,
- state_dependencies: &mut origin_cascade_data.state_dependencies,
- mapped_ids: &mut origin_cascade_data.mapped_ids,
- };
-
- selector.visit(&mut visitor);
-
- if visitor.needs_revalidation {
- origin_cascade_data.selectors_for_cache_revalidation.insert(
- RevalidationSelectorAndHashes::new(selector.clone(), hashes),
- quirks_mode
- );
+ if rebuild_kind.should_rebuild_invalidation() {
+ origin_cascade_data
+ .invalidation_map
+ .note_selector(selector, quirks_mode);
+ let mut visitor = StylistSelectorVisitor {
+ needs_revalidation: false,
+ passed_rightmost_selector: false,
+ attribute_dependencies: &mut origin_cascade_data.attribute_dependencies,
+ style_attribute_dependency: &mut origin_cascade_data.style_attribute_dependency,
+ state_dependencies: &mut origin_cascade_data.state_dependencies,
+ mapped_ids: &mut origin_cascade_data.mapped_ids,
+ };
+
+ selector.visit(&mut visitor);
+
+ if visitor.needs_revalidation {
+ origin_cascade_data.selectors_for_cache_revalidation.insert(
+ RevalidationSelectorAndHashes::new(selector.clone(), hashes),
+ quirks_mode
+ );
+ }
}
}
origin_cascade_data.rules_source_order += 1;
}
CssRule::Import(ref lock) => {
- let import_rule = lock.read_with(guard);
- origin_cascade_data
- .effective_media_query_results
- .saw_effective(import_rule);
+ if rebuild_kind.should_rebuild_invalidation() {
+ let import_rule = lock.read_with(guard);
+ 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);
- origin_cascade_data
- .effective_media_query_results
- .saw_effective(media_rule);
+ if rebuild_kind.should_rebuild_invalidation() {
+ let media_rule = lock.read_with(guard);
+ origin_cascade_data
+ .effective_media_query_results
+ .saw_effective(media_rule);
+ }
}
CssRule::Keyframes(ref keyframes_rule) => {
let keyframes_rule = keyframes_rule.read_with(guard);
@@ -489,14 +521,6 @@ impl Stylist {
return false;
}
- let author_style_disabled = self.stylesheets.author_style_disabled();
- let (doc_stylesheets, origins_to_rebuild, have_invalidations) =
- self.stylesheets.flush(document_element);
-
- if origins_to_rebuild.is_empty() {
- return have_invalidations;
- }
-
self.num_rebuilds += 1;
// Update viewport_constraints regardless of which origins'
@@ -515,32 +539,38 @@ impl Stylist {
// queries defined?)
let cascaded_rule = ViewportRule {
declarations: viewport_rule::Cascade::from_stylesheets(
- doc_stylesheets.clone(), guards.author, &self.device
+ self.stylesheets.iter(),
+ guards.author,
+ &self.device,
).finish()
};
self.viewport_constraints =
- ViewportConstraints::maybe_new(&self.device,
- &cascaded_rule,
- self.quirks_mode);
+ ViewportConstraints::maybe_new(
+ &self.device,
+ &cascaded_rule,
+ self.quirks_mode,
+ );
if let Some(ref constraints) = self.viewport_constraints {
self.device.account_for_viewport_rule(constraints);
}
}
+ let flusher = self.stylesheets.flush(document_element, &guards.author);
+
+ let had_invalidations = flusher.had_invalidations();
+
self.cascade_data.rebuild(
&self.device,
self.quirks_mode,
- doc_stylesheets,
+ flusher,
guards,
ua_sheets,
- author_style_disabled,
extra_data,
- origins_to_rebuild,
);
- have_invalidations
+ had_invalidations
}
/// Insert a given stylesheet before another stylesheet in the document.
@@ -1689,6 +1719,9 @@ impl<'a> SelectorVisitor for StylistSelectorVisitor<'a> {
/// Data resulting from performing the CSS cascade that is specific to a given
/// origin.
+///
+/// FIXME(emilio): Consider renaming and splitting in `CascadeData` and
+/// `InvalidationData`? That'd make `clear_cascade_data()` clearer.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug)]
struct CascadeData {
@@ -1784,20 +1817,25 @@ impl CascadeData {
self.pseudos_map.get(pseudo).is_some()
}
- fn clear(&mut self) {
+ /// Clears the cascade data, but not the invalidation data.
+ fn clear_cascade_data(&mut self) {
self.element_map.clear();
self.pseudos_map.clear();
self.animations.clear();
+ self.rules_source_order = 0;
+ self.num_selectors = 0;
+ self.num_declarations = 0;
+ }
+
+ fn clear(&mut self) {
+ self.clear_cascade_data();
+ self.effective_media_query_results.clear();
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.clear();
- self.effective_media_query_results.clear();
- self.rules_source_order = 0;
- self.num_selectors = 0;
- self.num_declarations = 0;
}
}