mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
style: Share user agent cascade data across documents.
MozReview-Commit-ID: KcyuTHD0bt9 Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
parent
985c6193eb
commit
cb31e782aa
4 changed files with 326 additions and 118 deletions
|
@ -31,11 +31,20 @@ where
|
|||
}
|
||||
|
||||
/// A iterator over the stylesheets of a list of entries in the StylesheetSet.
|
||||
#[derive(Clone)]
|
||||
pub struct StylesheetCollectionIterator<'a, S>(slice::Iter<'a, StylesheetSetEntry<S>>)
|
||||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static;
|
||||
|
||||
impl<'a, S> Clone for StylesheetCollectionIterator<'a, S>
|
||||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
StylesheetCollectionIterator(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, S> Iterator for StylesheetCollectionIterator<'a, S>
|
||||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static,
|
||||
|
@ -119,11 +128,8 @@ pub struct StylesheetFlusher<'a, S>
|
|||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static,
|
||||
{
|
||||
origins_dirty: OriginSetIterator,
|
||||
// NB: Bound to the StylesheetSet lifetime when constructed, see
|
||||
// StylesheetSet::flush.
|
||||
collections: *mut PerOrigin<SheetCollection<S>>,
|
||||
current: Option<(Origin, slice::IterMut<'a, StylesheetSetEntry<S>>)>,
|
||||
origins_dirty: OriginSet,
|
||||
collections: &'a mut PerOrigin<SheetCollection<S>>,
|
||||
origin_data_validity: PerOrigin<OriginValidity>,
|
||||
author_style_disabled: bool,
|
||||
had_invalidations: bool,
|
||||
|
@ -153,9 +159,56 @@ where
|
|||
*self.origin_data_validity.borrow_for_origin(&origin)
|
||||
}
|
||||
|
||||
/// Whether the origin data is dirty in any way.
|
||||
pub fn origin_dirty(&self, origin: Origin) -> bool {
|
||||
self.origins_dirty.contains(origin.into())
|
||||
}
|
||||
|
||||
/// Returns an iterator over the stylesheets of a given origin, assuming all
|
||||
/// of them will be flushed.
|
||||
pub fn manual_origin_sheets<'b>(&'b mut self, origin: Origin) -> StylesheetCollectionIterator<'b, S>
|
||||
where
|
||||
'a: 'b
|
||||
{
|
||||
debug_assert_eq!(origin, Origin::UserAgent);
|
||||
|
||||
// We could iterate over `origin_sheets(origin)` to ensure state is
|
||||
// consistent (that the `dirty` member of the Entry is reset to
|
||||
// `false`).
|
||||
//
|
||||
// In practice it doesn't matter for correctness given our use of it
|
||||
// (that this is UA only).
|
||||
self.collections.borrow_for_origin(&origin).iter()
|
||||
}
|
||||
|
||||
/// Returns a flusher for the dirty origin `origin`.
|
||||
pub fn origin_sheets<'b>(&'b mut self, origin: Origin) -> PerOriginFlusher<'b, S>
|
||||
where
|
||||
'a: 'b
|
||||
{
|
||||
let validity = self.origin_validity(origin);
|
||||
let origin_dirty = self.origins_dirty.contains(origin.into());
|
||||
|
||||
debug_assert!(
|
||||
origin_dirty || validity == OriginValidity::Valid,
|
||||
"origin_data_validity should be a subset of origins_dirty!"
|
||||
);
|
||||
|
||||
if self.author_style_disabled && origin == Origin::Author {
|
||||
return PerOriginFlusher {
|
||||
iter: [].iter_mut(),
|
||||
validity,
|
||||
}
|
||||
}
|
||||
PerOriginFlusher {
|
||||
iter: self.collections.borrow_mut_for_origin(&origin).entries.iter_mut(),
|
||||
validity,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether running the whole flushing process would be a no-op.
|
||||
pub fn nothing_to_do(&self) -> bool {
|
||||
self.origins_dirty.clone().next().is_none()
|
||||
self.origins_dirty.is_empty()
|
||||
}
|
||||
|
||||
/// Returns whether any DOM invalidations were processed as a result of the
|
||||
|
@ -165,81 +218,44 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl<'a, S> Drop for StylesheetFlusher<'a, S>
|
||||
/// A flusher struct for a given origin, that takes care of returning the
|
||||
/// appropriate stylesheets that need work.
|
||||
pub struct PerOriginFlusher<'a, S>
|
||||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static,
|
||||
S: StylesheetInDocument + PartialEq + 'static
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
debug_assert!(
|
||||
self.origins_dirty.next().is_none(),
|
||||
"You're supposed to fully consume the flusher"
|
||||
);
|
||||
}
|
||||
iter: slice::IterMut<'a, StylesheetSetEntry<S>>,
|
||||
validity: OriginValidity,
|
||||
}
|
||||
|
||||
impl<'a, S> Iterator for StylesheetFlusher<'a, S>
|
||||
impl<'a, S> Iterator for PerOriginFlusher<'a, S>
|
||||
where
|
||||
S: StylesheetInDocument + PartialEq + 'static,
|
||||
{
|
||||
type Item = (&'a S, Origin, SheetRebuildKind);
|
||||
type Item = (&'a S, SheetRebuildKind);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
use std::mem;
|
||||
|
||||
loop {
|
||||
if self.current.is_none() {
|
||||
let next_origin = match self.origins_dirty.next() {
|
||||
Some(o) => o,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
// Should've been cleared already.
|
||||
debug_assert_eq!(
|
||||
unsafe { &*self.collections }
|
||||
.borrow_for_origin(&next_origin)
|
||||
.data_validity,
|
||||
OriginValidity::Valid
|
||||
);
|
||||
|
||||
self.current =
|
||||
Some((
|
||||
next_origin,
|
||||
unsafe { &mut *self.collections }
|
||||
.borrow_mut_for_origin(&next_origin)
|
||||
.entries
|
||||
.iter_mut()
|
||||
));
|
||||
}
|
||||
|
||||
let potential_sheet = match self.current.as_mut().unwrap().1.next() {
|
||||
let potential_sheet = match self.iter.next() {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
self.current = None;
|
||||
continue;
|
||||
}
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let origin = self.current.as_ref().unwrap().0;
|
||||
|
||||
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, origin, SheetRebuildKind::Full))
|
||||
return Some((&potential_sheet.sheet, SheetRebuildKind::Full))
|
||||
}
|
||||
|
||||
if self.author_style_disabled && matches!(origin, Origin::Author) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let rebuild_kind = match self.origin_validity(origin) {
|
||||
let rebuild_kind = match self.validity {
|
||||
OriginValidity::Valid => continue,
|
||||
OriginValidity::CascadeInvalid => SheetRebuildKind::CascadeOnly,
|
||||
OriginValidity::FullyInvalid => SheetRebuildKind::Full,
|
||||
};
|
||||
|
||||
return Some((&potential_sheet.sheet, origin, rebuild_kind));
|
||||
return Some((&potential_sheet.sheet, rebuild_kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -501,10 +517,10 @@ where
|
|||
|
||||
let had_invalidations = self.invalidations.flush(document_element);
|
||||
let origins_dirty =
|
||||
mem::replace(&mut self.origins_dirty, OriginSet::empty()).iter();
|
||||
mem::replace(&mut self.origins_dirty, OriginSet::empty());
|
||||
|
||||
let mut origin_data_validity = PerOrigin::<OriginValidity>::default();
|
||||
for origin in origins_dirty.clone() {
|
||||
for origin in origins_dirty.iter() {
|
||||
let collection = self.collections.borrow_mut_for_origin(&origin);
|
||||
*origin_data_validity.borrow_mut_for_origin(&origin) =
|
||||
mem::replace(&mut collection.data_validity, OriginValidity::Valid);
|
||||
|
@ -516,7 +532,6 @@ where
|
|||
had_invalidations,
|
||||
origins_dirty,
|
||||
origin_data_validity,
|
||||
current: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue