stylo: Fix StyleSheetInner/Stylesheet mapping

The key of this patch is the split between Stylesheet and StylesheetContents.

Gecko will use StylesheetContents, which maps to a ServoStyleSheetInner.
This commit is contained in:
Emilio Cobos Álvarez 2017-06-28 12:12:14 -07:00
parent fd65ac8924
commit 1263075776
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
38 changed files with 3818 additions and 2931 deletions

View file

@ -101,6 +101,7 @@ use std::marker::PhantomData;
use std::mem as std_mem;
use std::ops::{Deref, DerefMut};
use std::process;
use std::slice;
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::mpsc::{Receiver, Sender, channel};
@ -117,7 +118,7 @@ use style::selector_parser::SnapshotMap;
use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW};
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards};
use style::stylearc::Arc as StyleArc;
use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
use style::stylesheets::{Origin, Stylesheet, StylesheetInDocument, UserAgentStylesheets};
use style::stylist::{ExtraStyleData, Stylist};
use style::thread_state;
use style::timer::Timer;
@ -417,6 +418,17 @@ fn add_font_face_rules(stylesheet: &Stylesheet,
}
}
#[derive(Clone)]
struct StylesheetIterator<'a>(slice::Iter<'a, StyleArc<Stylesheet>>);
impl<'a> Iterator for StylesheetIterator<'a> {
type Item = &'a Stylesheet;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|s| &**s)
}
}
impl LayoutThread {
/// Creates a new `LayoutThread` structure.
fn new(id: PipelineId,
@ -1146,7 +1158,7 @@ impl LayoutThread {
marker: PhantomData,
};
let needs_dirtying = self.stylist.update(
data.document_stylesheets.iter(),
StylesheetIterator(data.document_stylesheets.iter()),
&guards,
Some(ua_stylesheets),
data.stylesheets_changed,

View file

@ -82,7 +82,13 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule {
// https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-appendrule
fn AppendRule(&self, rule: DOMString) {
let rule = Keyframe::parse(&rule, self.cssrule.parent_stylesheet().style_stylesheet());
let style_stylesheet = self.cssrule.parent_stylesheet().style_stylesheet();
let rule = Keyframe::parse(
&rule,
&style_stylesheet.contents,
&style_stylesheet.shared_lock
);
if let Ok(rule) = rule {
let mut guard = self.cssrule.shared_lock().write();
self.keyframesrule.write_with(&mut guard).keyframes.push(rule);

View file

@ -93,7 +93,7 @@ impl CSSRuleList {
let new_rule =
css_rules.insert_rule(&parent_stylesheet.shared_lock,
rule,
parent_stylesheet,
&parent_stylesheet.contents,
index,
nested,
None)?;

View file

@ -146,7 +146,7 @@ impl CSSStyleOwner {
match *self {
CSSStyleOwner::Element(ref el) => window_from_node(&**el).Document().base_url(),
CSSStyleOwner::CSSRule(ref rule, _) => {
(*rule.parent_stylesheet().style_stylesheet().url_data.read()).clone()
(*rule.parent_stylesheet().style_stylesheet().contents.url_data.read()).clone()
}
}
}

View file

@ -57,10 +57,14 @@ impl CSSStyleSheet {
}
fn rulelist(&self) -> Root<CSSRuleList> {
self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(),
self,
RulesSource::Rules(self.style_stylesheet
.rules.clone())))
self.rulelist.or_init(|| {
let rules = self.style_stylesheet.contents.rules.clone();
CSSRuleList::new(
self.global().as_window(),
self,
RulesSource::Rules(rules)
)
})
}
pub fn disabled(&self) -> bool {

View file

@ -27,7 +27,7 @@ use style::attr::AttrValue;
use style::media_queries::MediaList;
use style::str::HTML_SPACE_CHARACTERS;
use style::stylearc::Arc;
use style::stylesheets::{Stylesheet, CssRule, CssRules, Origin, ViewportRule};
use style::stylesheets::{Stylesheet, StylesheetContents, CssRule, CssRules, Origin, ViewportRule};
#[dom_struct]
pub struct HTMLMetaElement {
@ -103,17 +103,20 @@ impl HTMLMetaElement {
let shared_lock = document.style_shared_lock();
let rule = CssRule::Viewport(Arc::new(shared_lock.wrap(translated_rule)));
*self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet {
rules: CssRules::new(vec![rule], shared_lock),
origin: Origin::Author,
shared_lock: shared_lock.clone(),
url_data: RwLock::new(window_from_node(self).get_url()),
namespaces: Default::default(),
contents: StylesheetContents {
rules: CssRules::new(vec![rule], shared_lock),
origin: Origin::Author,
namespaces: Default::default(),
quirks_mode: document.quirks_mode(),
url_data: RwLock::new(window_from_node(self).get_url()),
// Viewport constraints are always recomputed on
// resize; they don't need to force all styles to be
// recomputed.
dirty_on_viewport_size_change: AtomicBool::new(false),
},
media: Arc::new(shared_lock.wrap(MediaList::empty())),
// Viewport constraints are always recomputed on resize; they don't need to
// force all styles to be recomputed.
dirty_on_viewport_size_change: AtomicBool::new(false),
shared_lock: shared_lock.clone(),
disabled: AtomicBool::new(false),
quirks_mode: document.quirks_mode(),
}));
let doc = document_from_node(self);
doc.invalidate_stylesheets();

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::SourceLocation;
use document_loader::LoadType;
use dom::bindings::inheritance::Castable;
use dom::bindings::refcounted::Trusted;
@ -22,14 +23,19 @@ use ipc_channel::router::ROUTER;
use net_traits::{FetchResponseListener, FetchMetadata, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy};
use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
use network_listener::{NetworkListener, PreInvoke};
use parking_lot::RwLock;
use servo_url::ServoUrl;
use std::mem;
use std::sync::Mutex;
use std::sync::atomic::AtomicBool;
use style::media_queries::MediaList;
use style::shared_lock::Locked as StyleLocked;
use style::parser::ParserContext;
use style::shared_lock::{Locked, SharedRwLock};
use style::stylearc::Arc;
use style::stylesheets::{ImportRule, Stylesheet, Origin};
use style::stylesheets::{CssRules, ImportRule, Namespaces, Stylesheet, StylesheetContents, Origin};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::import_rule::ImportSheet;
use style::values::specified::url::SpecifiedUrl;
pub trait StylesheetOwner {
/// Returns whether this element was inserted by the parser (i.e., it should
@ -268,20 +274,43 @@ impl<'a> StylesheetLoader<'a> {
}
impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> {
/// Request a stylesheet after parsing a given `@import` rule, and return
/// the constructed `@import` rule.
fn request_stylesheet(
&self,
media: Arc<StyleLocked<MediaList>>,
make_import: &mut FnMut(Arc<StyleLocked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<StyleLocked<ImportRule>>,
) -> Arc<StyleLocked<ImportRule>> {
let import = make_import(media);
let url = import.url.url().expect("Invalid urls shouldn't enter the loader").clone();
url: SpecifiedUrl,
source_location: SourceLocation,
context: &ParserContext,
lock: &SharedRwLock,
media: Arc<Locked<MediaList>>,
) -> Arc<Locked<ImportRule>> {
let sheet = Arc::new(Stylesheet {
contents: StylesheetContents {
rules: CssRules::new(Vec::new(), lock),
origin: context.stylesheet_origin,
url_data: RwLock::new(context.url_data.clone()),
dirty_on_viewport_size_change: AtomicBool::new(false),
quirks_mode: context.quirks_mode,
namespaces: RwLock::new(Namespaces::default()),
},
media: media,
shared_lock: lock.clone(),
disabled: AtomicBool::new(false),
});
let stylesheet = ImportSheet(sheet.clone());
let import = ImportRule { url, source_location, stylesheet };
let url = match import.url.url().cloned() {
Some(url) => url,
None => return Arc::new(lock.wrap(import)),
};
// TODO (mrnayak) : Whether we should use the original loader's CORS
// setting? Fix this when spec has more details.
let source = StylesheetContextSource::Import(import.stylesheet.clone());
let source = StylesheetContextSource::Import(sheet.clone());
self.load(source, url, None, "".to_owned());
make_arc(import)
Arc::new(lock.wrap(import))
}
}

View file

@ -8,14 +8,13 @@
#![allow(non_snake_case, missing_docs)]
use gecko_bindings::bindings::{RawServoImportRule, RawServoSupportsRule};
use gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframesRule};
use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule};
use gecko_bindings::bindings::{RawServoNamespaceRule, RawServoPageRule};
use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule};
use gecko_bindings::bindings::{RawServoStyleSheet, RawServoImportRule, RawServoSupportsRule};
use gecko_bindings::bindings::{RawServoRuleNode, RawServoRuleNodeStrong, RawServoDocumentRule, RawServoMediaRule};
use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
use gecko_bindings::structs::{RawServoDeclarationBlock, RawServoStyleRule};
use gecko_bindings::structs::RawServoAnimationValue;
use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock, RawServoStyleRule, RawServoMediaList};
use gecko_bindings::structs::RawServoStyleSheetContents;
use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
use media_queries::MediaList;
use properties::{ComputedValues, PropertyDeclarationBlock};
@ -23,7 +22,7 @@ use properties::animated_properties::AnimationValue;
use rule_tree::StrongRuleNode;
use shared_lock::Locked;
use std::{mem, ptr};
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, KeyframesRule, MediaRule};
use stylesheets::{CssRules, StylesheetContents, StyleRule, ImportRule, KeyframesRule, MediaRule};
use stylesheets::{NamespaceRule, PageRule, SupportsRule, DocumentRule};
use stylesheets::keyframes_rule::Keyframe;
@ -49,8 +48,8 @@ macro_rules! impl_arc_ffi {
impl_arc_ffi!(Locked<CssRules> => ServoCssRules
[Servo_CssRules_AddRef, Servo_CssRules_Release]);
impl_arc_ffi!(Stylesheet => RawServoStyleSheet
[Servo_StyleSheet_AddRef, Servo_StyleSheet_Release]);
impl_arc_ffi!(StylesheetContents => RawServoStyleSheetContents
[Servo_StyleSheetContents_AddRef, Servo_StyleSheetContents_Release]);
impl_arc_ffi!(ComputedValues => ServoComputedValues
[Servo_ComputedValues_AddRef, Servo_ComputedValues_Release]);

View file

@ -9,18 +9,108 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use dom::TElement;
use fnv::FnvHashMap;
use gecko::rules::{CounterStyleRule, FontFaceRule};
use gecko_bindings::bindings::RawServoStyleSet;
use gecko_bindings::bindings::{self, RawServoStyleSet};
use gecko_bindings::structs::{ServoStyleSheet, StyleSheetInfo, ServoStyleSheetInner};
use gecko_bindings::structs::RawGeckoPresContextOwned;
use gecko_bindings::structs::nsIDocument;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use media_queries::Device;
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
use media_queries::{Device, MediaList};
use properties::ComputedValues;
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use stylearc::Arc;
use stylesheet_set::StylesheetSet;
use stylesheets::Origin;
use stylesheets::{Origin, StylesheetContents, StylesheetInDocument};
use stylist::{ExtraStyleData, Stylist};
/// Little wrapper to a Gecko style sheet.
#[derive(PartialEq, Eq, Debug)]
pub struct GeckoStyleSheet(*const ServoStyleSheet);
impl ToMediaListKey for ::gecko::data::GeckoStyleSheet {
fn to_media_list_key(&self) -> MediaListKey {
use std::mem;
unsafe {
MediaListKey::from_raw(mem::transmute(self.0))
}
}
}
impl GeckoStyleSheet {
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer.
#[inline]
pub unsafe fn new(s: *const ServoStyleSheet) -> Self {
debug_assert!(!s.is_null());
bindings::Gecko_StyleSheet_AddRef(s);
Self::from_addrefed(s)
}
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer that
/// already holds a strong reference.
#[inline]
pub unsafe fn from_addrefed(s: *const ServoStyleSheet) -> Self {
debug_assert!(!s.is_null());
GeckoStyleSheet(s)
}
/// Get the raw `ServoStyleSheet` that we're wrapping.
pub fn raw(&self) -> &ServoStyleSheet {
unsafe { &*self.0 }
}
fn inner(&self) -> &ServoStyleSheetInner {
unsafe {
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
}
}
}
impl Drop for GeckoStyleSheet {
fn drop(&mut self) {
unsafe { bindings::Gecko_StyleSheet_Release(self.0) };
}
}
impl Clone for GeckoStyleSheet {
fn clone(&self) -> Self {
unsafe { bindings::Gecko_StyleSheet_AddRef(self.0) };
GeckoStyleSheet(self.0)
}
}
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 media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
use gecko_bindings::structs::ServoMediaList;
use std::mem;
unsafe {
let servo_media_list =
self.raw()._base.mMedia.mRawPtr as *const ServoMediaList;
if servo_media_list.is_null() {
return None;
}
let raw_list = &*(*servo_media_list).mRawList.mRawPtr;
let list = Locked::<MediaList>::as_arc(mem::transmute(&raw_list));
Some(list.read_with(guard))
}
}
// All the stylesheets Servo knows about are enabled, because that state is
// handled externally by Gecko.
fn enabled(&self) -> bool {
true
}
}
/// The container for data that a Servo-backed Gecko document needs to style
/// itself.
pub struct PerDocumentStyleDataImpl {
@ -28,7 +118,7 @@ pub struct PerDocumentStyleDataImpl {
pub stylist: Stylist,
/// List of stylesheets, mirrored from Gecko.
pub stylesheets: StylesheetSet,
pub stylesheets: StylesheetSet<GeckoStyleSheet>,
/// List of effective font face rules.
pub font_faces: Vec<(Arc<Locked<FontFaceRule>>, Origin)>,
@ -87,12 +177,14 @@ impl PerDocumentStyleDataImpl {
let author_style_disabled = self.stylesheets.author_style_disabled();
self.stylist.clear();
let iter = self.stylesheets.flush(document_element);
self.stylist.rebuild(iter,
&StylesheetGuards::same(guard),
/* ua_sheets = */ None,
/* stylesheets_changed = */ true,
author_style_disabled,
&mut extra_data);
self.stylist.rebuild(
iter,
&StylesheetGuards::same(guard),
/* ua_sheets = */ None,
/* stylesheets_changed = */ true,
author_style_disabled,
&mut extra_data
);
}
/// Get the default computed values for this document.

View file

@ -4334,6 +4334,8 @@ cfg_if! {
pub static nsGkAtoms_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms18overlay_scrollbarsE"]
pub static nsGkAtoms_overlay_scrollbars: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms28windows_accent_color_appliesE"]
pub static nsGkAtoms_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms21windows_default_themeE"]
pub static nsGkAtoms_windows_default_theme: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms18mac_graphite_themeE"]
@ -4384,6 +4386,8 @@ cfg_if! {
pub static nsGkAtoms__moz_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms23_moz_overlay_scrollbarsE"]
pub static nsGkAtoms__moz_overlay_scrollbars: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms33_moz_windows_accent_color_appliesE"]
pub static nsGkAtoms__moz_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms26_moz_windows_default_themeE"]
pub static nsGkAtoms__moz_windows_default_theme: *mut nsIAtom;
#[link_name = "_ZN9nsGkAtoms23_moz_mac_graphite_themeE"]
@ -9455,6 +9459,8 @@ cfg_if! {
pub static nsGkAtoms_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "?overlay_scrollbars@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_overlay_scrollbars: *mut nsIAtom;
#[link_name = "?windows_accent_color_applies@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "?windows_default_theme@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms_windows_default_theme: *mut nsIAtom;
#[link_name = "?mac_graphite_theme@nsGkAtoms@@2PEAVnsIAtom@@EA"]
@ -9505,6 +9511,8 @@ cfg_if! {
pub static nsGkAtoms__moz_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "?_moz_overlay_scrollbars@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms__moz_overlay_scrollbars: *mut nsIAtom;
#[link_name = "?_moz_windows_accent_color_applies@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms__moz_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "?_moz_windows_default_theme@nsGkAtoms@@2PEAVnsIAtom@@EA"]
pub static nsGkAtoms__moz_windows_default_theme: *mut nsIAtom;
#[link_name = "?_moz_mac_graphite_theme@nsGkAtoms@@2PEAVnsIAtom@@EA"]
@ -14576,6 +14584,8 @@ cfg_if! {
pub static nsGkAtoms_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "\x01?overlay_scrollbars@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_overlay_scrollbars: *mut nsIAtom;
#[link_name = "\x01?windows_accent_color_applies@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "\x01?windows_default_theme@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms_windows_default_theme: *mut nsIAtom;
#[link_name = "\x01?mac_graphite_theme@nsGkAtoms@@2PAVnsIAtom@@A"]
@ -14626,6 +14636,8 @@ cfg_if! {
pub static nsGkAtoms__moz_scrollbar_thumb_proportional: *mut nsIAtom;
#[link_name = "\x01?_moz_overlay_scrollbars@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms__moz_overlay_scrollbars: *mut nsIAtom;
#[link_name = "\x01?_moz_windows_accent_color_applies@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms__moz_windows_accent_color_applies: *mut nsIAtom;
#[link_name = "\x01?_moz_windows_default_theme@nsGkAtoms@@2PAVnsIAtom@@A"]
pub static nsGkAtoms__moz_windows_default_theme: *mut nsIAtom;
#[link_name = "\x01?_moz_mac_graphite_theme@nsGkAtoms@@2PAVnsIAtom@@A"]
@ -19700,6 +19712,8 @@ macro_rules! atom {
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_scrollbar_thumb_proportional as *mut _) } };
("overlay-scrollbars") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_overlay_scrollbars as *mut _) } };
("windows-accent-color-applies") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_accent_color_applies as *mut _) } };
("windows-default-theme") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_default_theme as *mut _) } };
("mac-graphite-theme") =>
@ -19750,6 +19764,8 @@ macro_rules! atom {
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_scrollbar_thumb_proportional as *mut _) } };
("-moz-overlay-scrollbars") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_overlay_scrollbars as *mut _) } };
("-moz-windows-accent-color-applies") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_windows_accent_color_applies as *mut _) } };
("-moz-windows-default-theme") =>
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_windows_default_theme as *mut _) } };
("-moz-mac-graphite-theme") =>

View file

@ -24,6 +24,8 @@ use gecko_bindings::structs::RawGeckoFontFaceRuleList;
use gecko_bindings::structs::RawGeckoNode;
use gecko_bindings::structs::RawServoAnimationValue;
use gecko_bindings::structs::RawGeckoServoAnimationValueList;
use gecko_bindings::structs::RawServoMediaList;
use gecko_bindings::structs::RawServoStyleSheetContents;
use gecko_bindings::structs::RawServoDeclarationBlock;
use gecko_bindings::structs::RawServoStyleRule;
use gecko_bindings::structs::RawGeckoPresContext;
@ -305,11 +307,9 @@ pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;
pub type ServoCssRulesBorrowedOrNull<'a> = Option<&'a ServoCssRules>;
enum ServoCssRulesVoid { }
pub struct ServoCssRules(ServoCssRulesVoid);
pub type RawServoStyleSheetStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoStyleSheet>;
pub type RawServoStyleSheetBorrowed<'a> = &'a RawServoStyleSheet;
pub type RawServoStyleSheetBorrowedOrNull<'a> = Option<&'a RawServoStyleSheet>;
enum RawServoStyleSheetVoid { }
pub struct RawServoStyleSheet(RawServoStyleSheetVoid);
pub type RawServoStyleSheetContentsStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoStyleSheetContents>;
pub type RawServoStyleSheetContentsBorrowed<'a> = &'a RawServoStyleSheetContents;
pub type RawServoStyleSheetContentsBorrowedOrNull<'a> = Option<&'a RawServoStyleSheetContents>;
pub type ServoComputedValuesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoComputedValues>;
pub type ServoComputedValuesBorrowed<'a> = &'a ServoComputedValues;
pub type ServoComputedValuesBorrowedOrNull<'a> = Option<&'a ServoComputedValues>;
@ -342,8 +342,6 @@ pub struct RawServoKeyframesRule(RawServoKeyframesRuleVoid);
pub type RawServoMediaListStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoMediaList>;
pub type RawServoMediaListBorrowed<'a> = &'a RawServoMediaList;
pub type RawServoMediaListBorrowedOrNull<'a> = Option<&'a RawServoMediaList>;
enum RawServoMediaListVoid { }
pub struct RawServoMediaList(RawServoMediaListVoid);
pub type RawServoMediaRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoMediaRule>;
pub type RawServoMediaRuleBorrowed<'a> = &'a RawServoMediaRule;
pub type RawServoMediaRuleBorrowedOrNull<'a> = Option<&'a RawServoMediaRule>;
@ -390,10 +388,12 @@ extern "C" {
pub fn Servo_CssRules_Release(ptr: ServoCssRulesBorrowed);
}
extern "C" {
pub fn Servo_StyleSheet_AddRef(ptr: RawServoStyleSheetBorrowed);
pub fn Servo_StyleSheetContents_AddRef(ptr:
RawServoStyleSheetContentsBorrowed);
}
extern "C" {
pub fn Servo_StyleSheet_Release(ptr: RawServoStyleSheetBorrowed);
pub fn Servo_StyleSheetContents_Release(ptr:
RawServoStyleSheetContentsBorrowed);
}
extern "C" {
pub fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed);
@ -544,10 +544,10 @@ extern "C" {
parent: *mut ServoStyleSheet,
reusable_sheets:
*mut LoaderReusableStyleSheets,
child_sheet: RawServoStyleSheetBorrowed,
base_url_data: *mut RawGeckoURLExtraData,
url_bytes: *const u8, url_length: u32,
media_list: RawServoMediaListStrong);
media_list: RawServoMediaListStrong)
-> *mut ServoStyleSheet;
}
extern "C" {
pub fn Gecko_ElementState(element: RawGeckoElementBorrowed) -> u64;
@ -1416,6 +1416,17 @@ extern "C" {
RawGeckoPresContextBorrowed)
-> i32;
}
extern "C" {
pub fn Gecko_StyleSheet_Clone(aSheet: *const ServoStyleSheet,
aNewParentSheet: *const ServoStyleSheet)
-> *mut ServoStyleSheet;
}
extern "C" {
pub fn Gecko_StyleSheet_AddRef(aSheet: *const ServoStyleSheet);
}
extern "C" {
pub fn Gecko_StyleSheet_Release(aSheet: *const ServoStyleSheet);
}
extern "C" {
pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature;
}
@ -1813,53 +1824,41 @@ extern "C" {
extern "C" {
pub fn Servo_Element_ClearData(node: RawGeckoElementBorrowed);
}
extern "C" {
pub fn Servo_StyleSheet_Empty(parsing_mode: SheetParsingMode)
-> RawServoStyleSheetStrong;
}
extern "C" {
pub fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
gecko_stylesheet:
*mut ServoStyleSheet,
data: *const nsACString,
parsing_mode: SheetParsingMode,
media_list:
*const RawServoMediaList,
extra_data:
*mut RawGeckoURLExtraData,
line_number_offset: u32,
quirks_mode: nsCompatibility)
-> RawServoStyleSheetStrong;
-> RawServoStyleSheetContentsStrong;
}
extern "C" {
pub fn Servo_StyleSheet_ClearAndUpdate(stylesheet:
RawServoStyleSheetBorrowed,
loader: *mut Loader,
gecko_stylesheet:
*mut ServoStyleSheet,
data: *const nsACString,
extra_data:
*mut RawGeckoURLExtraData,
line_number_offset: u32,
reusable_sheets:
*mut LoaderReusableStyleSheets);
pub fn Servo_StyleSheet_Empty(parsing_mode: SheetParsingMode)
-> RawServoStyleSheetContentsStrong;
}
extern "C" {
pub fn Servo_StyleSheet_HasRules(sheet: RawServoStyleSheetBorrowed)
pub fn Servo_StyleSheet_HasRules(sheet:
RawServoStyleSheetContentsBorrowed)
-> bool;
}
extern "C" {
pub fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed)
pub fn Servo_StyleSheet_GetRules(sheet:
RawServoStyleSheetContentsBorrowed)
-> ServoCssRulesStrong;
}
extern "C" {
pub fn Servo_StyleSheet_Clone(sheet: RawServoStyleSheetBorrowed)
-> RawServoStyleSheetStrong;
pub fn Servo_StyleSheet_Clone(sheet: RawServoStyleSheetContentsBorrowed,
reference_sheet: *const ServoStyleSheet)
-> RawServoStyleSheetContentsStrong;
}
extern "C" {
pub fn Servo_StyleSheet_SizeOfIncludingThis(malloc_size_of: MallocSizeOf,
sheet:
RawServoStyleSheetBorrowed)
RawServoStyleSheetContentsBorrowed)
-> usize;
}
extern "C" {
@ -1882,30 +1881,26 @@ extern "C" {
}
extern "C" {
pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed,
sheet: RawServoStyleSheetBorrowed,
unique_id: u64);
gecko_sheet:
*const ServoStyleSheet);
}
extern "C" {
pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowed,
sheet: RawServoStyleSheetBorrowed,
unique_id: u64);
gecko_sheet:
*const ServoStyleSheet);
}
extern "C" {
pub fn Servo_StyleSet_RemoveStyleSheet(set: RawServoStyleSetBorrowed,
unique_id: u64);
gecko_sheet:
*const ServoStyleSheet);
}
extern "C" {
pub fn Servo_StyleSet_InsertStyleSheetBefore(set:
RawServoStyleSetBorrowed,
sheet:
RawServoStyleSheetBorrowed,
unique_id: u64,
before_unique_id: u64);
}
extern "C" {
pub fn Servo_StyleSet_UpdateStyleSheet(set: RawServoStyleSetBorrowed,
sheet: RawServoStyleSheetBorrowed,
unique_id: u64);
gecko_sheet:
*const ServoStyleSheet,
before:
*const ServoStyleSheet);
}
extern "C" {
pub fn Servo_StyleSet_FlushStyleSheets(set: RawServoStyleSetBorrowed,
@ -1967,7 +1962,8 @@ extern "C" {
}
extern "C" {
pub fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
sheet: RawServoStyleSheetBorrowed,
sheet:
RawServoStyleSheetContentsBorrowed,
rule: *const nsACString, index: u32,
nested: bool, loader: *mut Loader,
gecko_stylesheet: *mut ServoStyleSheet,
@ -2154,7 +2150,7 @@ extern "C" {
}
extern "C" {
pub fn Servo_ImportRule_GetSheet(rule: RawServoImportRuleBorrowed)
-> *const RawServoStyleSheet;
-> *const ServoStyleSheet;
}
extern "C" {
pub fn Servo_Keyframe_GetKeyText(keyframe: RawServoKeyframeBorrowed,
@ -2197,7 +2193,8 @@ extern "C" {
}
extern "C" {
pub fn Servo_KeyframesRule_AppendRule(rule: RawServoKeyframesRuleBorrowed,
sheet: RawServoStyleSheetBorrowed,
sheet:
RawServoStyleSheetContentsBorrowed,
css: *const nsACString) -> bool;
}
extern "C" {
@ -2264,6 +2261,11 @@ extern "C" {
nsCSSPropertyID)
-> RawServoAnimationValueStrong;
}
extern "C" {
pub fn Servo_ComputedValues_SpecifiesAnimationsOrTransitions(computed_values:
ServoComputedValuesBorrowed)
-> bool;
}
extern "C" {
pub fn Servo_Property_IsAnimatable(property: nsCSSPropertyID) -> bool;
}
@ -2679,6 +2681,10 @@ extern "C" {
set: RawServoStyleSetBorrowed)
-> ServoComputedValuesStrong;
}
extern "C" {
pub fn Servo_SetExplicitStyle(element: RawGeckoElementBorrowed,
primary_style: ServoComputedValuesBorrowed);
}
extern "C" {
pub fn Servo_HasAuthorSpecifiedRules(element: RawGeckoElementBorrowed,
rule_type_mask: u32,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,6 +27,13 @@ use stylesheets::{NestedRuleIterationCondition, Stylesheet};
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MediaListKey(usize);
impl MediaListKey {
/// Create a MediaListKey from a raw usize.
pub fn from_raw(k: usize) -> Self {
MediaListKey(k)
}
}
/// A trait to get a given `MediaListKey` for a given item that can hold a
/// `MediaList`.
pub trait ToMediaListKey : Sized {

View file

@ -15,7 +15,7 @@ use selector_parser::SelectorImpl;
use selectors::attr::CaseSensitivity;
use selectors::parser::{Component, Selector};
use shared_lock::SharedRwLockReadGuard;
use stylesheets::{CssRule, Stylesheet};
use stylesheets::{CssRule, StylesheetInDocument};
use stylist::Stylist;
/// An invalidation scope represents a kind of subtree that may need to be
@ -80,11 +80,14 @@ impl StylesheetInvalidationSet {
/// Analyze the given stylesheet, and collect invalidations from their
/// rules, in order to avoid doing a full restyle when we style the document
/// next time.
pub fn collect_invalidations_for(
pub fn collect_invalidations_for<S>(
&mut self,
stylist: &Stylist,
stylesheet: &Stylesheet,
guard: &SharedRwLockReadGuard)
stylesheet: &S,
guard: &SharedRwLockReadGuard
)
where
S: StylesheetInDocument,
{
debug!("StylesheetInvalidationSet::collect_invalidations_for");
if self.fully_invalid {
@ -92,7 +95,7 @@ impl StylesheetInvalidationSet {
return;
}
if stylesheet.disabled() ||
if !stylesheet.enabled() ||
!stylesheet.is_effective_for_device(stylist.device(), guard) {
debug!(" > Stylesheet was not effective");
return; // Nothing to do here.

View file

@ -228,6 +228,18 @@ pub trait ToCssWithGuard {
}
}
/// Parameters needed for deep clones.
#[cfg(feature = "gecko")]
pub struct DeepCloneParams {
/// The new sheet we're cloning rules into.
pub reference_sheet: *const ::gecko_bindings::structs::ServoStyleSheet,
}
/// Parameters needed for deep clones.
#[cfg(feature = "servo")]
pub struct DeepCloneParams;
/// A trait to do a deep clone of a given CSS type. Gets a lock and a read
/// guard, in order to be able to read and clone nested structures.
pub trait DeepCloneWithLock : Sized {
@ -235,7 +247,8 @@ pub trait DeepCloneWithLock : Sized {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self;
}

View file

@ -8,36 +8,46 @@ use dom::TElement;
use invalidation::stylesheets::StylesheetInvalidationSet;
use shared_lock::SharedRwLockReadGuard;
use std::slice;
use stylearc::Arc;
use stylesheets::Stylesheet;
use stylesheets::StylesheetInDocument;
use stylist::Stylist;
/// Entry for a StylesheetSet. We don't bother creating a constructor, because
/// there's no sensible defaults for the member variables.
pub struct StylesheetSetEntry {
unique_id: u64,
sheet: Arc<Stylesheet>,
pub struct StylesheetSetEntry<S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
sheet: S,
}
/// A iterator over the stylesheets of a list of entries in the StylesheetSet.
#[derive(Clone)]
pub struct StylesheetIterator<'a>(slice::Iter<'a, StylesheetSetEntry>);
pub struct StylesheetIterator<'a, S>(slice::Iter<'a, StylesheetSetEntry<S>>)
where
S: StylesheetInDocument + PartialEq + 'static;
impl<'a, S> Iterator for StylesheetIterator<'a, S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
type Item = &'a S;
impl<'a> Iterator for StylesheetIterator<'a> {
type Item = &'a Arc<Stylesheet>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|entry| &entry.sheet)
}
}
/// The set of stylesheets effective for a given document.
pub struct StylesheetSet {
pub struct StylesheetSet<S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
/// The actual list of all the stylesheets that apply to the given document,
/// each stylesheet associated with a unique ID.
///
/// This is only a list of top-level stylesheets, and as such it doesn't
/// include recursive `@import` rules.
entries: Vec<StylesheetSetEntry>,
entries: Vec<StylesheetSetEntry<S>>,
/// Whether the entries list above has changed since the last restyle.
dirty: bool,
@ -49,7 +59,10 @@ pub struct StylesheetSet {
invalidations: StylesheetInvalidationSet,
}
impl StylesheetSet {
impl<S> StylesheetSet<S>
where
S: StylesheetInDocument + PartialEq + 'static,
{
/// Create a new empty StylesheetSet.
pub fn new() -> Self {
StylesheetSet {
@ -66,98 +79,72 @@ impl StylesheetSet {
self.author_style_disabled
}
fn remove_stylesheet_if_present(&mut self, unique_id: u64) {
self.entries.retain(|x| x.unique_id != unique_id);
fn remove_stylesheet_if_present(&mut self, sheet: &S) {
self.entries.retain(|entry| entry.sheet != *sheet);
}
/// Appends a new stylesheet to the current set.
pub fn append_stylesheet(
&mut self,
stylist: &Stylist,
sheet: &Arc<Stylesheet>,
unique_id: u64,
guard: &SharedRwLockReadGuard)
{
sheet: S,
guard: &SharedRwLockReadGuard
) {
debug!("StylesheetSet::append_stylesheet");
self.remove_stylesheet_if_present(unique_id);
self.entries.push(StylesheetSetEntry {
unique_id: unique_id,
sheet: sheet.clone(),
});
self.dirty = true;
self.remove_stylesheet_if_present(&sheet);
self.invalidations.collect_invalidations_for(
stylist,
sheet,
guard)
&sheet,
guard
);
self.dirty = true;
self.entries.push(StylesheetSetEntry { sheet });
}
/// Prepend a new stylesheet to the current set.
pub fn prepend_stylesheet(
&mut self,
stylist: &Stylist,
sheet: &Arc<Stylesheet>,
unique_id: u64,
guard: &SharedRwLockReadGuard)
{
sheet: S,
guard: &SharedRwLockReadGuard
) {
debug!("StylesheetSet::prepend_stylesheet");
self.remove_stylesheet_if_present(unique_id);
self.entries.insert(0, StylesheetSetEntry {
unique_id: unique_id,
sheet: sheet.clone(),
});
self.dirty = true;
self.remove_stylesheet_if_present(&sheet);
self.invalidations.collect_invalidations_for(
stylist,
sheet,
guard)
&sheet,
guard
);
self.entries.insert(0, StylesheetSetEntry { sheet });
self.dirty = true;
}
/// Insert a given stylesheet before another stylesheet in the document.
pub fn insert_stylesheet_before(
&mut self,
stylist: &Stylist,
sheet: &Arc<Stylesheet>,
unique_id: u64,
before_unique_id: u64,
sheet: S,
before_sheet: S,
guard: &SharedRwLockReadGuard)
{
debug!("StylesheetSet::insert_stylesheet_before");
self.remove_stylesheet_if_present(unique_id);
let index = self.entries.iter().position(|x| {
x.unique_id == before_unique_id
}).expect("`before_unique_id` stylesheet not found");
self.entries.insert(index, StylesheetSetEntry {
unique_id: unique_id,
sheet: sheet.clone(),
});
self.dirty = true;
self.remove_stylesheet_if_present(&sheet);
let index = self.entries.iter().position(|entry| {
entry.sheet == before_sheet
}).expect("`before_sheet` stylesheet not found");
self.invalidations.collect_invalidations_for(
stylist,
sheet,
guard)
}
/// Update the sheet that matches the unique_id.
pub fn update_stylesheet(
&mut self,
sheet: &Arc<Stylesheet>,
unique_id: u64)
{
// Since this function doesn't set self.dirty, or call
// self.invalidations.collect_invalidations_for, it should
// only be called in the case where sheet is a clone of
// the sheet it is updating.
debug!("StylesheetSet::update_stylesheet");
if let Some(entry) = self.entries.iter_mut().find(
|e| e.unique_id == unique_id) {
entry.sheet = sheet.clone();
}
&sheet,
guard
);
self.entries.insert(index, StylesheetSetEntry { sheet });
self.dirty = true;
}
/// Remove a given stylesheet from the set.
pub fn remove_stylesheet(&mut self, unique_id: u64) {
pub fn remove_stylesheet(&mut self, sheet: S) {
debug!("StylesheetSet::remove_stylesheet");
self.remove_stylesheet_if_present(unique_id);
self.remove_stylesheet_if_present(&sheet);
self.dirty = true;
// FIXME(emilio): We can do better!
self.invalidations.invalidate_fully();
@ -181,10 +168,12 @@ impl StylesheetSet {
/// Flush the current set, unmarking it as dirty, and returns an iterator
/// over the new stylesheet list.
pub fn flush<E>(&mut self,
document_element: Option<E>)
-> StylesheetIterator
where E: TElement,
pub fn flush<E>(
&mut self,
document_element: Option<E>
) -> StylesheetIterator<S>
where
E: TElement,
{
debug!("StylesheetSet::flush");
debug_assert!(self.dirty);
@ -196,7 +185,7 @@ impl StylesheetSet {
}
/// Returns an iterator over the current list of stylesheets.
pub fn iter(&self) -> StylesheetIterator {
pub fn iter(&self) -> StylesheetIterator<S> {
StylesheetIterator(self.entries.iter())
}

View file

@ -9,7 +9,7 @@
use cssparser::{Parser, Token, SourceLocation, BasicParseError};
use media_queries::Device;
use parser::{Parse, ParserContext};
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylearc::Arc;
@ -47,11 +47,12 @@ impl DeepCloneWithLock for DocumentRule {
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
let rules = self.rules.read_with(guard);
DocumentRule {
condition: self.condition.clone(),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard))),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
source_location: self.source_location.clone(),
}
}

View file

@ -7,13 +7,72 @@
//! [import]: https://drafts.csswg.org/css-cascade-3/#at-import
use cssparser::SourceLocation;
use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
use media_queries::MediaList;
use shared_lock::{DeepCloneWithLock, DeepCloneParams, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use stylearc::Arc;
use stylesheets::stylesheet::Stylesheet;
use stylesheets::{StylesheetContents, StylesheetInDocument};
use values::specified::url::SpecifiedUrl;
/// A sheet that is held from an import rule.
#[cfg(feature = "gecko")]
#[derive(Debug)]
pub struct ImportSheet(pub ::gecko::data::GeckoStyleSheet);
#[cfg(feature = "gecko")]
impl DeepCloneWithLock for ImportSheet {
fn deep_clone_with_lock(
&self,
_lock: &SharedRwLock,
_guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> 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) })
}
}
/// A sheet that is held from an import rule.
#[cfg(feature = "servo")]
#[derive(Debug)]
pub struct ImportSheet(pub ::stylearc::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 contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
self.0.contents(guard)
}
fn enabled(&self) -> bool {
self.0.enabled()
}
}
#[cfg(feature = "servo")]
impl DeepCloneWithLock for ImportSheet {
fn deep_clone_with_lock(
&self,
_lock: &SharedRwLock,
_guard: &SharedRwLockReadGuard,
_params: &DeepCloneParams,
) -> Self {
use stylearc::Arc;
ImportSheet(Arc::new((&*self.0).clone()))
}
}
/// The [`@import`][import] at-rule.
///
/// [import]: https://drafts.csswg.org/css-cascade-3/#at-import
@ -26,18 +85,22 @@ pub struct ImportRule {
///
/// It contains an empty list of rules and namespace set that is updated
/// when it loads.
pub stylesheet: Arc<Stylesheet>,
pub stylesheet: ImportSheet,
/// The line and column of the rule's source code.
pub source_location: SourceLocation,
}
impl Clone for ImportRule {
fn clone(&self) -> ImportRule {
let stylesheet: &Stylesheet = &*self.stylesheet;
impl DeepCloneWithLock for ImportRule {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
ImportRule {
url: self.url.clone(),
stylesheet: Arc::new(stylesheet.clone()),
stylesheet: self.stylesheet.deep_clone_with_lock(lock, guard, params),
source_location: self.source_location.clone(),
}
}
@ -49,11 +112,15 @@ impl ToCssWithGuard for ImportRule {
{
dest.write_str("@import ")?;
self.url.to_css(dest)?;
let media = self.stylesheet.media.read_with(guard);
if !media.is_empty() {
dest.write_str(" ")?;
media.to_css(dest)?;
}
match self.stylesheet.media(guard) {
Some(media) if !media.is_empty() => {
dest.write_str(" ")?;
media.to_css(dest)?;
}
_ => {},
};
dest.write_str(";")
}
}

View file

@ -14,11 +14,11 @@ use properties::LonghandIdSet;
use properties::animated_properties::AnimatableLonghand;
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
use selectors::parser::SelectorParseError;
use shared_lock::{DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
use std::fmt;
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
use stylearc::Arc;
use stylesheets::{CssRuleType, Stylesheet};
use stylesheets::{CssRuleType, StylesheetContents};
use stylesheets::rule_parser::VendorPrefix;
use values::KeyframesName;
@ -78,13 +78,17 @@ impl DeepCloneWithLock for KeyframesRule {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
KeyframesRule {
name: self.name.clone(),
keyframes: self.keyframes.iter()
.map(|ref x| Arc::new(lock.wrap(
x.read_with(guard).deep_clone_with_lock(lock, guard))))
.map(|x| {
Arc::new(lock.wrap(
x.read_with(guard).deep_clone_with_lock(lock, guard, params)
))
})
.collect(),
vendor_prefix: self.vendor_prefix.clone(),
source_location: self.source_location.clone(),
@ -202,23 +206,26 @@ impl ToCssWithGuard for Keyframe {
impl Keyframe {
/// Parse a CSS keyframe.
pub fn parse<'i>(css: &'i str, parent_stylesheet: &Stylesheet)
-> Result<Arc<Locked<Self>>, ParseError<'i>> {
let url_data = parent_stylesheet.url_data.read();
pub fn parse<'i>(
css: &'i str,
parent_stylesheet_contents: &StylesheetContents,
lock: &SharedRwLock,
) -> Result<Arc<Locked<Self>>, ParseError<'i>> {
let url_data = parent_stylesheet_contents.url_data.read();
let error_reporter = NullReporter;
let context = ParserContext::new(parent_stylesheet.origin,
let context = ParserContext::new(parent_stylesheet_contents.origin,
&url_data,
&error_reporter,
Some(CssRuleType::Keyframe),
PARSING_MODE_DEFAULT,
parent_stylesheet.quirks_mode);
parent_stylesheet_contents.quirks_mode);
let mut input = ParserInput::new(css);
let mut input = Parser::new(&mut input);
let mut declarations = SourcePropertyDeclaration::new();
let mut rule_parser = KeyframeListParser {
context: &context,
shared_lock: &parent_stylesheet.shared_lock,
shared_lock: &lock,
declarations: &mut declarations,
};
parse_one_rule(&mut input, &mut rule_parser)
@ -230,7 +237,8 @@ impl DeepCloneWithLock for Keyframe {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
_params: &DeepCloneParams,
) -> Keyframe {
Keyframe {
selector: self.selector.clone(),

View file

@ -5,39 +5,25 @@
//! The stylesheet loader is the abstraction used to trigger network requests
//! for `@import` rules.
use cssparser::SourceLocation;
use media_queries::MediaList;
use shared_lock::Locked;
use parser::ParserContext;
use shared_lock::{Locked, SharedRwLock};
use stylearc::Arc;
use stylesheets::ImportRule;
use stylesheets::import_rule::ImportRule;
use values::specified::url::SpecifiedUrl;
/// The stylesheet loader is the abstraction used to trigger network requests
/// for `@import` rules.
pub trait StylesheetLoader {
/// Request a stylesheet after parsing a given `@import` rule.
///
/// The called code is responsible to update the `stylesheet` rules field
/// when the sheet is done loading.
///
/// The convoluted signature allows impls to look at MediaList and
/// ImportRule before theyre locked, while keeping the trait object-safe.
/// Request a stylesheet after parsing a given `@import` rule, and return
/// the constructed `@import` rule.
fn request_stylesheet(
&self,
url: SpecifiedUrl,
location: SourceLocation,
context: &ParserContext,
lock: &SharedRwLock,
media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>>;
}
/// A dummy loader that just creates the import rule with the empty stylesheet.
pub struct NoOpLoader;
impl StylesheetLoader for NoOpLoader {
fn request_stylesheet(
&self,
media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>> {
make_arc(make_import(media))
}
}

View file

@ -8,7 +8,7 @@
use cssparser::SourceLocation;
use media_queries::MediaList;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use stylearc::Arc;
@ -47,13 +47,14 @@ impl DeepCloneWithLock for MediaRule {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
let media_queries = self.media_queries.read_with(guard);
let rules = self.rules.read_with(guard);
MediaRule {
media_queries: Arc::new(lock.wrap(media_queries.clone())),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard))),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
source_location: self.source_location.clone(),
}
}

View file

@ -7,7 +7,7 @@
mod counter_style_rule;
mod document_rule;
mod font_face_rule;
mod import_rule;
pub mod import_rule;
pub mod keyframes_rule;
mod loader;
mod media_rule;
@ -25,7 +25,7 @@ pub mod viewport_rule;
use cssparser::{parse_one_rule, Parser, ParserInput};
use error_reporting::NullReporter;
use parser::ParserContext;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::PARSING_MODE_DEFAULT;
use stylearc::Arc;
@ -43,7 +43,7 @@ pub use self::page_rule::PageRule;
pub use self::rule_parser::{State, TopLevelRuleParser};
pub use self::rule_list::{CssRules, CssRulesHelpers};
pub use self::rules_iterator::{AllRules, EffectiveRules, NestedRuleIterationCondition, RulesIterator};
pub use self::stylesheet::{Namespaces, Stylesheet, UserAgentStylesheets};
pub use self::stylesheet::{Namespaces, Stylesheet, StylesheetContents, StylesheetInDocument, UserAgentStylesheets};
pub use self::style_rule::StyleRule;
pub use self::supports_rule::SupportsRule;
pub use self::viewport_rule::ViewportRule;
@ -221,32 +221,33 @@ impl CssRule {
/// Input state is None for a nested rule
pub fn parse(
css: &str,
parent_stylesheet: &Stylesheet,
parent_stylesheet_contents: &StylesheetContents,
shared_lock: &SharedRwLock,
state: Option<State>,
loader: Option<&StylesheetLoader>
) -> Result<(Self, State), SingleRuleParseError> {
let url_data = parent_stylesheet.url_data.read();
let url_data = parent_stylesheet_contents.url_data.read();
let error_reporter = NullReporter;
let context = ParserContext::new(
parent_stylesheet.origin,
parent_stylesheet_contents.origin,
&url_data,
&error_reporter,
None,
PARSING_MODE_DEFAULT,
parent_stylesheet.quirks_mode
parent_stylesheet_contents.quirks_mode,
);
let mut input = ParserInput::new(css);
let mut input = Parser::new(&mut input);
let mut guard = parent_stylesheet.namespaces.write();
let mut guard = parent_stylesheet_contents.namespaces.write();
// nested rules are in the body state
let state = state.unwrap_or(State::Body);
let mut rule_parser = TopLevelRuleParser {
stylesheet_origin: parent_stylesheet.origin,
stylesheet_origin: parent_stylesheet_contents.origin,
context: context,
shared_lock: &parent_stylesheet.shared_lock,
shared_lock: &shared_lock,
loader: loader,
state: state,
namespaces: Some(&mut *guard),
@ -270,6 +271,7 @@ impl DeepCloneWithLock for CssRule {
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> CssRule {
match *self {
CssRule::Namespace(ref arc) => {
@ -277,18 +279,19 @@ impl DeepCloneWithLock for CssRule {
CssRule::Namespace(Arc::new(lock.wrap(rule.clone())))
},
CssRule::Import(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Import(Arc::new(lock.wrap(rule.clone())))
let rule = arc.read_with(guard)
.deep_clone_with_lock(lock, guard, params);
CssRule::Import(Arc::new(lock.wrap(rule)))
},
CssRule::Style(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Style(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
CssRule::Media(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Media(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
CssRule::FontFace(ref arc) => {
let rule = arc.read_with(guard);
@ -307,22 +310,22 @@ impl DeepCloneWithLock for CssRule {
CssRule::Keyframes(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Keyframes(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
CssRule::Supports(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Supports(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
CssRule::Page(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Page(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
CssRule::Document(ref arc) => {
let rule = arc.read_with(guard);
CssRule::Document(Arc::new(
lock.wrap(rule.deep_clone_with_lock(lock, guard))))
lock.wrap(rule.deep_clone_with_lock(lock, guard, params))))
},
}
}

View file

@ -8,7 +8,7 @@
use cssparser::SourceLocation;
use properties::PropertyDeclarationBlock;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use stylearc::Arc;
@ -51,6 +51,7 @@ impl DeepCloneWithLock for PageRule {
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
_params: &DeepCloneParams,
) -> Self {
PageRule {
block: Arc::new(lock.wrap(self.block.read_with(&guard).clone())),

View file

@ -4,13 +4,13 @@
//! A list of CSS rules.
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
use stylearc::Arc;
use stylesheets::{CssRule, RulesMutateError};
use stylesheets::loader::StylesheetLoader;
use stylesheets::memory::{MallocSizeOfFn, MallocSizeOfWithGuard};
use stylesheets::rule_parser::State;
use stylesheets::stylesheet::Stylesheet;
use stylesheets::stylesheet::StylesheetContents;
/// A list of CSS rules.
#[derive(Debug)]
@ -27,11 +27,12 @@ impl DeepCloneWithLock for CssRules {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
CssRules(
self.0.iter().map(|ref x| x.deep_clone_with_lock(lock, guard)).collect()
)
CssRules(self.0.iter().map(|x| {
x.deep_clone_with_lock(lock, guard, params)
}).collect())
}
}
@ -101,7 +102,7 @@ pub trait CssRulesHelpers {
fn insert_rule(&self,
lock: &SharedRwLock,
rule: &str,
parent_stylesheet: &Stylesheet,
parent_stylesheet_contents: &StylesheetContents,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
@ -112,7 +113,7 @@ impl CssRulesHelpers for Arc<Locked<CssRules>> {
fn insert_rule(&self,
lock: &SharedRwLock,
rule: &str,
parent_stylesheet: &Stylesheet,
parent_stylesheet_contents: &StylesheetContents,
index: usize,
nested: bool,
loader: Option<&StylesheetLoader>)
@ -139,7 +140,13 @@ impl CssRulesHelpers for Arc<Locked<CssRules>> {
// Step 3, 4
// XXXManishearth should we also store the namespace map?
let (new_rule, new_state) =
CssRule::parse(&rule, parent_stylesheet, state, loader)?;
CssRule::parse(
&rule,
parent_stylesheet_contents,
lock,
state,
loader
)?;
{
let mut write_guard = lock.write();

View file

@ -11,7 +11,6 @@ use cssparser::{CompactCowStr, SourceLocation};
use error_reporting::ContextualParseError;
use font_face::parse_font_face_block;
use media_queries::{parse_media_query_list, MediaList};
use parking_lot::RwLock;
use parser::{Parse, ParserContext, log_css_error};
use properties::parse_property_declaration_list;
use selector_parser::{SelectorImpl, SelectorParser};
@ -19,17 +18,15 @@ use selectors::SelectorList;
use selectors::parser::SelectorParseError;
use shared_lock::{Locked, SharedRwLock};
use std::borrow::Cow;
use std::sync::atomic::AtomicBool;
use str::starts_with_ignore_ascii_case;
use style_traits::{StyleParseError, ParseError};
use stylearc::Arc;
use stylesheets::{CssRule, CssRules, CssRuleType, Origin, StylesheetLoader};
use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
use stylesheets::{DocumentRule, KeyframesRule, MediaRule, NamespaceRule, PageRule};
use stylesheets::{StyleRule, SupportsRule, ViewportRule};
use stylesheets::document_rule::DocumentCondition;
use stylesheets::keyframes_rule::parse_keyframe_list;
use stylesheets::loader::NoOpLoader;
use stylesheets::stylesheet::{Namespaces, Stylesheet};
use stylesheets::stylesheet::Namespaces;
use stylesheets::supports_rule::SupportsCondition;
use stylesheets::viewport_rule;
use values::CustomIdent;
@ -165,35 +162,18 @@ impl<'a, 'i> AtRuleParser<'i> for TopLevelRuleParser<'a> {
let media = parse_media_query_list(&self.context, input);
let media = Arc::new(self.shared_lock.wrap(media));
let noop_loader = NoOpLoader;
let loader = if !specified_url.is_invalid() {
self.loader.expect("Expected a stylesheet loader for @import")
} else {
&noop_loader
};
let loader =
self.loader.expect("Expected a stylesheet loader for @import");
let mut specified_url = Some(specified_url);
let arc = loader.request_stylesheet(media, &mut |media| {
ImportRule {
url: specified_url.take().unwrap(),
stylesheet: Arc::new(Stylesheet {
rules: CssRules::new(Vec::new(), self.shared_lock),
media: media,
shared_lock: self.shared_lock.clone(),
origin: self.context.stylesheet_origin,
url_data: RwLock::new(self.context.url_data.clone()),
namespaces: RwLock::new(Namespaces::default()),
dirty_on_viewport_size_change: AtomicBool::new(false),
disabled: AtomicBool::new(false),
quirks_mode: self.context.quirks_mode,
}),
source_location: location,
}
}, &mut |import_rule| {
Arc::new(self.shared_lock.wrap(import_rule))
});
let import_rule = loader.request_stylesheet(
specified_url,
location,
&self.context,
&self.shared_lock,
media,
);
return Ok(AtRuleType::WithoutBlock(CssRule::Import(arc)))
return Ok(AtRuleType::WithoutBlock(CssRule::Import(import_rule)))
},
"namespace" => {
if self.state > State::Namespaces {

View file

@ -10,6 +10,7 @@ use shared_lock::SharedRwLockReadGuard;
use smallvec::SmallVec;
use std::slice;
use stylesheets::{CssRule, CssRules, DocumentRule, ImportRule, MediaRule, SupportsRule};
use stylesheets::StylesheetInDocument;
/// An iterator over a list of rules.
pub struct RulesIterator<'a, 'b, C>
@ -96,7 +97,9 @@ impl<'a, 'b, C> Iterator for RulesIterator<'a, 'b, C>
import_rule) {
continue;
}
import_rule.stylesheet.rules.read_with(self.guard).0.iter()
import_rule
.stylesheet.contents(self.guard).rules
.read_with(self.guard).0.iter()
}
CssRule::Document(ref doc_rule) => {
let doc_rule = doc_rule.read_with(self.guard);
@ -182,11 +185,11 @@ impl NestedRuleIterationCondition for EffectiveRules {
fn process_import(
guard: &SharedRwLockReadGuard,
device: &Device,
quirks_mode: QuirksMode,
_quirks_mode: QuirksMode,
rule: &ImportRule)
-> bool
{
rule.stylesheet.media.read_with(guard).evaluate(device, quirks_mode)
rule.stylesheet.is_effective_for_device(device, guard)
}
fn process_media(

View file

@ -8,7 +8,7 @@ use cssparser::SourceLocation;
use properties::PropertyDeclarationBlock;
use selector_parser::SelectorImpl;
use selectors::SelectorList;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::ToCss;
use stylearc::Arc;
@ -31,6 +31,7 @@ impl DeepCloneWithLock for StyleRule {
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
_params: &DeepCloneParams,
) -> StyleRule {
StyleRule {
selectors: self.selectors.clone(),

View file

@ -10,7 +10,7 @@ use fnv::FnvHashMap;
use media_queries::{MediaList, Device};
use parking_lot::RwLock;
use parser::{ParserContext, log_css_error};
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
use std::mem;
use std::sync::atomic::{AtomicBool, Ordering};
use style_traits::PARSING_MODE_DEFAULT;
@ -42,28 +42,232 @@ pub struct Namespaces {
pub prefixes: FnvHashMap<Prefix, (Namespace, NamespaceId)>,
}
/// The structure servo uses to represent a stylesheet.
/// The contents of a given stylesheet. This effectively maps to a
/// StyleSheetInner in Gecko.
#[derive(Debug)]
pub struct Stylesheet {
pub struct StylesheetContents {
/// List of rules in the order they were found (important for
/// cascading order)
pub rules: Arc<Locked<CssRules>>,
/// List of media associated with the Stylesheet.
pub media: Arc<Locked<MediaList>>,
/// The origin of this stylesheet.
pub origin: Origin,
/// The url data this stylesheet should use.
pub url_data: RwLock<UrlExtraData>,
/// The lock used for objects inside this stylesheet
pub shared_lock: SharedRwLock,
/// The namespaces that apply to this stylesheet.
pub namespaces: RwLock<Namespaces>,
/// Whether this stylesheet would be dirty when the viewport size changes.
pub dirty_on_viewport_size_change: AtomicBool,
/// Whether this stylesheet should be disabled.
pub disabled: AtomicBool,
/// The quirks mode of this stylesheet.
pub quirks_mode: QuirksMode,
/// Whether this stylesheet would be dirty when the viewport size changes.
pub dirty_on_viewport_size_change: AtomicBool,
}
impl StylesheetContents {
/// Parse a given CSS string, with a given url-data, origin, and
/// quirks mode.
pub fn from_str(
css: &str,
url_data: UrlExtraData,
origin: Origin,
shared_lock: &SharedRwLock,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: &ParseErrorReporter,
quirks_mode: QuirksMode,
line_number_offset: u64
) -> Self {
let namespaces = RwLock::new(Namespaces::default());
let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules(
css,
&url_data,
origin,
&mut *namespaces.write(),
&shared_lock,
stylesheet_loader,
error_reporter,
quirks_mode,
line_number_offset,
);
Self {
rules: CssRules::new(rules, &shared_lock),
origin: origin,
url_data: RwLock::new(url_data),
namespaces: namespaces,
dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change),
quirks_mode: quirks_mode,
}
}
/// Return an iterator using the condition `C`.
#[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)
)
}
}
impl DeepCloneWithLock for StylesheetContents {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
// Make a deep clone of the rules, using the new lock.
let rules =
self.rules.read_with(guard)
.deep_clone_with_lock(lock, guard, params);
let dirty_on_viewport_size_change =
AtomicBool::new(self.dirty_on_viewport_size_change.load(Ordering::Relaxed));
Self {
rules: Arc::new(lock.wrap(rules)),
dirty_on_viewport_size_change,
quirks_mode: self.quirks_mode,
origin: self.origin,
url_data: RwLock::new((*self.url_data.read()).clone()),
namespaces: RwLock::new((*self.namespaces.read()).clone()),
}
}
}
impl MallocSizeOfWithGuard for StylesheetContents {
fn malloc_size_of_children(
&self,
guard: &SharedRwLockReadGuard,
malloc_size_of: MallocSizeOfFn
) -> usize {
// Measurement of other fields may be added later.
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
}
}
/// The structure servo uses to represent a stylesheet.
#[derive(Debug)]
pub struct Stylesheet {
/// The contents of this stylesheet.
pub contents: StylesheetContents,
/// The lock used for objects inside this stylesheet
pub shared_lock: SharedRwLock,
/// List of media associated with the Stylesheet.
pub media: Arc<Locked<MediaList>>,
/// Whether this stylesheet should be disabled.
pub disabled: AtomicBool,
}
macro_rules! rule_filter {
($( $method: ident($variant:ident => $rule_type: ident), )+) => {
$(
#[allow(missing_docs)]
fn $method<F>(&self, device: &Device, guard: &SharedRwLockReadGuard, mut f: F)
where F: FnMut(&::stylesheets::$rule_type),
{
use stylesheets::CssRule;
for rule in self.effective_rules(device, guard) {
if let CssRule::$variant(ref lock) = *rule {
let rule = lock.read_with(guard);
f(&rule)
}
}
}
)+
}
}
/// 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
}
/// Get the stylesheet quirks mode.
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
self.contents(guard).quirks_mode
}
/// 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;
/// Return an iterator using the condition `C`.
#[inline]
fn iter_rules<'a, 'b, C>(
&'a self,
device: &'a Device,
guard: &'a SharedRwLockReadGuard<'b>
) -> RulesIterator<'a, 'b, C>
where
C: NestedRuleIterationCondition,
{
self.contents(guard).iter_rules(device, guard)
}
/// Return an iterator over the effective rules within the style-sheet, as
/// according to the supplied `Device`.
#[inline]
fn effective_rules<'a, 'b>(
&'a self,
device: &'a Device,
guard: &'a SharedRwLockReadGuard<'b>
) -> EffectiveRulesIterator<'a, 'b> {
self.iter_rules::<'a, 'b, EffectiveRules>(device, guard)
}
rule_filter! {
effective_style_rules(Style => StyleRule),
effective_media_rules(Media => MediaRule),
effective_font_face_rules(FontFace => FontFaceRule),
effective_counter_style_rules(CounterStyle => CounterStyleRule),
effective_viewport_rules(Viewport => ViewportRule),
effective_keyframes_rules(Keyframes => KeyframesRule),
effective_supports_rules(Supports => SupportsRule),
effective_page_rules(Page => PageRule),
effective_document_rules(Document => DocumentRule),
}
}
impl StylesheetInDocument for Stylesheet {
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
&self.contents
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
Some(self.media.read_with(guard))
}
fn enabled(&self) -> bool {
!self.disabled()
}
}
impl Stylesheet {
@ -79,23 +283,26 @@ impl Stylesheet {
Stylesheet::parse_rules(
css,
&url_data,
existing.origin,
existing.contents.origin,
&mut *namespaces.write(),
&existing.shared_lock,
stylesheet_loader,
error_reporter,
existing.quirks_mode,
existing.contents.quirks_mode,
line_number_offset
);
*existing.url_data.write() = url_data;
mem::swap(&mut *existing.namespaces.write(), &mut *namespaces.write());
existing.dirty_on_viewport_size_change
*existing.contents.url_data.write() = url_data;
mem::swap(
&mut *existing.contents.namespaces.write(),
&mut *namespaces.write()
);
existing.contents.dirty_on_viewport_size_change
.store(dirty_on_viewport_size_change, Ordering::Release);
// Acquire the lock *after* parsing, to minimize the exclusive section.
let mut guard = existing.shared_lock.write();
*existing.rules.write_with(&mut guard) = CssRules(rules);
*existing.contents.rules.write_with(&mut guard) = CssRules(rules);
}
fn parse_rules(
@ -169,35 +376,28 @@ impl Stylesheet {
quirks_mode: QuirksMode,
line_number_offset: u64)
-> Stylesheet {
let namespaces = RwLock::new(Namespaces::default());
let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules(
let contents = StylesheetContents::from_str(
css,
&url_data,
url_data,
origin,
&mut *namespaces.write(),
&shared_lock,
stylesheet_loader,
error_reporter,
quirks_mode,
line_number_offset,
line_number_offset
);
Stylesheet {
origin: origin,
url_data: RwLock::new(url_data),
namespaces: namespaces,
rules: CssRules::new(rules, &shared_lock),
media: media,
shared_lock: shared_lock,
dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change),
contents,
shared_lock,
media,
disabled: AtomicBool::new(false),
quirks_mode: quirks_mode,
}
}
/// Whether this stylesheet can be dirty on viewport size change.
pub fn dirty_on_viewport_size_change(&self) -> bool {
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)
self.contents.dirty_on_viewport_size_change.load(Ordering::SeqCst)
}
/// When CSSOM inserts a rule or declaration into this stylesheet, it needs to call this method
@ -212,43 +412,10 @@ impl Stylesheet {
/// Instead, we conservatively assume there might be some.
/// Restyling will some some more work than necessary, but give correct results.
pub fn inserted_has_viewport_percentages(&self, has_viewport_percentages: bool) {
self.dirty_on_viewport_size_change.fetch_or(has_viewport_percentages, Ordering::SeqCst);
}
/// Returns whether the style-sheet applies for the current device depending
/// on the associated MediaList.
///
/// Always true if no associated MediaList exists.
pub fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
self.media.read_with(guard).evaluate(device, self.quirks_mode)
}
/// Return an iterator over the effective rules within the style-sheet, as
/// according to the supplied `Device`.
#[inline]
pub fn effective_rules<'a, 'b>(
&'a self,
device: &'a Device,
guard: &'a SharedRwLockReadGuard<'b>)
-> EffectiveRulesIterator<'a, 'b>
{
self.iter_rules::<'a, 'b, EffectiveRules>(device, guard)
}
/// Return an iterator using the condition `C`.
#[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))
self.contents.dirty_on_viewport_size_change.fetch_or(
has_viewport_percentages,
Ordering::SeqCst
);
}
/// Returns whether the stylesheet has been explicitly disabled through the
@ -269,76 +436,28 @@ impl Stylesheet {
}
}
#[cfg(feature = "servo")]
impl Clone for Stylesheet {
fn clone(&self) -> Stylesheet {
fn clone(&self) -> Self {
// Create a new lock for our clone.
let lock = self.shared_lock.clone();
let guard = self.shared_lock.read();
// Make a deep clone of the rules, using the new lock.
let rules = self.rules.read_with(&guard);
let cloned_rules = rules.deep_clone_with_lock(&lock, &guard);
// Make a deep clone of the media, using the new lock.
let media = self.media.read_with(&guard);
let cloned_media = media.clone();
let media = self.media.read_with(&guard).clone();
let media = Arc::new(lock.wrap(media));
let contents = self.contents.deep_clone_with_lock(
&lock,
&guard,
&DeepCloneParams
);
Stylesheet {
rules: Arc::new(lock.wrap(cloned_rules)),
media: Arc::new(lock.wrap(cloned_media)),
origin: self.origin,
url_data: RwLock::new((*self.url_data.read()).clone()),
contents,
media: media,
shared_lock: lock,
namespaces: RwLock::new((*self.namespaces.read()).clone()),
dirty_on_viewport_size_change: AtomicBool::new(
self.dirty_on_viewport_size_change.load(Ordering::SeqCst)),
disabled: AtomicBool::new(self.disabled.load(Ordering::SeqCst)),
quirks_mode: self.quirks_mode,
}
}
}
impl MallocSizeOfWithGuard for Stylesheet {
fn malloc_size_of_children(
&self,
guard: &SharedRwLockReadGuard,
malloc_size_of: MallocSizeOfFn
) -> usize {
// Measurement of other fields may be added later.
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
}
}
macro_rules! rule_filter {
($( $method: ident($variant:ident => $rule_type: ident), )+) => {
impl Stylesheet {
$(
#[allow(missing_docs)]
pub fn $method<F>(&self, device: &Device, guard: &SharedRwLockReadGuard, mut f: F)
where F: FnMut(&::stylesheets::$rule_type),
{
use stylesheets::CssRule;
for rule in self.effective_rules(device, guard) {
if let CssRule::$variant(ref lock) = *rule {
let rule = lock.read_with(guard);
f(&rule)
}
}
}
)+
}
}
}
rule_filter! {
effective_style_rules(Style => StyleRule),
effective_media_rules(Media => MediaRule),
effective_font_face_rules(FontFace => FontFaceRule),
effective_counter_style_rules(CounterStyle => CounterStyleRule),
effective_viewport_rules(Viewport => ViewportRule),
effective_keyframes_rules(Keyframes => KeyframesRule),
effective_supports_rules(Supports => SupportsRule),
effective_page_rules(Page => PageRule),
effective_document_rules(Document => DocumentRule),
}

View file

@ -9,7 +9,7 @@ use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
use parser::ParserContext;
use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
use selectors::parser::SelectorParseError;
use shared_lock::{DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use std::fmt;
use style_traits::{ToCss, ParseError, StyleParseError};
use stylearc::Arc;
@ -48,12 +48,13 @@ impl DeepCloneWithLock for SupportsRule {
fn deep_clone_with_lock(
&self,
lock: &SharedRwLock,
guard: &SharedRwLockReadGuard
guard: &SharedRwLockReadGuard,
params: &DeepCloneParams,
) -> Self {
let rules = self.rules.read_with(guard);
SupportsRule {
condition: self.condition.clone(),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard))),
rules: Arc::new(lock.wrap(rules.deep_clone_with_lock(lock, guard, params))),
enabled: self.enabled,
source_location: self.source_location.clone(),
}

View file

@ -26,8 +26,7 @@ use std::iter::Enumerate;
use std::str::Chars;
use style_traits::{PinchZoomFactor, ToCss, ParseError, StyleParseError};
use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom};
use stylearc::Arc;
use stylesheets::{Stylesheet, Origin};
use stylesheets::{StylesheetInDocument, Origin};
use values::computed::{Context, ToComputedValue};
use values::specified::{NoCalcLength, LengthOrPercentageOrAuto, ViewportPercentageLength};
@ -563,11 +562,14 @@ impl Cascade {
}
}
pub fn from_stylesheets<'a, I>(stylesheets: I,
guard: &SharedRwLockReadGuard,
device: &Device)
-> Self
where I: Iterator<Item = &'a Arc<Stylesheet>>,
pub fn from_stylesheets<'a, I, S>(
stylesheets: I,
guard: &SharedRwLockReadGuard,
device: &Device
) -> Self
where
I: Iterator<Item = &'a S>,
S: StylesheetInDocument + 'static,
{
let mut cascade = Self::new();
for stylesheet in stylesheets {

View file

@ -15,7 +15,7 @@ use font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
use gecko_bindings::structs::{nsIAtom, StyleRuleInclusion};
use invalidation::element::invalidation_map::InvalidationMap;
use invalidation::media_queries::EffectiveMediaQueryResults;
use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey};
use matching::CascadeVisitedMode;
use media_queries::Device;
use properties::{self, CascadeFlags, ComputedValues};
@ -43,7 +43,7 @@ use stylearc::Arc;
#[cfg(feature = "gecko")]
use stylesheets::{CounterStyleRule, FontFaceRule};
use stylesheets::{CssRule, StyleRule};
use stylesheets::{Stylesheet, Origin, UserAgentStylesheets};
use stylesheets::{StylesheetInDocument, Origin, UserAgentStylesheets};
use stylesheets::keyframes_rule::KeyframesAnimation;
use stylesheets::viewport_rule::{self, MaybeNew, ViewportRule};
use thread_state;
@ -342,14 +342,18 @@ impl Stylist {
/// This method resets all the style data each time the stylesheets change
/// (which is indicated by the `stylesheets_changed` parameter), or the
/// device is dirty, which means we need to re-evaluate media queries.
pub fn rebuild<'a, 'b, I>(&mut self,
doc_stylesheets: I,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool,
author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>) -> bool
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
pub fn rebuild<'a, 'b, I, S>(
&mut self,
doc_stylesheets: I,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool,
author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>
) -> bool
where
I: Iterator<Item = &'b S> + Clone,
S: StylesheetInDocument + ToMediaListKey + 'static,
{
debug_assert!(!self.is_cleared || self.is_device_dirty);
@ -398,7 +402,7 @@ impl Stylist {
if let Some(ua_stylesheets) = ua_stylesheets {
for stylesheet in &ua_stylesheets.user_or_user_agent_stylesheets {
self.add_stylesheet(&stylesheet, guards.ua_or_user, extra_data);
self.add_stylesheet(stylesheet, guards.ua_or_user, extra_data);
}
if self.quirks_mode != QuirksMode::NoQuirks {
@ -409,10 +413,10 @@ impl Stylist {
// Only use author stylesheets if author styles are enabled.
let sheets_to_add = doc_stylesheets.filter(|s| {
!author_style_disabled || s.origin != Origin::Author
!author_style_disabled || s.origin(guards.author) != Origin::Author
});
for ref stylesheet in sheets_to_add {
for stylesheet in sheets_to_add {
self.add_stylesheet(stylesheet, guards.author, extra_data);
}
@ -429,14 +433,18 @@ impl Stylist {
/// clear the stylist and then rebuild it. Chances are, you want to use
/// either clear() or rebuild(), with the latter done lazily, instead.
pub fn update<'a, 'b, I>(&mut self,
doc_stylesheets: I,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool,
author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>) -> bool
where I: Iterator<Item = &'b Arc<Stylesheet>> + Clone,
pub fn update<'a, 'b, I, S>(
&mut self,
doc_stylesheets: I,
guards: &StylesheetGuards,
ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool,
author_style_disabled: bool,
extra_data: &mut ExtraStyleData<'a>
) -> bool
where
I: Iterator<Item = &'b S> + Clone,
S: StylesheetInDocument + ToMediaListKey + 'static,
{
debug_assert!(!self.is_cleared || self.is_device_dirty);
@ -450,16 +458,23 @@ impl Stylist {
author_style_disabled, extra_data)
}
fn add_stylesheet<'a>(&mut self,
stylesheet: &Stylesheet,
guard: &SharedRwLockReadGuard,
_extra_data: &mut ExtraStyleData<'a>) {
if stylesheet.disabled() || !stylesheet.is_effective_for_device(&self.device, guard) {
fn add_stylesheet<'a, S>(
&mut self,
stylesheet: &S,
guard: &SharedRwLockReadGuard,
_extra_data: &mut ExtraStyleData<'a>
)
where
S: StylesheetInDocument + ToMediaListKey + 'static,
{
if !stylesheet.enabled() ||
!stylesheet.is_effective_for_device(&self.device, guard) {
return;
}
self.effective_media_query_results.saw_effective(stylesheet);
let origin = stylesheet.origin(guard);
for rule in stylesheet.effective_rules(&self.device, guard) {
match *rule {
CssRule::Style(ref locked) => {
@ -472,9 +487,9 @@ impl Stylist {
self.pseudos_map
.entry(pseudo.canonical())
.or_insert_with(PerPseudoElementSelectorMap::new)
.borrow_for_origin(&stylesheet.origin)
.borrow_for_origin(&origin)
} else {
self.element_map.borrow_for_origin(&stylesheet.origin)
self.element_map.borrow_for_origin(&origin)
};
map.insert(
@ -529,7 +544,7 @@ impl Stylist {
}
#[cfg(feature = "gecko")]
CssRule::FontFace(ref rule) => {
_extra_data.add_font_face(&rule, stylesheet.origin);
_extra_data.add_font_face(&rule, origin);
}
#[cfg(feature = "gecko")]
CssRule::CounterStyle(ref rule) => {
@ -909,9 +924,13 @@ impl Stylist {
pub fn set_device(&mut self,
mut device: Device,
guard: &SharedRwLockReadGuard,
stylesheets: &[Arc<Stylesheet>]) {
stylesheets: &[Arc<::stylesheets::Stylesheet>]) {
let cascaded_rule = ViewportRule {
declarations: viewport_rule::Cascade::from_stylesheets(stylesheets.iter(), guard, &device).finish(),
declarations: viewport_rule::Cascade::from_stylesheets(
stylesheets.iter().map(|s| &**s),
guard,
&device
).finish(),
};
self.viewport_constraints =
@ -923,7 +942,7 @@ impl Stylist {
self.device = device;
let features_changed = self.media_features_change_changed_style(
stylesheets.iter(),
stylesheets.iter().map(|s| &**s),
guard
);
self.is_device_dirty |= features_changed;
@ -931,12 +950,14 @@ impl Stylist {
/// Returns whether, given a media feature change, any previously-applicable
/// style has become non-applicable, or vice-versa.
pub fn media_features_change_changed_style<'a, I>(
pub fn media_features_change_changed_style<'a, I, S>(
&self,
stylesheets: I,
guard: &SharedRwLockReadGuard,
) -> bool
where I: Iterator<Item = &'a Arc<Stylesheet>>
where
I: Iterator<Item = &'a S>,
S: StylesheetInDocument + ToMediaListKey + 'static,
{
use invalidation::media_queries::PotentiallyEffectiveMediaRules;
@ -944,11 +965,10 @@ impl Stylist {
for stylesheet in stylesheets {
let effective_now =
stylesheet.media.read_with(guard)
.evaluate(&self.device, self.quirks_mode);
stylesheet.is_effective_for_device(&self.device, guard);
let effective_then =
self.effective_media_query_results.was_effective(&**stylesheet);
self.effective_media_query_results.was_effective(stylesheet);
if effective_now != effective_then {
debug!(" > Stylesheet changed -> {}, {}",
@ -982,9 +1002,9 @@ impl Stylist {
}
CssRule::Import(ref lock) => {
let import_rule = lock.read_with(guard);
let mq = import_rule.stylesheet.media.read_with(guard);
let effective_now =
mq.evaluate(&self.device, self.quirks_mode);
import_rule.stylesheet
.is_effective_for_device(&self.device, guard);
let effective_then =
self.effective_media_query_results.was_effective(import_rule);
if effective_now != effective_then {

View file

@ -18,7 +18,7 @@ use style::dom::{ShowSubtreeData, TElement, TNode};
use style::element_state::ElementState;
use style::error_reporting::RustLogReporter;
use style::font_metrics::{FontMetricsProvider, get_metrics_provider_for_product};
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
use style::gecko::data::{GeckoStyleSheet, PerDocumentStyleData, PerDocumentStyleDataImpl};
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_THREAD_POOL};
use style::gecko::restyle_damage::GeckoRestyleDamage;
use style::gecko::selector_parser::PseudoElement;
@ -32,13 +32,13 @@ use style::gecko_bindings::bindings::{RawServoDocumentRule, RawServoDocumentRule
use style::gecko_bindings::bindings::{RawServoImportRule, RawServoImportRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoKeyframe, RawServoKeyframeBorrowed, RawServoKeyframeStrong};
use style::gecko_bindings::bindings::{RawServoKeyframesRule, RawServoKeyframesRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoMediaList, RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedValuesBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoComputedValuesStrong};
use style::gecko_bindings::bindings::{RawServoSupportsRule, RawServoSupportsRuleBorrowed};
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
use style::gecko_bindings::bindings::{nsACString, nsAString, nsCSSPropertyIDSetBorrowedMut};
@ -59,14 +59,12 @@ use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueMapBorrowedMut;
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
use style::gecko_bindings::bindings::RawServoStyleRuleBorrowed;
use style::gecko_bindings::bindings::RawServoStyleSheet;
use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
use style::gecko_bindings::bindings::nsTimingFunctionBorrowed;
use style::gecko_bindings::bindings::nsTimingFunctionBorrowedMut;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation};
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
use style::gecko_bindings::structs::{CSSPseudoElementType, CompositeOperation, Loader};
use style::gecko_bindings::structs::{RawServoStyleRule, ServoStyleSheet};
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsCSSFontFaceRule, nsCSSCounterStyleRule};
@ -105,7 +103,8 @@ use style::style_adjuster::StyleAdjuster;
use style::stylearc::Arc;
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
use style::stylesheets::{ImportRule, KeyframesRule, MallocSizeOfWithGuard, MediaRule};
use style::stylesheets::{NamespaceRule, Origin, PageRule, Stylesheet, StyleRule, SupportsRule};
use style::stylesheets::{NamespaceRule, Origin, PageRule, StyleRule, SupportsRule};
use style::stylesheets::StylesheetContents;
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration;
@ -739,7 +738,7 @@ pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) {
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetStrong {
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetContentsStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
@ -747,24 +746,31 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
};
let shared_lock = global_style_data.shared_lock.clone();
Arc::new(Stylesheet::from_str(
"", unsafe { dummy_url_data() }.clone(), origin,
Arc::new(shared_lock.wrap(MediaList::empty())),
shared_lock, None, &RustLogReporter, QuirksMode::NoQuirks, 0u64)
let shared_lock = &global_style_data.shared_lock;
Arc::new(
StylesheetContents::from_str(
"",
unsafe { dummy_url_data() }.clone(),
origin,
shared_lock,
/* loader = */ None,
&RustLogReporter,
QuirksMode::NoQuirks,
0
)
).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
stylesheet: *mut ServoStyleSheet,
data: *const nsACString,
mode: SheetParsingMode,
media_list: *const RawServoMediaList,
extra_data: *mut URLExtraData,
line_number_offset: u32,
quirks_mode: nsCompatibility)
-> RawServoStyleSheetStrong {
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
loader: *mut Loader,
stylesheet: *mut ServoStyleSheet,
data: *const nsACString,
mode: SheetParsingMode,
extra_data: *mut URLExtraData,
line_number_offset: u32,
quirks_mode: nsCompatibility
) -> RawServoStyleSheetContentsStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
@ -788,63 +794,28 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
Some(ref s) => Some(s),
};
let shared_lock = global_style_data.shared_lock.clone();
let media = if media_list.is_null() {
Arc::new(shared_lock.wrap(MediaList::empty()))
} else {
Locked::<MediaList>::as_arc(unsafe { &&*media_list }).clone()
};
Arc::new(Stylesheet::from_str(
input, url_data.clone(), origin, media,
shared_lock, loader, &RustLogReporter,
Arc::new(StylesheetContents::from_str(
input, url_data.clone(), origin,
&global_style_data.shared_lock, loader, &RustLogReporter,
quirks_mode.into(), line_number_offset as u64)
).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_ClearAndUpdate(stylesheet: RawServoStyleSheetBorrowed,
loader: *mut Loader,
gecko_stylesheet: *mut ServoStyleSheet,
data: *const nsACString,
extra_data: *mut URLExtraData,
line_number_offset: u32,
reusable_sheets: *mut LoaderReusableStyleSheets)
{
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
let url_data = unsafe { RefPtr::from_ptr_ref(&extra_data) };
let loader = if loader.is_null() {
None
} else {
Some(StylesheetLoader::new(loader, gecko_stylesheet, reusable_sheets))
};
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
let loader: Option<&StyleStylesheetLoader> = match loader {
None => None,
Some(ref s) => Some(s),
};
let sheet = Stylesheet::as_arc(&stylesheet);
Stylesheet::update_from_str(&sheet, input, url_data.clone(), loader,
&RustLogReporter, line_number_offset as u64);
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
unique_id: u64) {
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
raw_data: RawServoStyleSetBorrowed,
sheet: *const ServoStyleSheet,
) {
let global_style_data = &*GLOBAL_STYLE_DATA;
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let mut data = &mut *data;
let sheet = HasArcFFI::as_arc(&raw_sheet);
let guard = global_style_data.shared_lock.read();
data.stylesheets.append_stylesheet(
&data.stylist,
sheet,
unique_id,
&guard);
unsafe { GeckoStyleSheet::new(sheet) },
&guard
);
data.clear_stylist();
}
@ -875,65 +846,55 @@ pub extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
unique_id: u64) {
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
raw_data: RawServoStyleSetBorrowed,
sheet: *const ServoStyleSheet,
) {
let global_style_data = &*GLOBAL_STYLE_DATA;
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let mut data = &mut *data;
let sheet = HasArcFFI::as_arc(&raw_sheet);
let guard = global_style_data.shared_lock.read();
data.stylesheets.prepend_stylesheet(
&data.stylist,
sheet,
unique_id,
&guard);
unsafe { GeckoStyleSheet::new(sheet) },
&guard,
);
data.clear_stylist();
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
unique_id: u64,
before_unique_id: u64) {
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(
raw_data: RawServoStyleSetBorrowed,
sheet: *const ServoStyleSheet,
before_sheet: *const ServoStyleSheet
) {
let global_style_data = &*GLOBAL_STYLE_DATA;
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let mut data = &mut *data;
let sheet = HasArcFFI::as_arc(&raw_sheet);
let guard = global_style_data.shared_lock.read();
data.stylesheets.insert_stylesheet_before(
&data.stylist,
sheet,
unique_id,
before_unique_id,
unsafe { GeckoStyleSheet::new(sheet) },
unsafe { GeckoStyleSheet::new(before_sheet) },
&guard);
data.clear_stylist();
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_UpdateStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
unique_id: u64) {
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(
raw_data: RawServoStyleSetBorrowed,
sheet: *const ServoStyleSheet
) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let sheet = HasArcFFI::as_arc(&raw_sheet);
data.stylesheets.update_stylesheet(
sheet,
unique_id);
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowed,
unique_id: u64) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
data.stylesheets.remove_stylesheet(unique_id);
data.stylesheets.remove_stylesheet(unsafe { GeckoStyleSheet::new(sheet) });
data.clear_stylist();
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_FlushStyleSheets(
raw_data: RawServoStyleSetBorrowed,
doc_element: RawGeckoElementBorrowedOrNull)
{
doc_element: RawGeckoElementBorrowedOrNull,
) {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
@ -944,8 +905,8 @@ pub extern "C" fn Servo_StyleSet_FlushStyleSheets(
#[no_mangle]
pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(
raw_data: RawServoStyleSetBorrowed,
author_style_disabled: bool)
{
author_style_disabled: bool,
) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
data.stylesheets.force_dirty();
data.stylesheets.set_author_style_disabled(author_style_disabled);
@ -953,30 +914,50 @@ pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
pub extern "C" fn Servo_StyleSheet_HasRules(
raw_contents: RawServoStyleSheetContentsBorrowed
) -> bool {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
!Stylesheet::as_arc(&raw_sheet).rules.read_with(&guard).0.is_empty()
!StylesheetContents::as_arc(&raw_contents)
.rules.read_with(&guard).0.is_empty()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed) -> ServoCssRulesStrong {
Stylesheet::as_arc(&sheet).rules.clone().into_strong()
pub extern "C" fn Servo_StyleSheet_GetRules(
sheet: RawServoStyleSheetContentsBorrowed
) -> ServoCssRulesStrong {
StylesheetContents::as_arc(&sheet).rules.clone().into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_Clone(raw_sheet: RawServoStyleSheetBorrowed) -> RawServoStyleSheetStrong {
let sheet: &Arc<Stylesheet> = HasArcFFI::as_arc(&raw_sheet);
Arc::new(sheet.as_ref().clone()).into_strong()
pub extern "C" fn Servo_StyleSheet_Clone(
raw_sheet: RawServoStyleSheetContentsBorrowed,
reference_sheet: *const ServoStyleSheet,
) -> RawServoStyleSheetContentsStrong {
use style::shared_lock::{DeepCloneParams, DeepCloneWithLock};
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let contents = StylesheetContents::as_arc(&raw_sheet);
let params = DeepCloneParams { reference_sheet };
Arc::new(contents.deep_clone_with_lock(
&global_style_data.shared_lock,
&guard,
&params,
)).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_SizeOfIncludingThis(malloc_size_of: MallocSizeOf,
sheet: RawServoStyleSheetBorrowed) -> usize {
pub extern "C" fn Servo_StyleSheet_SizeOfIncludingThis(
malloc_size_of: MallocSizeOf,
sheet: RawServoStyleSheetContentsBorrowed
) -> usize {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let malloc_size_of = malloc_size_of.unwrap();
Stylesheet::as_arc(&sheet).malloc_size_of_children(&guard, malloc_size_of)
StylesheetContents::as_arc(&sheet)
.malloc_size_of_children(&guard, malloc_size_of)
}
fn read_locked_arc<T, R, F>(raw: &<Locked<T> as HasFFI>::FFIType, func: F) -> R
@ -1008,15 +989,16 @@ pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
sheet: RawServoStyleSheetBorrowed,
rule: *const nsACString,
index: u32,
nested: bool,
loader: *mut Loader,
gecko_stylesheet: *mut ServoStyleSheet,
rule_type: *mut u16) -> nsresult {
let sheet = Stylesheet::as_arc(&sheet);
pub extern "C" fn Servo_CssRules_InsertRule(
rules: ServoCssRulesBorrowed,
contents: RawServoStyleSheetContentsBorrowed,
rule: *const nsACString,
index: u32,
nested: bool,
loader: *mut Loader,
gecko_stylesheet: *mut ServoStyleSheet,
rule_type: *mut u16,
) -> nsresult {
let loader = if loader.is_null() {
None
} else {
@ -1026,12 +1008,17 @@ pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() };
let global_style_data = &*GLOBAL_STYLE_DATA;
match Locked::<CssRules>::as_arc(&rules).insert_rule(&global_style_data.shared_lock,
rule,
sheet,
index as usize,
nested,
loader) {
let contents = StylesheetContents::as_arc(&contents);
let result = Locked::<CssRules>::as_arc(&rules).insert_rule(
&global_style_data.shared_lock,
rule,
contents,
index as usize,
nested,
loader
);
match result {
Ok(new_rule) => {
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16;
nsresult::NS_OK
@ -1041,7 +1028,10 @@ pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_DeleteRule(rules: ServoCssRulesBorrowed, index: u32) -> nsresult {
pub extern "C" fn Servo_CssRules_DeleteRule(
rules: ServoCssRulesBorrowed,
index: u32
) -> nsresult {
write_locked_arc(rules, |rules: &mut CssRules| {
match rules.remove_rule(index as usize) {
Ok(_) => nsresult::NS_OK,
@ -1085,7 +1075,13 @@ macro_rules! impl_basic_rule_funcs {
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let rules = Locked::<CssRules>::as_arc(&rules).read_with(&guard);
match rules.0[index as usize] {
let index = index as usize;
if index >= rules.0.len() {
return Strong::null();
}
match rules.0[index] {
CssRule::$name(ref rule) => {
let location = rule.read_with(&guard).source_location;
*unsafe { line.as_mut().unwrap() } = location.line as u32;
@ -1093,8 +1089,7 @@ macro_rules! impl_basic_rule_funcs {
rule.clone().into_strong()
},
_ => {
unreachable!(concat!(stringify!($getter), "should only be called ",
"on a ", stringify!($name), " rule"));
Strong::null()
}
}
}
@ -1244,9 +1239,11 @@ pub extern "C" fn Servo_StyleRule_GetSelectorCount(rule: RawServoStyleRuleBorrow
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSpecificityAtIndex(rule: RawServoStyleRuleBorrowed,
index: u32,
specificity: *mut u64) {
pub extern "C" fn Servo_StyleRule_GetSpecificityAtIndex(
rule: RawServoStyleRuleBorrowed,
index: u32,
specificity: *mut u64
) {
read_locked_arc(rule, |rule: &StyleRule| {
let mut specificity = unsafe { specificity.as_mut().unwrap() };
let index = index as usize;
@ -1266,14 +1263,19 @@ pub extern "C" fn Servo_ImportRule_GetHref(rule: RawServoImportRuleBorrowed, res
}
#[no_mangle]
pub extern "C" fn Servo_ImportRule_GetSheet(rule: RawServoImportRuleBorrowed) -> *const RawServoStyleSheet {
pub extern "C" fn Servo_ImportRule_GetSheet(
rule: RawServoImportRuleBorrowed
) -> *const ServoStyleSheet {
read_locked_arc(rule, |rule: &ImportRule| {
rule.stylesheet.as_borrowed_opt().unwrap() as *const _
rule.stylesheet.0.raw() as *const ServoStyleSheet
})
}
#[no_mangle]
pub extern "C" fn Servo_Keyframe_GetKeyText(keyframe: RawServoKeyframeBorrowed, result: *mut nsAString) {
pub extern "C" fn Servo_Keyframe_GetKeyText(
keyframe: RawServoKeyframeBorrowed,
result: *mut nsAString
) {
read_locked_arc(keyframe, |keyframe: &Keyframe| {
keyframe.selector.to_css(unsafe { result.as_mut().unwrap() }).unwrap()
})
@ -1344,18 +1346,22 @@ pub extern "C" fn Servo_KeyframesRule_FindRule(rule: RawServoKeyframesRuleBorrow
}
#[no_mangle]
pub extern "C" fn Servo_KeyframesRule_AppendRule(rule: RawServoKeyframesRuleBorrowed,
sheet: RawServoStyleSheetBorrowed,
css: *const nsACString) -> bool {
pub extern "C" fn Servo_KeyframesRule_AppendRule(
rule: RawServoKeyframesRuleBorrowed,
contents: RawServoStyleSheetContentsBorrowed,
css: *const nsACString
) -> bool {
let css = unsafe { css.as_ref().unwrap().as_str_unchecked() };
let sheet = Stylesheet::as_arc(&sheet);
if let Ok(keyframe) = Keyframe::parse(css, sheet) {
write_locked_arc(rule, |rule: &mut KeyframesRule| {
rule.keyframes.push(keyframe);
});
true
} else {
false
let contents = StylesheetContents::as_arc(&contents);
let global_style_data = &*GLOBAL_STYLE_DATA;
match Keyframe::parse(css, &contents, &global_style_data.shared_lock) {
Ok(keyframe) => {
write_locked_arc(rule, |rule: &mut KeyframesRule| {
rule.keyframes.push(keyframe);
});
true
}
Err(..) => false,
}
}
@ -1607,10 +1613,10 @@ fn get_pseudo_style(
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_Inherit(
raw_data: RawServoStyleSetBorrowed,
parent_style: ServoComputedValuesBorrowedOrNull,
target: structs::InheritTarget)
-> ServoComputedValuesStrong {
raw_data: RawServoStyleSetBorrowed,
parent_style: ServoComputedValuesBorrowedOrNull,
target: structs::InheritTarget
) -> ServoComputedValuesStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let maybe_arc = ComputedValues::arc_from_borrowed(&parent_style);
@ -3149,11 +3155,11 @@ pub extern "C" fn Servo_StyleSet_GetCounterStyleRule(raw_data: RawServoStyleSetB
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(raw_data: RawServoStyleSetBorrowed,
parent_style_or_null: ServoComputedValuesBorrowedOrNull,
declarations: RawServoDeclarationBlockBorrowed)
-> ServoComputedValuesStrong
{
pub extern "C" fn Servo_StyleSet_ResolveForDeclarations(
raw_data: RawServoStyleSetBorrowed,
parent_style_or_null: ServoComputedValuesBorrowedOrNull,
declarations: RawServoDeclarationBlockBorrowed
) -> ServoComputedValuesStrong {
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();

View file

@ -2,13 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use cssparser::SourceLocation;
use style::gecko::data::GeckoStyleSheet;
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, LoaderReusableStyleSheets};
use style::gecko_bindings::sugar::ownership::{HasArcFFI, FFIArcHelpers};
use style::gecko_bindings::sugar::ownership::FFIArcHelpers;
use style::media_queries::MediaList;
use style::shared_lock::Locked;
use style::parser::ParserContext;
use style::shared_lock::{Locked, SharedRwLock};
use style::stylearc::Arc;
use style::stylesheets::{ImportRule, Stylesheet, StylesheetLoader as StyleStylesheetLoader};
use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader};
use style::stylesheets::import_rule::ImportSheet;
use style::values::specified::url::SpecifiedUrl;
pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet, *mut LoaderReusableStyleSheets);
@ -23,29 +28,34 @@ impl StylesheetLoader {
impl StyleStylesheetLoader for StylesheetLoader {
fn request_stylesheet(
&self,
url: SpecifiedUrl,
source_location: SourceLocation,
_context: &ParserContext,
lock: &SharedRwLock,
media: Arc<Locked<MediaList>>,
make_import: &mut FnMut(Arc<Locked<MediaList>>) -> ImportRule,
make_arc: &mut FnMut(ImportRule) -> Arc<Locked<ImportRule>>,
) -> Arc<Locked<ImportRule>> {
let import = make_import(media.clone());
// After we get this raw pointer ImportRule will be moved into a lock and Arc
// and so the Arc<Url> pointer inside will also move,
// but the Url it points to or the allocating backing the String inside that Url wont,
// so this raw pointer will still be valid.
let (spec_bytes, spec_len): (*const u8, usize) = import.url.as_slice_components();
let base_url_data = import.url.extra_data.get();
unsafe {
let child_sheet = unsafe {
let (spec_bytes, spec_len) = url.as_slice_components();
let base_url_data = url.extra_data.get();
Gecko_LoadStyleSheet(self.0,
self.1,
self.2,
Stylesheet::arc_as_borrowed(&import.stylesheet),
base_url_data,
spec_bytes,
spec_len as u32,
media.into_strong())
}
make_arc(import)
};
debug_assert!(!child_sheet.is_null(),
"Import rules should always have a strong sheet");
let stylesheet = unsafe {
ImportSheet(GeckoStyleSheet::from_addrefed(child_sheet))
};
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
}
}

View file

@ -13,7 +13,7 @@ use style::media_queries::*;
use style::servo::media_queries::*;
use style::shared_lock::SharedRwLock;
use style::stylearc::Arc;
use style::stylesheets::{AllRules, Stylesheet, Origin, CssRule};
use style::stylesheets::{AllRules, Stylesheet, StylesheetInDocument, Origin, CssRule};
use style::values::specified;
use style_traits::ToCss;

View file

@ -62,7 +62,7 @@ fn parse_rules(css: &str) -> Vec<(StyleSource, CascadeLevel)> {
QuirksMode::NoQuirks,
0u64);
let guard = s.shared_lock.read();
let rules = s.rules.read_with(&guard);
let rules = s.contents.rules.read_with(&guard);
rules.0.iter().filter_map(|rule| {
match *rule {
CssRule::Style(ref style_rule) => Some(style_rule),

View file

@ -23,7 +23,7 @@ use style::properties::longhands::animation_play_state;
use style::shared_lock::SharedRwLock;
use style::stylearc::Arc;
use style::stylesheets::{Origin, Namespaces};
use style::stylesheets::{Stylesheet, NamespaceRule, CssRule, CssRules, StyleRule, KeyframesRule};
use style::stylesheets::{Stylesheet, StylesheetContents, NamespaceRule, CssRule, CssRules, StyleRule, KeyframesRule};
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframePercentage};
use style::values::{KeyframesName, CustomIdent};
use style::values::specified::{LengthOrPercentageOrAuto, Percentage, PositionComponent};
@ -72,176 +72,178 @@ fn test_parse_stylesheet() {
let mut namespaces = Namespaces::default();
namespaces.default = Some((ns!(html), ()));
let expected = Stylesheet {
origin: Origin::UserAgent,
media: Arc::new(stylesheet.shared_lock.wrap(MediaList::empty())),
shared_lock: stylesheet.shared_lock.clone(),
namespaces: RwLock::new(namespaces),
url_data: RwLock::new(url),
dirty_on_viewport_size_change: AtomicBool::new(false),
disabled: AtomicBool::new(false),
quirks_mode: QuirksMode::NoQuirks,
rules: CssRules::new(vec![
CssRule::Namespace(Arc::new(stylesheet.shared_lock.wrap(NamespaceRule {
prefix: None,
url: NsAtom::from("http://www.w3.org/1999/xhtml"),
source_location: SourceLocation {
line: 1,
column: 19,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("input"),
lower_name: local_name!("input"),
}),
Component::AttributeInNoNamespace {
local_name: local_name!("type"),
local_name_lower: local_name!("type"),
operator: AttrSelectorOperator::Equal,
value: "hidden".to_owned(),
case_sensitivity: ParsedCaseSensitivity::AsciiCaseInsensitive,
never_matches: false,
}
), (0 << 20) + (1 << 10) + (1 << 0))
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Display(longhands::display::SpecifiedValue::none),
Importance::Important),
(PropertyDeclaration::Custom(Atom::from("a"),
DeclaredValueOwned::CSSWideKeyword(CSSWideKeyword::Inherit)),
Importance::Important),
]))),
source_location: SourceLocation {
line: 3,
column: 9,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
contents: StylesheetContents {
origin: Origin::UserAgent,
namespaces: RwLock::new(namespaces),
url_data: RwLock::new(url),
dirty_on_viewport_size_change: AtomicBool::new(false),
quirks_mode: QuirksMode::NoQuirks,
rules: CssRules::new(vec![
CssRule::Namespace(Arc::new(stylesheet.shared_lock.wrap(NamespaceRule {
prefix: None,
url: NsAtom::from("http://www.w3.org/1999/xhtml"),
source_location: SourceLocation {
line: 1,
column: 19,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("html"),
lower_name: local_name!("html"),
name: local_name!("input"),
lower_name: local_name!("input"),
}),
), (0 << 20) + (0 << 10) + (1 << 0)),
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("body"),
lower_name: local_name!("body"),
})
), (0 << 20) + (0 << 10) + (1 << 0)
),
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Display(longhands::display::SpecifiedValue::block),
Importance::Normal),
]))),
source_location: SourceLocation {
line: 11,
column: 9,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::ID(Atom::from("d1")),
Component::Combinator(Combinator::Child),
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::Class(Atom::from("ok"))
), (1 << 20) + (1 << 10) + (0 << 0))
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::BackgroundColor(
longhands::background_color::SpecifiedValue::Numeric {
authored: Some("blue".to_owned().into_boxed_str()),
parsed: cssparser::RGBA::new(0, 0, 255, 255),
}
),
Importance::Normal),
(PropertyDeclaration::BackgroundPositionX(
longhands::background_position_x::SpecifiedValue(
vec![PositionComponent::zero()])),
Importance::Normal),
(PropertyDeclaration::BackgroundPositionY(
longhands::background_position_y::SpecifiedValue(
vec![PositionComponent::zero()])),
Importance::Normal),
(PropertyDeclaration::BackgroundRepeat(
longhands::background_repeat::SpecifiedValue(
vec![longhands::background_repeat::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundAttachment(
longhands::background_attachment::SpecifiedValue(
vec![longhands::background_attachment::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundImage(
longhands::background_image::SpecifiedValue(
vec![longhands::background_image::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundSize(
longhands::background_size::SpecifiedValue(
vec![longhands::background_size::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundOrigin(
longhands::background_origin::SpecifiedValue(
vec![longhands::background_origin::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundClip(
longhands::background_clip::SpecifiedValue(
vec![longhands::background_clip::single_value
::get_initial_specified_value()])),
Importance::Normal),
]))),
source_location: SourceLocation {
line: 15,
column: 9,
},
}))),
CssRule::Keyframes(Arc::new(stylesheet.shared_lock.wrap(KeyframesRule {
name: KeyframesName::Ident(CustomIdent("foo".into())),
keyframes: vec![
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(0.)]),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Width(
LengthOrPercentageOrAuto::Percentage(Percentage(0.))),
Importance::Normal),
])))
})),
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(1.)]),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Width(
LengthOrPercentageOrAuto::Percentage(Percentage(1.))),
Importance::Normal),
(PropertyDeclaration::AnimationPlayState(
animation_play_state::SpecifiedValue(
vec![animation_play_state::SingleSpecifiedValue::running])),
Importance::Normal),
]))),
})),
],
vendor_prefix: None,
source_location: SourceLocation {
line: 16,
column: 19,
},
})))
Component::AttributeInNoNamespace {
local_name: local_name!("type"),
local_name_lower: local_name!("type"),
operator: AttrSelectorOperator::Equal,
value: "hidden".to_owned(),
case_sensitivity: ParsedCaseSensitivity::AsciiCaseInsensitive,
never_matches: false,
}
), (0 << 20) + (1 << 10) + (1 << 0))
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Display(longhands::display::SpecifiedValue::none),
Importance::Important),
(PropertyDeclaration::Custom(Atom::from("a"),
DeclaredValueOwned::CSSWideKeyword(CSSWideKeyword::Inherit)),
Importance::Important),
]))),
source_location: SourceLocation {
line: 3,
column: 9,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("html"),
lower_name: local_name!("html"),
}),
), (0 << 20) + (0 << 10) + (1 << 0)),
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::LocalName(LocalName {
name: local_name!("body"),
lower_name: local_name!("body"),
})
), (0 << 20) + (0 << 10) + (1 << 0)
),
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Display(longhands::display::SpecifiedValue::block),
Importance::Normal),
]))),
source_location: SourceLocation {
line: 11,
column: 9,
},
}))),
CssRule::Style(Arc::new(stylesheet.shared_lock.wrap(StyleRule {
selectors: SelectorList::from_vec(vec!(
Selector::from_vec(vec!(
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::ID(Atom::from("d1")),
Component::Combinator(Combinator::Child),
Component::DefaultNamespace(NsAtom::from("http://www.w3.org/1999/xhtml")),
Component::Class(Atom::from("ok"))
), (1 << 20) + (1 << 10) + (0 << 0))
)),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::BackgroundColor(
longhands::background_color::SpecifiedValue::Numeric {
authored: Some("blue".to_owned().into_boxed_str()),
parsed: cssparser::RGBA::new(0, 0, 255, 255),
}
),
Importance::Normal),
(PropertyDeclaration::BackgroundPositionX(
longhands::background_position_x::SpecifiedValue(
vec![PositionComponent::zero()])),
Importance::Normal),
(PropertyDeclaration::BackgroundPositionY(
longhands::background_position_y::SpecifiedValue(
vec![PositionComponent::zero()])),
Importance::Normal),
(PropertyDeclaration::BackgroundRepeat(
longhands::background_repeat::SpecifiedValue(
vec![longhands::background_repeat::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundAttachment(
longhands::background_attachment::SpecifiedValue(
vec![longhands::background_attachment::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundImage(
longhands::background_image::SpecifiedValue(
vec![longhands::background_image::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundSize(
longhands::background_size::SpecifiedValue(
vec![longhands::background_size::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundOrigin(
longhands::background_origin::SpecifiedValue(
vec![longhands::background_origin::single_value
::get_initial_specified_value()])),
Importance::Normal),
(PropertyDeclaration::BackgroundClip(
longhands::background_clip::SpecifiedValue(
vec![longhands::background_clip::single_value
::get_initial_specified_value()])),
Importance::Normal),
]))),
source_location: SourceLocation {
line: 15,
column: 9,
},
}))),
CssRule::Keyframes(Arc::new(stylesheet.shared_lock.wrap(KeyframesRule {
name: KeyframesName::Ident(CustomIdent("foo".into())),
keyframes: vec![
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(0.)]),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Width(
LengthOrPercentageOrAuto::Percentage(Percentage(0.))),
Importance::Normal),
])))
})),
Arc::new(stylesheet.shared_lock.wrap(Keyframe {
selector: KeyframeSelector::new_for_unit_testing(
vec![KeyframePercentage::new(1.)]),
block: Arc::new(stylesheet.shared_lock.wrap(block_from(vec![
(PropertyDeclaration::Width(
LengthOrPercentageOrAuto::Percentage(Percentage(1.))),
Importance::Normal),
(PropertyDeclaration::AnimationPlayState(
animation_play_state::SpecifiedValue(
vec![animation_play_state::SingleSpecifiedValue::running])),
Importance::Normal),
]))),
})),
],
vendor_prefix: None,
source_location: SourceLocation {
line: 16,
column: 19,
},
})))
], &stylesheet.shared_lock),
], &stylesheet.shared_lock),
},
media: Arc::new(stylesheet.shared_lock.wrap(MediaList::empty())),
shared_lock: stylesheet.shared_lock.clone(),
disabled: AtomicBool::new(false),
};
assert_eq!(format!("{:#?}", stylesheet), format!("{:#?}", expected));

View file

@ -12,7 +12,7 @@ use style::media_queries::{Device, MediaList, MediaType};
use style::parser::{Parse, ParserContext};
use style::shared_lock::SharedRwLock;
use style::stylearc::Arc;
use style::stylesheets::{CssRuleType, Stylesheet, Origin};
use style::stylesheets::{CssRuleType, Stylesheet, StylesheetInDocument, Origin};
use style::stylesheets::viewport_rule::*;
use style::values::specified::LengthOrPercentageOrAuto::{self, Auto};
use style::values::specified::NoCalcLength::{self, ViewportPercentage};
@ -269,7 +269,11 @@ fn multiple_stylesheets_cascading() {
Author, error_reporter, shared_lock.clone())
];
let declarations = Cascade::from_stylesheets(stylesheets.iter(), &shared_lock.read(), &device).finish();
let declarations = Cascade::from_stylesheets(
stylesheets.iter().map(|s| &**s),
&shared_lock.read(),
&device,
).finish();
assert_decl_len!(declarations == 3);
assert_decl_eq!(&declarations[0], UserAgent, Zoom: Zoom::Number(1.));
assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px));
@ -283,7 +287,11 @@ fn multiple_stylesheets_cascading() {
stylesheet!("@viewport { min-width: 300px !important; min-height: 300px !important; zoom: 3 !important; }",
Author, error_reporter, shared_lock.clone())
];
let declarations = Cascade::from_stylesheets(stylesheets.iter(), &shared_lock.read(), &device).finish();
let declarations = Cascade::from_stylesheets(
stylesheets.iter().map(|s| &**s),
&shared_lock.read(),
&device,
).finish();
assert_decl_len!(declarations == 3);
assert_decl_eq!(&declarations[0], UserAgent, MinWidth: viewport_length!(100., px), !important);
assert_decl_eq!(&declarations[1], User, MinHeight: viewport_length!(200., px), !important);