style: Add a StylesheetFlusher abstraction to enable more incremental rebuilds.

MozReview-Commit-ID: 8RBUUErm4bm
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Emilio Cobos Álvarez 2017-08-22 15:48:38 +02:00
parent 029ab24671
commit 15594dda10
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 105 additions and 42 deletions

View file

@ -47,6 +47,77 @@ where
}
}
/// 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,
author_style_disabled: bool,
had_invalidations: bool,
}
/// The type of rebuild that we need to do for a given stylesheet.
pub enum SheetRebuildKind {
/// For now we only support full rebuilds, in the future we'll implement
/// partial rebuilds.
Full,
}
impl<'a, 'b, S> StylesheetFlusher<'a, 'b, S>
where
'b: 'a,
S: StylesheetInDocument + PartialEq + 'static,
{
/// The set of origins to fully rebuild, which need to be cleared
/// beforehand.
pub fn origins_to_fully_rebuild(&self) -> OriginSet {
self.origins_dirty
}
/// 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
}
}
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> {
loop {
let potential_sheet = match self.iter.next() {
None => return None,
Some(s) => s,
};
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;
}
return Some((&potential_sheet.sheet, SheetRebuildKind::Full))
}
}
}
/// The set of stylesheets effective for a given document.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct StylesheetSet<S>
@ -189,12 +260,13 @@ where
!self.origins_dirty.is_empty()
}
/// Flush the current set, unmarking it as dirty, and returns the damaged
/// origins, and whether 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>,
) -> (OriginSet, bool)
guard: &'a SharedRwLockReadGuard<'b>,
) -> StylesheetFlusher<'a, 'b, S>
where
E: TElement,
{
@ -202,10 +274,16 @@ where
debug!("StylesheetSet::flush");
let have_invalidations = self.invalidations.flush(document_element);
let origins = mem::replace(&mut self.origins_dirty, OriginSet::empty());
let had_invalidations = self.invalidations.flush(document_element);
let origins_dirty = mem::replace(&mut self.origins_dirty, OriginSet::empty());
(origins, have_invalidations)
StylesheetFlusher {
iter: self.entries.iter_mut(),
author_style_disabled: self.author_style_disabled,
had_invalidations,
origins_dirty,
guard,
}
}
/// Flush stylesheets, but without running any of the invalidation passes.