style: Unify how servo and Gecko handle UA sheets.

This commit is contained in:
Emilio Cobos Álvarez 2017-09-14 13:10:29 +02:00
parent 2cbd27c83a
commit 0a9309aa96
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
11 changed files with 122 additions and 161 deletions

View file

@ -155,7 +155,6 @@ impl PerDocumentStyleDataImpl {
{
self.stylist.flush(
&StylesheetGuards::same(guard),
/* ua_sheets = */ None,
document_element,
)
}

View file

@ -13,6 +13,7 @@ use std::cell::UnsafeCell;
use std::fmt;
#[cfg(feature = "gecko")]
use std::ptr;
use stylesheets::Origin;
/// A shared read/write lock that can protect multiple objects.
///
@ -262,7 +263,7 @@ pub trait DeepCloneWithLock : Sized {
/// Guards for a document
#[derive(Clone)]
pub struct StylesheetGuards<'a> {
/// For author-origin stylesheets
/// For author-origin stylesheets.
pub author: &'a SharedRwLockReadGuard<'a>,
/// For user-agent-origin and user-origin stylesheets
@ -270,6 +271,14 @@ pub struct StylesheetGuards<'a> {
}
impl<'a> StylesheetGuards<'a> {
/// Get the guard for a given stylesheet origin.
pub fn for_origin(&self, origin: Origin) -> &SharedRwLockReadGuard<'a> {
match origin {
Origin::Author => &self.author,
_ => &self.ua_or_user,
}
}
/// Same guard for all origins
pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
StylesheetGuards {

View file

@ -59,14 +59,14 @@ where
{
origins: OriginSetIterator,
collections: &'a PerOrigin<SheetCollection<S>>,
current: Option<StylesheetCollectionIterator<'a, S>>,
current: Option<(Origin, StylesheetCollectionIterator<'a, S>)>,
}
impl<'a, S> Iterator for StylesheetIterator<'a, S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
type Item = &'a S;
type Item = (&'a S, Origin);
fn next(&mut self) -> Option<Self::Item> {
loop {
@ -77,11 +77,14 @@ where
};
self.current =
Some(self.collections.borrow_for_origin(&next_origin).iter());
Some((next_origin, self.collections.borrow_for_origin(&next_origin).iter()));
}
if let Some(s) = self.current.as_mut().unwrap().next() {
return Some(s)
{
let (origin, ref mut iter) = *self.current.as_mut().unwrap();
if let Some(s) = iter.next() {
return Some((s, origin))
}
}
self.current = None;
@ -112,17 +115,15 @@ impl Default for OriginValidity {
}
/// A struct to iterate over the different stylesheets to be flushed.
pub struct StylesheetFlusher<'a, 'b, S>
pub struct StylesheetFlusher<'a, S>
where
'b: 'a,
S: StylesheetInDocument + PartialEq + 'static,
{
guard: &'a SharedRwLockReadGuard<'b>,
origins_dirty: OriginSetIterator,
// NB: Bound to the StylesheetSet lifetime when constructed, see
// StylesheetSet::flush.
collections: *mut PerOrigin<SheetCollection<S>>,
current: Option<slice::IterMut<'a, StylesheetSetEntry<S>>>,
current: Option<(Origin, slice::IterMut<'a, StylesheetSetEntry<S>>)>,
origin_data_validity: PerOrigin<OriginValidity>,
author_style_disabled: bool,
had_invalidations: bool,
@ -143,9 +144,8 @@ impl SheetRebuildKind {
}
}
impl<'a, 'b, S> StylesheetFlusher<'a, 'b, S>
impl<'a, S> StylesheetFlusher<'a, S>
where
'b: 'a,
S: StylesheetInDocument + PartialEq + 'static,
{
/// The data validity for a given origin.
@ -166,9 +166,8 @@ where
}
#[cfg(debug_assertions)]
impl<'a, 'b, S> Drop for StylesheetFlusher<'a, 'b, S>
impl<'a, S> Drop for StylesheetFlusher<'a, S>
where
'b: 'a,
S: StylesheetInDocument + PartialEq + 'static,
{
fn drop(&mut self) {
@ -179,12 +178,11 @@ where
}
}
impl<'a, 'b, S> Iterator for StylesheetFlusher<'a, 'b, S>
impl<'a, S> Iterator for StylesheetFlusher<'a, S>
where
'b: 'a,
S: StylesheetInDocument + PartialEq + 'static,
{
type Item = (&'a S, SheetRebuildKind);
type Item = (&'a S, Origin, SheetRebuildKind);
fn next(&mut self) -> Option<Self::Item> {
use std::mem;
@ -205,10 +203,16 @@ where
);
self.current =
Some(unsafe { &mut *self.collections }.borrow_mut_for_origin(&next_origin).entries.iter_mut());
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().next() {
let potential_sheet = match self.current.as_mut().unwrap().1.next() {
Some(s) => s,
None => {
self.current = None;
@ -216,14 +220,15 @@ where
}
};
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, SheetRebuildKind::Full))
return Some((&potential_sheet.sheet, origin, SheetRebuildKind::Full))
}
let origin = potential_sheet.sheet.contents(self.guard).origin;
if self.author_style_disabled && matches!(origin, Origin::Author) {
continue;
}
@ -234,7 +239,7 @@ where
OriginValidity::FullyInvalid => SheetRebuildKind::Full,
};
return Some((&potential_sheet.sheet, rebuild_kind));
return Some((&potential_sheet.sheet, origin, rebuild_kind));
}
}
}
@ -483,11 +488,10 @@ where
/// Flush the current set, unmarking it as dirty, and returns a
/// `StylesheetFlusher` in order to rebuild the stylist.
pub fn flush<'a, 'b, E>(
pub fn flush<'a, E>(
&'a mut self,
document_element: Option<E>,
guard: &'a SharedRwLockReadGuard<'b>,
) -> StylesheetFlusher<'a, 'b, S>
) -> StylesheetFlusher<'a, S>
where
E: TElement,
{
@ -512,7 +516,6 @@ where
had_invalidations,
origins_dirty,
origin_data_validity,
guard,
current: None,
}
}

View file

@ -30,9 +30,9 @@ pub struct UserAgentStylesheets {
/// The lock used for user-agent stylesheets.
pub shared_lock: SharedRwLock,
/// The user or user agent stylesheets.
pub user_or_user_agent_stylesheets: Vec<Stylesheet>,
pub user_or_user_agent_stylesheets: Vec<DocumentStyleSheet>,
/// The quirks mode stylesheet.
pub quirks_mode_stylesheet: Stylesheet,
pub quirks_mode_stylesheet: DocumentStyleSheet,
}
/// A set of namespaces applying to a given stylesheet.

View file

@ -19,7 +19,7 @@ use parser::{ParserContext, ParserErrorContext};
use properties::StyleBuilder;
use rule_cache::RuleCacheConditions;
use selectors::parser::SelectorParseError;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::cell::RefCell;
@ -571,16 +571,16 @@ impl Cascade {
pub fn from_stylesheets<'a, I, S>(
stylesheets: I,
guard: &SharedRwLockReadGuard,
guards: &StylesheetGuards,
device: &Device
) -> Self
where
I: Iterator<Item = &'a S>,
I: Iterator<Item = (&'a S, Origin)>,
S: StylesheetInDocument + 'static,
{
let mut cascade = Self::new();
for stylesheet in stylesheets {
stylesheet.effective_viewport_rules(device, guard, |rule| {
for (stylesheet, origin) in stylesheets {
stylesheet.effective_viewport_rules(device, guards.for_origin(origin), |rule| {
for declaration in &rule.declarations {
cascade.add(Cow::Borrowed(declaration))
}

View file

@ -47,7 +47,6 @@ use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRul
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
use stylesheets::StyleRule;
use stylesheets::StylesheetInDocument;
use stylesheets::UserAgentStylesheets;
use stylesheets::keyframes_rule::KeyframesAnimation;
use stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
use thread_state;
@ -95,16 +94,14 @@ impl DocumentCascadeData {
/// Rebuild the cascade data for the given document stylesheets, and
/// optionally with a set of user agent stylesheets. Returns Err(..)
/// to signify OOM.
fn rebuild<'a, 'b, S>(
fn rebuild<'a, S>(
&mut self,
device: &Device,
quirks_mode: QuirksMode,
flusher: StylesheetFlusher<'a, 'b, S>,
flusher: StylesheetFlusher<'a, S>,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
) -> Result<(), FailedAllocationError>
where
'b: 'a,
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
{
debug_assert!(!flusher.nothing_to_do());
@ -128,84 +125,16 @@ impl DocumentCascadeData {
}
}
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;
debug_assert!(matches!(
sheet_origin,
Origin::UserAgent | Origin::User
));
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.per_origin
.borrow_mut_for_origin(&sheet_origin)
.add_stylesheet(
device,
quirks_mode,
stylesheet,
guards.ua_or_user,
SheetRebuildKind::Full,
&mut self.precomputed_pseudo_element_decls,
)?;
}
if quirks_mode != QuirksMode::NoQuirks {
let stylesheet = &ua_stylesheets.quirks_mode_stylesheet;
let sheet_origin =
stylesheet.contents(guards.ua_or_user).origin;
debug_assert!(matches!(
sheet_origin,
Origin::UserAgent | Origin::User
));
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.per_origin
.borrow_mut_for_origin(&sheet_origin)
.add_stylesheet(
device,
quirks_mode,
&ua_stylesheets.quirks_mode_stylesheet,
guards.ua_or_user,
SheetRebuildKind::Full,
&mut self.precomputed_pseudo_element_decls,
)?;
}
}
}
for (stylesheet, rebuild_kind) in flusher {
let origin = stylesheet.origin(guards.author);
for (stylesheet, origin, rebuild_kind) in flusher {
let guard = guards.for_origin(origin);
let origin = stylesheet.origin(guard);
self.per_origin
.borrow_mut_for_origin(&origin)
.add_stylesheet(
device,
quirks_mode,
stylesheet,
guards.author,
guard,
rebuild_kind,
&mut self.precomputed_pseudo_element_decls,
)?;
@ -398,7 +327,6 @@ impl Stylist {
pub fn flush<E>(
&mut self,
guards: &StylesheetGuards,
ua_sheets: Option<&UserAgentStylesheets>,
document_element: Option<E>,
) -> bool
where
@ -427,7 +355,7 @@ impl Stylist {
let cascaded_rule = ViewportRule {
declarations: viewport_rule::Cascade::from_stylesheets(
self.stylesheets.iter(),
guards.author,
guards,
&self.device,
).finish()
};
@ -444,7 +372,7 @@ impl Stylist {
}
}
let flusher = self.stylesheets.flush(document_element, &guards.author);
let flusher = self.stylesheets.flush(document_element);
let had_invalidations = flusher.had_invalidations();
@ -453,7 +381,6 @@ impl Stylist {
self.quirks_mode,
flusher,
guards,
ua_sheets,
).unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
had_invalidations
@ -1003,7 +930,7 @@ impl Stylist {
pub fn set_device(
&mut self,
mut device: Device,
guard: &SharedRwLockReadGuard,
guards: &StylesheetGuards,
) -> OriginSet {
if viewport_rule::enabled() {
let cascaded_rule = {
@ -1012,7 +939,7 @@ impl Stylist {
ViewportRule {
declarations: viewport_rule::Cascade::from_stylesheets(
stylesheets.clone(),
guard,
guards,
&device
).finish(),
}
@ -1027,14 +954,14 @@ impl Stylist {
}
self.device = device;
self.media_features_change_changed_style(guard)
self.media_features_change_changed_style(guards)
}
/// Returns whether, given a media feature change, any previously-applicable
/// style has become non-applicable, or vice-versa for each origin.
pub fn media_features_change_changed_style(
&self,
guard: &SharedRwLockReadGuard,
guards: &StylesheetGuards,
) -> OriginSet {
use invalidation::media_queries::PotentiallyEffectiveMediaRules;
@ -1043,12 +970,11 @@ impl Stylist {
let mut origins = OriginSet::empty();
let stylesheets = self.stylesheets.iter();
'stylesheets_loop: for stylesheet in stylesheets {
'stylesheets_loop: for (stylesheet, origin) in stylesheets {
let guard = guards.for_origin(origin);
let effective_now =
stylesheet.is_effective_for_device(&self.device, guard);
let origin = stylesheet.origin(guard);
if origins.contains(origin.into()) {
continue;
}