mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
style: Allow placeholder import sheets.
This is necessary because we can't create GeckoStyleSheets off-main-thread, so we need a placeholder until it can be filled in. Bug: 1454030 Reviewed-by: emilio MozReview-Commit-ID: ssRme4fLYg
This commit is contained in:
parent
441f1cd231
commit
afe484e46b
7 changed files with 152 additions and 71 deletions
|
@ -5,6 +5,7 @@
|
|||
//! Data needed to style a Gecko document.
|
||||
|
||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use context::QuirksMode;
|
||||
use dom::TElement;
|
||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
||||
use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
|
||||
|
@ -17,7 +18,7 @@ use properties::ComputedValues;
|
|||
use selector_parser::SnapshotMap;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
||||
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
||||
use stylesheets::{CssRule, Origin, StylesheetContents, StylesheetInDocument};
|
||||
use stylist::Stylist;
|
||||
|
||||
/// Little wrapper to a Gecko style sheet.
|
||||
|
@ -58,6 +59,16 @@ impl GeckoStyleSheet {
|
|||
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the StylesheetContents for this stylesheet.
|
||||
pub fn contents(&self) -> &StylesheetContents {
|
||||
debug_assert!(!self.inner().mContents.mRawPtr.is_null());
|
||||
unsafe {
|
||||
let contents =
|
||||
(&**StylesheetContents::as_arc(&&*self.inner().mContents.mRawPtr)) as *const _;
|
||||
&*contents
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GeckoStyleSheet {
|
||||
|
@ -74,13 +85,12 @@ impl Clone for GeckoStyleSheet {
|
|||
}
|
||||
|
||||
impl StylesheetInDocument for GeckoStyleSheet {
|
||||
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
|
||||
debug_assert!(!self.inner().mContents.mRawPtr.is_null());
|
||||
unsafe {
|
||||
let contents =
|
||||
(&**StylesheetContents::as_arc(&&*self.inner().mContents.mRawPtr)) as *const _;
|
||||
&*contents
|
||||
}
|
||||
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||
self.contents().origin
|
||||
}
|
||||
|
||||
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||
self.contents().quirks_mode
|
||||
}
|
||||
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||
|
@ -103,6 +113,11 @@ impl StylesheetInDocument for GeckoStyleSheet {
|
|||
fn enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||
self.contents().rules(guard)
|
||||
}
|
||||
}
|
||||
|
||||
/// The container for data that a Servo-backed Gecko document needs to style
|
||||
|
|
|
@ -478,7 +478,7 @@ where
|
|||
sheet: &S,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
) -> &mut SheetCollection<S> {
|
||||
let origin = sheet.contents(guard).origin;
|
||||
let origin = sheet.origin(guard);
|
||||
self.collections.borrow_mut_for_origin(&origin)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
//!
|
||||
//! [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
||||
|
||||
use context::QuirksMode;
|
||||
use cssparser::SourceLocation;
|
||||
use media_queries::MediaList;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
||||
|
@ -13,13 +14,52 @@ use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
|||
use std::fmt::{self, Write};
|
||||
use str::CssStringWriter;
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
||||
use stylesheets::{CssRule, Origin, StylesheetInDocument};
|
||||
use values::CssUrl;
|
||||
|
||||
/// With asynchronous stylesheet parsing, we can't synchronously create a
|
||||
/// GeckoStyleSheet. So we use this placeholder instead.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PendingSheet {
|
||||
origin: Origin,
|
||||
quirks_mode: QuirksMode,
|
||||
}
|
||||
|
||||
/// A sheet that is held from an import rule.
|
||||
#[cfg(feature = "gecko")]
|
||||
#[derive(Debug)]
|
||||
pub struct ImportSheet(pub ::gecko::data::GeckoStyleSheet);
|
||||
pub enum ImportSheet {
|
||||
/// A bonafide stylesheet.
|
||||
Sheet(::gecko::data::GeckoStyleSheet),
|
||||
/// An @import created while parsing off-main-thread, whose Gecko sheet has
|
||||
/// yet to be created and attached.
|
||||
Pending(PendingSheet),
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ImportSheet {
|
||||
/// Creates a new ImportSheet from a GeckoStyleSheet.
|
||||
pub fn new(sheet: ::gecko::data::GeckoStyleSheet) -> Self {
|
||||
ImportSheet::Sheet(sheet)
|
||||
}
|
||||
|
||||
/// Creates a pending ImportSheet for a load that has not started yet.
|
||||
pub fn new_pending(origin: Origin, quirks_mode: QuirksMode) -> Self {
|
||||
ImportSheet::Pending(PendingSheet {
|
||||
origin,
|
||||
quirks_mode,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a reference to the GeckoStyleSheet in this ImportSheet, if it
|
||||
/// exists.
|
||||
pub fn as_sheet(&self) -> Option<&::gecko::data::GeckoStyleSheet> {
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => Some(s),
|
||||
ImportSheet::Pending(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl DeepCloneWithLock for ImportSheet {
|
||||
|
@ -31,10 +71,15 @@ impl DeepCloneWithLock for ImportSheet {
|
|||
) -> Self {
|
||||
use gecko::data::GeckoStyleSheet;
|
||||
use gecko_bindings::bindings;
|
||||
let clone = unsafe {
|
||||
bindings::Gecko_StyleSheet_Clone(self.0.raw() as *const _, params.reference_sheet)
|
||||
};
|
||||
ImportSheet(unsafe { GeckoStyleSheet::from_addrefed(clone) })
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => {
|
||||
let clone = unsafe {
|
||||
bindings::Gecko_StyleSheet_Clone(s.raw() as *const _, params.reference_sheet)
|
||||
};
|
||||
ImportSheet::Sheet(unsafe { GeckoStyleSheet::from_addrefed(clone) })
|
||||
},
|
||||
ImportSheet::Pending(ref p) => ImportSheet::Pending(p.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,17 +89,39 @@ impl DeepCloneWithLock for ImportSheet {
|
|||
pub struct ImportSheet(pub ::servo_arc::Arc<::stylesheets::Stylesheet>);
|
||||
|
||||
impl StylesheetInDocument for ImportSheet {
|
||||
/// Get the media associated with this stylesheet.
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||
self.0.media(guard)
|
||||
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => s.contents().origin,
|
||||
ImportSheet::Pending(ref p) => p.origin,
|
||||
}
|
||||
}
|
||||
|
||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
|
||||
self.0.contents(guard)
|
||||
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => s.contents().quirks_mode,
|
||||
ImportSheet::Pending(ref p) => p.quirks_mode,
|
||||
}
|
||||
}
|
||||
|
||||
fn enabled(&self) -> bool {
|
||||
self.0.enabled()
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => s.enabled(),
|
||||
ImportSheet::Pending(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => s.media(guard),
|
||||
ImportSheet::Pending(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||
match *self {
|
||||
ImportSheet::Sheet(ref s) => s.contents().rules(guard),
|
||||
ImportSheet::Pending(_) => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@ use media_queries::Device;
|
|||
use shared_lock::SharedRwLockReadGuard;
|
||||
use smallvec::SmallVec;
|
||||
use std::slice;
|
||||
use stylesheets::{CssRule, CssRules, DocumentRule, ImportRule, MediaRule, SupportsRule};
|
||||
use stylesheets::{CssRule, DocumentRule, ImportRule, MediaRule, SupportsRule};
|
||||
use stylesheets::StylesheetInDocument;
|
||||
use stylesheets::import_rule::ImportSheet;
|
||||
|
||||
/// An iterator over a list of rules.
|
||||
pub struct RulesIterator<'a, 'b, C>
|
||||
|
@ -35,10 +36,10 @@ where
|
|||
device: &'a Device,
|
||||
quirks_mode: QuirksMode,
|
||||
guard: &'a SharedRwLockReadGuard<'b>,
|
||||
rules: &'a CssRules,
|
||||
rules: &'a [CssRule],
|
||||
) -> Self {
|
||||
let mut stack = SmallVec::new();
|
||||
stack.push(rules.0.iter());
|
||||
stack.push(rules.iter());
|
||||
Self {
|
||||
device: device,
|
||||
quirks_mode: quirks_mode,
|
||||
|
@ -102,10 +103,7 @@ where
|
|||
}
|
||||
import_rule
|
||||
.stylesheet
|
||||
.contents(self.guard)
|
||||
.rules
|
||||
.read_with(self.guard)
|
||||
.0
|
||||
.rules(self.guard)
|
||||
.iter()
|
||||
},
|
||||
CssRule::Document(ref doc_rule) => {
|
||||
|
|
|
@ -103,22 +103,10 @@ impl StylesheetContents {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return an iterator using the condition `C`.
|
||||
/// Returns a reference to the list of rules.
|
||||
#[inline]
|
||||
pub fn iter_rules<'a, 'b, C>(
|
||||
&'a self,
|
||||
device: &'a Device,
|
||||
guard: &'a SharedRwLockReadGuard<'b>,
|
||||
) -> RulesIterator<'a, 'b, C>
|
||||
where
|
||||
C: NestedRuleIterationCondition,
|
||||
{
|
||||
RulesIterator::new(
|
||||
device,
|
||||
self.quirks_mode,
|
||||
guard,
|
||||
&self.rules.read_with(guard),
|
||||
)
|
||||
pub fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||
&self.rules.read_with(guard).0
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
|
@ -189,32 +177,20 @@ macro_rules! rule_filter {
|
|||
|
||||
/// A trait to represent a given stylesheet in a document.
|
||||
pub trait StylesheetInDocument {
|
||||
/// Get the contents of this stylesheet.
|
||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents;
|
||||
|
||||
/// Get the stylesheet origin.
|
||||
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||
self.contents(guard).origin
|
||||
}
|
||||
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin;
|
||||
|
||||
/// Get the stylesheet quirks mode.
|
||||
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||
self.contents(guard).quirks_mode
|
||||
}
|
||||
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode;
|
||||
|
||||
/// Get whether this stylesheet is enabled.
|
||||
fn enabled(&self) -> bool;
|
||||
|
||||
/// Get the media associated with this stylesheet.
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList>;
|
||||
|
||||
/// Returns whether the style-sheet applies for the current device.
|
||||
fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
|
||||
match self.media(guard) {
|
||||
Some(medialist) => medialist.evaluate(device, self.quirks_mode(guard)),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get whether this stylesheet is enabled.
|
||||
fn enabled(&self) -> bool;
|
||||
/// Returns a reference to the list of rules in this stylesheet.
|
||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule];
|
||||
|
||||
/// Return an iterator using the condition `C`.
|
||||
#[inline]
|
||||
|
@ -226,7 +202,15 @@ pub trait StylesheetInDocument {
|
|||
where
|
||||
C: NestedRuleIterationCondition,
|
||||
{
|
||||
self.contents(guard).iter_rules(device, guard)
|
||||
RulesIterator::new(device, self.quirks_mode(guard), guard, self.rules(guard))
|
||||
}
|
||||
|
||||
/// Returns whether the style-sheet applies for the current device.
|
||||
fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
|
||||
match self.media(guard) {
|
||||
Some(medialist) => medialist.evaluate(device, self.quirks_mode(guard)),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an iterator over the effective rules within the style-sheet, as
|
||||
|
@ -255,8 +239,12 @@ pub trait StylesheetInDocument {
|
|||
}
|
||||
|
||||
impl StylesheetInDocument for Stylesheet {
|
||||
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
|
||||
&self.contents
|
||||
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||
self.contents.origin
|
||||
}
|
||||
|
||||
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||
self.contents.quirks_mode
|
||||
}
|
||||
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||
|
@ -266,6 +254,11 @@ impl StylesheetInDocument for Stylesheet {
|
|||
fn enabled(&self) -> bool {
|
||||
!self.disabled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||
self.contents.rules(guard)
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple wrapper over an `Arc<Stylesheet>`, with pointer comparison, and
|
||||
|
@ -289,8 +282,12 @@ impl ToMediaListKey for DocumentStyleSheet {
|
|||
}
|
||||
|
||||
impl StylesheetInDocument for DocumentStyleSheet {
|
||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
|
||||
self.0.contents(guard)
|
||||
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||
self.0.origin(guard)
|
||||
}
|
||||
|
||||
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||
self.0.quirks_mode(guard)
|
||||
}
|
||||
|
||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||
|
@ -300,6 +297,11 @@ impl StylesheetInDocument for DocumentStyleSheet {
|
|||
fn enabled(&self) -> bool {
|
||||
self.0.enabled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||
self.0.rules(guard)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stylesheet {
|
||||
|
|
|
@ -2048,7 +2048,7 @@ pub extern "C" fn Servo_ImportRule_GetSheet(
|
|||
rule: RawServoImportRuleBorrowed,
|
||||
) -> *const ServoStyleSheet {
|
||||
read_locked_arc(rule, |rule: &ImportRule| {
|
||||
rule.stylesheet.0.raw() as *const ServoStyleSheet
|
||||
rule.stylesheet.as_sheet().unwrap().raw() as *const ServoStyleSheet
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,8 @@ impl StyleStylesheetLoader for StylesheetLoader {
|
|||
|
||||
debug_assert!(!child_sheet.is_null(),
|
||||
"Import rules should always have a strong sheet");
|
||||
let stylesheet = unsafe {
|
||||
ImportSheet(GeckoStyleSheet::from_addrefed(child_sheet))
|
||||
};
|
||||
let sheet = unsafe { GeckoStyleSheet::from_addrefed(child_sheet) };
|
||||
let stylesheet = ImportSheet::new(sheet);
|
||||
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue