mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #18502 - emilio:ua-sheets-unify, r=simonsapin
style: Unify how servo and Gecko handle UA sheets. <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18502) <!-- Reviewable:end -->
This commit is contained in:
commit
75e126f139
11 changed files with 122 additions and 161 deletions
|
@ -136,7 +136,7 @@ use style::properties::PropertyId;
|
||||||
use style::selector_parser::SnapshotMap;
|
use style::selector_parser::SnapshotMap;
|
||||||
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
|
||||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
|
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
|
||||||
use style::stylesheets::{Origin, OriginSet, Stylesheet, DocumentStyleSheet, StylesheetInDocument, UserAgentStylesheets};
|
use style::stylesheets::{Origin, Stylesheet, DocumentStyleSheet, StylesheetInDocument, UserAgentStylesheets};
|
||||||
use style::stylist::Stylist;
|
use style::stylist::Stylist;
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
|
@ -1139,14 +1139,22 @@ impl LayoutThread {
|
||||||
Au::from_f32_px(initial_viewport.height));
|
Au::from_f32_px(initial_viewport.height));
|
||||||
|
|
||||||
// Calculate the actual viewport as per DEVICE-ADAPT § 6
|
// Calculate the actual viewport as per DEVICE-ADAPT § 6
|
||||||
|
// If the entire flow tree is invalid, then it will be reflowed anyhow.
|
||||||
let document_shared_lock = document.style_shared_lock();
|
let document_shared_lock = document.style_shared_lock();
|
||||||
self.document_shared_lock = Some(document_shared_lock.clone());
|
self.document_shared_lock = Some(document_shared_lock.clone());
|
||||||
let author_guard = document_shared_lock.read();
|
let author_guard = document_shared_lock.read();
|
||||||
|
|
||||||
|
let ua_stylesheets = &*UA_STYLESHEETS;
|
||||||
|
let ua_or_user_guard = ua_stylesheets.shared_lock.read();
|
||||||
|
let guards = StylesheetGuards {
|
||||||
|
author: &author_guard,
|
||||||
|
ua_or_user: &ua_or_user_guard,
|
||||||
|
};
|
||||||
|
|
||||||
let had_used_viewport_units = self.stylist.device().used_viewport_units();
|
let had_used_viewport_units = self.stylist.device().used_viewport_units();
|
||||||
let device = Device::new(MediaType::screen(), initial_viewport, device_pixel_ratio);
|
let device = Device::new(MediaType::screen(), initial_viewport, device_pixel_ratio);
|
||||||
let sheet_origins_affected_by_device_change =
|
let sheet_origins_affected_by_device_change =
|
||||||
self.stylist.set_device(device, &author_guard);
|
self.stylist.set_device(device, &guards);
|
||||||
|
|
||||||
self.stylist.force_stylesheet_origins_dirty(sheet_origins_affected_by_device_change);
|
self.stylist.force_stylesheet_origins_dirty(sheet_origins_affected_by_device_change);
|
||||||
self.viewport_size =
|
self.viewport_size =
|
||||||
|
@ -1173,23 +1181,23 @@ impl LayoutThread {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the entire flow tree is invalid, then it will be reflowed anyhow.
|
|
||||||
let ua_stylesheets = &*UA_STYLESHEETS;
|
|
||||||
let ua_or_user_guard = ua_stylesheets.shared_lock.read();
|
|
||||||
let guards = StylesheetGuards {
|
|
||||||
author: &author_guard,
|
|
||||||
ua_or_user: &ua_or_user_guard,
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if self.first_reflow.get() {
|
if self.first_reflow.get() {
|
||||||
debug!("First reflow, rebuilding user and UA rules");
|
debug!("First reflow, rebuilding user and UA rules");
|
||||||
let mut ua_and_user = OriginSet::empty();
|
|
||||||
ua_and_user |= Origin::User;
|
|
||||||
ua_and_user |= Origin::UserAgent;
|
|
||||||
self.stylist.force_stylesheet_origins_dirty(ua_and_user);
|
|
||||||
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
|
||||||
self.handle_add_stylesheet(stylesheet, &ua_or_user_guard);
|
self.stylist.append_stylesheet(stylesheet.clone(), &ua_or_user_guard);
|
||||||
|
self.handle_add_stylesheet(&stylesheet.0, &ua_or_user_guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.stylist.quirks_mode() != QuirksMode::NoQuirks {
|
||||||
|
self.stylist.append_stylesheet(
|
||||||
|
ua_stylesheets.quirks_mode_stylesheet.clone(),
|
||||||
|
&ua_or_user_guard,
|
||||||
|
);
|
||||||
|
self.handle_add_stylesheet(
|
||||||
|
&ua_stylesheets.quirks_mode_stylesheet.0,
|
||||||
|
&ua_or_user_guard,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,11 +1206,7 @@ impl LayoutThread {
|
||||||
self.stylist.force_stylesheet_origins_dirty(Origin::Author.into());
|
self.stylist.force_stylesheet_origins_dirty(Origin::Author.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.stylist.flush(
|
self.stylist.flush(&guards, Some(element));
|
||||||
&guards,
|
|
||||||
Some(ua_stylesheets),
|
|
||||||
Some(element),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if viewport_size_changed {
|
if viewport_size_changed {
|
||||||
|
@ -1706,10 +1710,12 @@ fn get_root_flow_background_color(flow: &mut Flow) -> webrender_api::ColorF {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
|
fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
|
||||||
fn parse_ua_stylesheet(shared_lock: &SharedRwLock, filename: &'static str)
|
fn parse_ua_stylesheet(
|
||||||
-> Result<Stylesheet, &'static str> {
|
shared_lock: &SharedRwLock,
|
||||||
|
filename: &'static str,
|
||||||
|
) -> Result<DocumentStyleSheet, &'static str> {
|
||||||
let res = read_resource_file(filename).map_err(|_| filename)?;
|
let res = read_resource_file(filename).map_err(|_| filename)?;
|
||||||
Ok(Stylesheet::from_bytes(
|
Ok(DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes(
|
||||||
&res,
|
&res,
|
||||||
ServoUrl::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
|
ServoUrl::parse(&format!("chrome://resources/{:?}", filename)).unwrap(),
|
||||||
None,
|
None,
|
||||||
|
@ -1719,7 +1725,8 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
|
||||||
shared_lock.clone(),
|
shared_lock.clone(),
|
||||||
None,
|
None,
|
||||||
&NullReporter,
|
&NullReporter,
|
||||||
QuirksMode::NoQuirks))
|
QuirksMode::NoQuirks,
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
let shared_lock = SharedRwLock::new();
|
let shared_lock = SharedRwLock::new();
|
||||||
|
@ -1730,9 +1737,20 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
|
||||||
user_or_user_agent_stylesheets.push(parse_ua_stylesheet(&shared_lock, filename)?);
|
user_or_user_agent_stylesheets.push(parse_ua_stylesheet(&shared_lock, filename)?);
|
||||||
}
|
}
|
||||||
for &(ref contents, ref url) in &opts::get().user_stylesheets {
|
for &(ref contents, ref url) in &opts::get().user_stylesheets {
|
||||||
user_or_user_agent_stylesheets.push(Stylesheet::from_bytes(
|
user_or_user_agent_stylesheets.push(
|
||||||
&contents, url.clone(), None, None, Origin::User, MediaList::empty(),
|
DocumentStyleSheet(ServoArc::new(Stylesheet::from_bytes(
|
||||||
shared_lock.clone(), None, &RustLogReporter, QuirksMode::NoQuirks));
|
&contents,
|
||||||
|
url.clone(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Origin::User,
|
||||||
|
MediaList::empty(),
|
||||||
|
shared_lock.clone(),
|
||||||
|
None,
|
||||||
|
&RustLogReporter,
|
||||||
|
QuirksMode::NoQuirks,
|
||||||
|
)))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let quirks_mode_stylesheet = parse_ua_stylesheet(&shared_lock, "quirks-mode.css")?;
|
let quirks_mode_stylesheet = parse_ua_stylesheet(&shared_lock, "quirks-mode.css")?;
|
||||||
|
|
|
@ -655,7 +655,7 @@ where
|
||||||
S: JSTraceable + ::style::stylesheets::StylesheetInDocument + PartialEq + 'static,
|
S: JSTraceable + ::style::stylesheets::StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
unsafe fn trace(&self, tracer: *mut JSTracer) {
|
unsafe fn trace(&self, tracer: *mut JSTracer) {
|
||||||
for s in self.iter() {
|
for (s, _origin) in self.iter() {
|
||||||
s.trace(tracer)
|
s.trace(tracer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2397,9 +2397,13 @@ impl Document {
|
||||||
owner.is::<HTMLMetaElement>(), "Wat");
|
owner.is::<HTMLMetaElement>(), "Wat");
|
||||||
|
|
||||||
let mut stylesheets = self.stylesheets.borrow_mut();
|
let mut stylesheets = self.stylesheets.borrow_mut();
|
||||||
let insertion_point = stylesheets.iter().find(|sheet_in_doc| {
|
let insertion_point =
|
||||||
owner.upcast::<Node>().is_before(sheet_in_doc.owner.upcast())
|
stylesheets
|
||||||
}).cloned();
|
.iter()
|
||||||
|
.map(|(sheet, _origin)| sheet)
|
||||||
|
.find(|sheet_in_doc| {
|
||||||
|
owner.upcast::<Node>().is_before(sheet_in_doc.owner.upcast())
|
||||||
|
}).cloned();
|
||||||
|
|
||||||
self.window()
|
self.window()
|
||||||
.layout_chan()
|
.layout_chan()
|
||||||
|
|
|
@ -155,7 +155,6 @@ impl PerDocumentStyleDataImpl {
|
||||||
{
|
{
|
||||||
self.stylist.flush(
|
self.stylist.flush(
|
||||||
&StylesheetGuards::same(guard),
|
&StylesheetGuards::same(guard),
|
||||||
/* ua_sheets = */ None,
|
|
||||||
document_element,
|
document_element,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::cell::UnsafeCell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use stylesheets::Origin;
|
||||||
|
|
||||||
/// A shared read/write lock that can protect multiple objects.
|
/// A shared read/write lock that can protect multiple objects.
|
||||||
///
|
///
|
||||||
|
@ -262,7 +263,7 @@ pub trait DeepCloneWithLock : Sized {
|
||||||
/// Guards for a document
|
/// Guards for a document
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct StylesheetGuards<'a> {
|
pub struct StylesheetGuards<'a> {
|
||||||
/// For author-origin stylesheets
|
/// For author-origin stylesheets.
|
||||||
pub author: &'a SharedRwLockReadGuard<'a>,
|
pub author: &'a SharedRwLockReadGuard<'a>,
|
||||||
|
|
||||||
/// For user-agent-origin and user-origin stylesheets
|
/// For user-agent-origin and user-origin stylesheets
|
||||||
|
@ -270,6 +271,14 @@ pub struct StylesheetGuards<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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
|
/// Same guard for all origins
|
||||||
pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
|
pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
|
||||||
StylesheetGuards {
|
StylesheetGuards {
|
||||||
|
|
|
@ -59,14 +59,14 @@ where
|
||||||
{
|
{
|
||||||
origins: OriginSetIterator,
|
origins: OriginSetIterator,
|
||||||
collections: &'a PerOrigin<SheetCollection<S>>,
|
collections: &'a PerOrigin<SheetCollection<S>>,
|
||||||
current: Option<StylesheetCollectionIterator<'a, S>>,
|
current: Option<(Origin, StylesheetCollectionIterator<'a, S>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> Iterator for StylesheetIterator<'a, S>
|
impl<'a, S> Iterator for StylesheetIterator<'a, S>
|
||||||
where
|
where
|
||||||
S: StylesheetInDocument + PartialEq + 'static,
|
S: StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
type Item = &'a S;
|
type Item = (&'a S, Origin);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
|
@ -77,11 +77,14 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
self.current =
|
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;
|
self.current = None;
|
||||||
|
@ -112,17 +115,15 @@ impl Default for OriginValidity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct to iterate over the different stylesheets to be flushed.
|
/// A struct to iterate over the different stylesheets to be flushed.
|
||||||
pub struct StylesheetFlusher<'a, 'b, S>
|
pub struct StylesheetFlusher<'a, S>
|
||||||
where
|
where
|
||||||
'b: 'a,
|
|
||||||
S: StylesheetInDocument + PartialEq + 'static,
|
S: StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
guard: &'a SharedRwLockReadGuard<'b>,
|
|
||||||
origins_dirty: OriginSetIterator,
|
origins_dirty: OriginSetIterator,
|
||||||
// NB: Bound to the StylesheetSet lifetime when constructed, see
|
// NB: Bound to the StylesheetSet lifetime when constructed, see
|
||||||
// StylesheetSet::flush.
|
// StylesheetSet::flush.
|
||||||
collections: *mut PerOrigin<SheetCollection<S>>,
|
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>,
|
origin_data_validity: PerOrigin<OriginValidity>,
|
||||||
author_style_disabled: bool,
|
author_style_disabled: bool,
|
||||||
had_invalidations: 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
|
where
|
||||||
'b: 'a,
|
|
||||||
S: StylesheetInDocument + PartialEq + 'static,
|
S: StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
/// The data validity for a given origin.
|
/// The data validity for a given origin.
|
||||||
|
@ -166,9 +166,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
impl<'a, 'b, S> Drop for StylesheetFlusher<'a, 'b, S>
|
impl<'a, S> Drop for StylesheetFlusher<'a, S>
|
||||||
where
|
where
|
||||||
'b: 'a,
|
|
||||||
S: StylesheetInDocument + PartialEq + 'static,
|
S: StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
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
|
where
|
||||||
'b: 'a,
|
|
||||||
S: StylesheetInDocument + PartialEq + 'static,
|
S: StylesheetInDocument + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
type Item = (&'a S, SheetRebuildKind);
|
type Item = (&'a S, Origin, SheetRebuildKind);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -205,10 +203,16 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
self.current =
|
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,
|
Some(s) => s,
|
||||||
None => {
|
None => {
|
||||||
self.current = 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);
|
let dirty = mem::replace(&mut potential_sheet.dirty, false);
|
||||||
|
|
||||||
if dirty {
|
if dirty {
|
||||||
// If the sheet was dirty, we need to do a full rebuild anyway.
|
// 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) {
|
if self.author_style_disabled && matches!(origin, Origin::Author) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +239,7 @@ where
|
||||||
OriginValidity::FullyInvalid => SheetRebuildKind::Full,
|
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
|
/// Flush the current set, unmarking it as dirty, and returns a
|
||||||
/// `StylesheetFlusher` in order to rebuild the stylist.
|
/// `StylesheetFlusher` in order to rebuild the stylist.
|
||||||
pub fn flush<'a, 'b, E>(
|
pub fn flush<'a, E>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
document_element: Option<E>,
|
document_element: Option<E>,
|
||||||
guard: &'a SharedRwLockReadGuard<'b>,
|
) -> StylesheetFlusher<'a, S>
|
||||||
) -> StylesheetFlusher<'a, 'b, S>
|
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -512,7 +516,6 @@ where
|
||||||
had_invalidations,
|
had_invalidations,
|
||||||
origins_dirty,
|
origins_dirty,
|
||||||
origin_data_validity,
|
origin_data_validity,
|
||||||
guard,
|
|
||||||
current: None,
|
current: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ pub struct UserAgentStylesheets {
|
||||||
/// The lock used for user-agent stylesheets.
|
/// The lock used for user-agent stylesheets.
|
||||||
pub shared_lock: SharedRwLock,
|
pub shared_lock: SharedRwLock,
|
||||||
/// The user or user agent stylesheets.
|
/// 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.
|
/// The quirks mode stylesheet.
|
||||||
pub quirks_mode_stylesheet: Stylesheet,
|
pub quirks_mode_stylesheet: DocumentStyleSheet,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of namespaces applying to a given stylesheet.
|
/// A set of namespaces applying to a given stylesheet.
|
||||||
|
|
|
@ -19,7 +19,7 @@ use parser::{ParserContext, ParserErrorContext};
|
||||||
use properties::StyleBuilder;
|
use properties::StyleBuilder;
|
||||||
use rule_cache::RuleCacheConditions;
|
use rule_cache::RuleCacheConditions;
|
||||||
use selectors::parser::SelectorParseError;
|
use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
use shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -571,16 +571,16 @@ impl Cascade {
|
||||||
|
|
||||||
pub fn from_stylesheets<'a, I, S>(
|
pub fn from_stylesheets<'a, I, S>(
|
||||||
stylesheets: I,
|
stylesheets: I,
|
||||||
guard: &SharedRwLockReadGuard,
|
guards: &StylesheetGuards,
|
||||||
device: &Device
|
device: &Device
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a S>,
|
I: Iterator<Item = (&'a S, Origin)>,
|
||||||
S: StylesheetInDocument + 'static,
|
S: StylesheetInDocument + 'static,
|
||||||
{
|
{
|
||||||
let mut cascade = Self::new();
|
let mut cascade = Self::new();
|
||||||
for stylesheet in stylesheets {
|
for (stylesheet, origin) in stylesheets {
|
||||||
stylesheet.effective_viewport_rules(device, guard, |rule| {
|
stylesheet.effective_viewport_rules(device, guards.for_origin(origin), |rule| {
|
||||||
for declaration in &rule.declarations {
|
for declaration in &rule.declarations {
|
||||||
cascade.add(Cow::Borrowed(declaration))
|
cascade.add(Cow::Borrowed(declaration))
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRul
|
||||||
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||||
use stylesheets::StyleRule;
|
use stylesheets::StyleRule;
|
||||||
use stylesheets::StylesheetInDocument;
|
use stylesheets::StylesheetInDocument;
|
||||||
use stylesheets::UserAgentStylesheets;
|
|
||||||
use stylesheets::keyframes_rule::KeyframesAnimation;
|
use stylesheets::keyframes_rule::KeyframesAnimation;
|
||||||
use stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
|
use stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
|
||||||
use thread_state;
|
use thread_state;
|
||||||
|
@ -95,16 +94,14 @@ impl DocumentCascadeData {
|
||||||
/// Rebuild the cascade data for the given document stylesheets, and
|
/// Rebuild the cascade data for the given document stylesheets, and
|
||||||
/// optionally with a set of user agent stylesheets. Returns Err(..)
|
/// optionally with a set of user agent stylesheets. Returns Err(..)
|
||||||
/// to signify OOM.
|
/// to signify OOM.
|
||||||
fn rebuild<'a, 'b, S>(
|
fn rebuild<'a, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
flusher: StylesheetFlusher<'a, 'b, S>,
|
flusher: StylesheetFlusher<'a, S>,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
ua_stylesheets: Option<&UserAgentStylesheets>,
|
|
||||||
) -> Result<(), FailedAllocationError>
|
) -> Result<(), FailedAllocationError>
|
||||||
where
|
where
|
||||||
'b: 'a,
|
|
||||||
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
|
S: StylesheetInDocument + ToMediaListKey + PartialEq + 'static,
|
||||||
{
|
{
|
||||||
debug_assert!(!flusher.nothing_to_do());
|
debug_assert!(!flusher.nothing_to_do());
|
||||||
|
@ -128,84 +125,16 @@ impl DocumentCascadeData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ua_stylesheets) = ua_stylesheets {
|
for (stylesheet, origin, rebuild_kind) in flusher {
|
||||||
debug_assert!(cfg!(feature = "servo"));
|
let guard = guards.for_origin(origin);
|
||||||
|
let origin = stylesheet.origin(guard);
|
||||||
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);
|
|
||||||
self.per_origin
|
self.per_origin
|
||||||
.borrow_mut_for_origin(&origin)
|
.borrow_mut_for_origin(&origin)
|
||||||
.add_stylesheet(
|
.add_stylesheet(
|
||||||
device,
|
device,
|
||||||
quirks_mode,
|
quirks_mode,
|
||||||
stylesheet,
|
stylesheet,
|
||||||
guards.author,
|
guard,
|
||||||
rebuild_kind,
|
rebuild_kind,
|
||||||
&mut self.precomputed_pseudo_element_decls,
|
&mut self.precomputed_pseudo_element_decls,
|
||||||
)?;
|
)?;
|
||||||
|
@ -398,7 +327,6 @@ impl Stylist {
|
||||||
pub fn flush<E>(
|
pub fn flush<E>(
|
||||||
&mut self,
|
&mut self,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
ua_sheets: Option<&UserAgentStylesheets>,
|
|
||||||
document_element: Option<E>,
|
document_element: Option<E>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
|
@ -427,7 +355,7 @@ impl Stylist {
|
||||||
let cascaded_rule = ViewportRule {
|
let cascaded_rule = ViewportRule {
|
||||||
declarations: viewport_rule::Cascade::from_stylesheets(
|
declarations: viewport_rule::Cascade::from_stylesheets(
|
||||||
self.stylesheets.iter(),
|
self.stylesheets.iter(),
|
||||||
guards.author,
|
guards,
|
||||||
&self.device,
|
&self.device,
|
||||||
).finish()
|
).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();
|
let had_invalidations = flusher.had_invalidations();
|
||||||
|
|
||||||
|
@ -453,7 +381,6 @@ impl Stylist {
|
||||||
self.quirks_mode,
|
self.quirks_mode,
|
||||||
flusher,
|
flusher,
|
||||||
guards,
|
guards,
|
||||||
ua_sheets,
|
|
||||||
).unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
|
).unwrap_or_else(|_| warn!("OOM in Stylist::flush"));
|
||||||
|
|
||||||
had_invalidations
|
had_invalidations
|
||||||
|
@ -1003,7 +930,7 @@ impl Stylist {
|
||||||
pub fn set_device(
|
pub fn set_device(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut device: Device,
|
mut device: Device,
|
||||||
guard: &SharedRwLockReadGuard,
|
guards: &StylesheetGuards,
|
||||||
) -> OriginSet {
|
) -> OriginSet {
|
||||||
if viewport_rule::enabled() {
|
if viewport_rule::enabled() {
|
||||||
let cascaded_rule = {
|
let cascaded_rule = {
|
||||||
|
@ -1012,7 +939,7 @@ impl Stylist {
|
||||||
ViewportRule {
|
ViewportRule {
|
||||||
declarations: viewport_rule::Cascade::from_stylesheets(
|
declarations: viewport_rule::Cascade::from_stylesheets(
|
||||||
stylesheets.clone(),
|
stylesheets.clone(),
|
||||||
guard,
|
guards,
|
||||||
&device
|
&device
|
||||||
).finish(),
|
).finish(),
|
||||||
}
|
}
|
||||||
|
@ -1027,14 +954,14 @@ impl Stylist {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.device = device;
|
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
|
/// Returns whether, given a media feature change, any previously-applicable
|
||||||
/// style has become non-applicable, or vice-versa for each origin.
|
/// style has become non-applicable, or vice-versa for each origin.
|
||||||
pub fn media_features_change_changed_style(
|
pub fn media_features_change_changed_style(
|
||||||
&self,
|
&self,
|
||||||
guard: &SharedRwLockReadGuard,
|
guards: &StylesheetGuards,
|
||||||
) -> OriginSet {
|
) -> OriginSet {
|
||||||
use invalidation::media_queries::PotentiallyEffectiveMediaRules;
|
use invalidation::media_queries::PotentiallyEffectiveMediaRules;
|
||||||
|
|
||||||
|
@ -1043,12 +970,11 @@ impl Stylist {
|
||||||
let mut origins = OriginSet::empty();
|
let mut origins = OriginSet::empty();
|
||||||
let stylesheets = self.stylesheets.iter();
|
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 =
|
let effective_now =
|
||||||
stylesheet.is_effective_for_device(&self.device, guard);
|
stylesheet.is_effective_for_device(&self.device, guard);
|
||||||
|
|
||||||
let origin = stylesheet.origin(guard);
|
|
||||||
|
|
||||||
if origins.contains(origin.into()) {
|
if origins.contains(origin.into()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -945,8 +945,9 @@ pub extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
|
||||||
*viewport_units_used = data.stylist.device().used_viewport_size();
|
*viewport_units_used = data.stylist.device().used_viewport_size();
|
||||||
}
|
}
|
||||||
data.stylist.device_mut().reset_computed_values();
|
data.stylist.device_mut().reset_computed_values();
|
||||||
|
let guards = StylesheetGuards::same(&guard);
|
||||||
let origins_in_which_rules_changed =
|
let origins_in_which_rules_changed =
|
||||||
data.stylist.media_features_change_changed_style(&guard);
|
data.stylist.media_features_change_changed_style(&guards);
|
||||||
|
|
||||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
||||||
// work as return values with the Linux 32-bit ABI at the moment because
|
// work as return values with the Linux 32-bit ABI at the moment because
|
||||||
|
@ -964,8 +965,9 @@ pub extern "C" fn Servo_StyleSet_SetDevice(
|
||||||
|
|
||||||
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||||
let device = Device::new(pres_context);
|
let device = Device::new(pres_context);
|
||||||
|
let guards = StylesheetGuards::same(&guard);
|
||||||
let origins_in_which_rules_changed =
|
let origins_in_which_rules_changed =
|
||||||
data.stylist.set_device(device, &guard);
|
data.stylist.set_device(device, &guards);
|
||||||
|
|
||||||
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
|
||||||
// work as return values with the Linux 32-bit ABI at the moment because
|
// work as return values with the Linux 32-bit ABI at the moment because
|
||||||
|
|
|
@ -12,7 +12,7 @@ use servo_url::ServoUrl;
|
||||||
use style::context::QuirksMode;
|
use style::context::QuirksMode;
|
||||||
use style::media_queries::{Device, MediaList, MediaType};
|
use style::media_queries::{Device, MediaList, MediaType};
|
||||||
use style::parser::{ParserContext, ParserErrorContext};
|
use style::parser::{ParserContext, ParserErrorContext};
|
||||||
use style::shared_lock::SharedRwLock;
|
use style::shared_lock::{SharedRwLock, StylesheetGuards};
|
||||||
use style::stylesheets::{CssRuleType, Stylesheet, StylesheetInDocument, Origin};
|
use style::stylesheets::{CssRuleType, Stylesheet, StylesheetInDocument, Origin};
|
||||||
use style::stylesheets::viewport_rule::*;
|
use style::stylesheets::viewport_rule::*;
|
||||||
use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
|
use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
|
||||||
|
@ -271,8 +271,8 @@ fn multiple_stylesheets_cascading() {
|
||||||
];
|
];
|
||||||
|
|
||||||
let declarations = Cascade::from_stylesheets(
|
let declarations = Cascade::from_stylesheets(
|
||||||
stylesheets.iter().map(|s| &**s),
|
stylesheets.iter().map(|s| (&**s, Origin::Author)),
|
||||||
&shared_lock.read(),
|
&StylesheetGuards::same(&shared_lock.read()),
|
||||||
&device,
|
&device,
|
||||||
).finish();
|
).finish();
|
||||||
assert_decl_len!(declarations == 3);
|
assert_decl_len!(declarations == 3);
|
||||||
|
@ -289,8 +289,8 @@ fn multiple_stylesheets_cascading() {
|
||||||
Author, error_reporter, shared_lock.clone())
|
Author, error_reporter, shared_lock.clone())
|
||||||
];
|
];
|
||||||
let declarations = Cascade::from_stylesheets(
|
let declarations = Cascade::from_stylesheets(
|
||||||
stylesheets.iter().map(|s| &**s),
|
stylesheets.iter().map(|s| (&**s, Origin::Author)),
|
||||||
&shared_lock.read(),
|
&StylesheetGuards::same(&shared_lock.read()),
|
||||||
&device,
|
&device,
|
||||||
).finish();
|
).finish();
|
||||||
assert_decl_len!(declarations == 3);
|
assert_decl_len!(declarations == 3);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue