mirror of
https://github.com/servo/servo.git
synced 2025-07-24 07:40:27 +01:00
Auto merge of #20657 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit from details.
This commit is contained in:
commit
087bd20b6d
14 changed files with 329 additions and 98 deletions
|
@ -397,6 +397,14 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
unsafe { self.element.is_html_element() }
|
unsafe { self.element.is_html_element() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_mathml_element(&self) -> bool {
|
||||||
|
*self.element.namespace() == ns!(mathml)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_svg_element(&self) -> bool {
|
||||||
|
*self.element.namespace() == ns!(svg)
|
||||||
|
}
|
||||||
|
|
||||||
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
|
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
|
(*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
|
||||||
|
|
|
@ -135,7 +135,7 @@ use style::selector_parser::{RestyleDamage, Snapshot};
|
||||||
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard};
|
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard};
|
||||||
use style::str::{split_html_space_chars, str_join};
|
use style::str::{split_html_space_chars, str_join};
|
||||||
use style::stylesheet_set::DocumentStylesheetSet;
|
use style::stylesheet_set::DocumentStylesheetSet;
|
||||||
use style::stylesheets::{Stylesheet, StylesheetContents, Origin, OriginSet};
|
use style::stylesheets::{CssRule, Stylesheet, Origin, OriginSet};
|
||||||
use task_source::TaskSource;
|
use task_source::TaskSource;
|
||||||
use time;
|
use time;
|
||||||
use timers::OneshotTimerCallback;
|
use timers::OneshotTimerCallback;
|
||||||
|
@ -216,16 +216,24 @@ impl PartialEq for StyleSheetInDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
impl ::style::stylesheets::StylesheetInDocument for StyleSheetInDocument {
|
||||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
|
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
self.sheet.contents(guard)
|
self.sheet.origin(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
|
self.sheet.quirks_mode(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enabled(&self) -> bool {
|
||||||
|
self.sheet.enabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
self.sheet.media(guard)
|
self.sheet.media(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enabled(&self) -> bool {
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
self.sheet.enabled()
|
self.sheet.rules(guard)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,6 +434,15 @@ pub trait TElement:
|
||||||
/// Return whether this element is an element in the HTML namespace.
|
/// Return whether this element is an element in the HTML namespace.
|
||||||
fn is_html_element(&self) -> bool;
|
fn is_html_element(&self) -> bool;
|
||||||
|
|
||||||
|
/// Return whether this element is an element in the MathML namespace.
|
||||||
|
fn is_mathml_element(&self) -> bool;
|
||||||
|
|
||||||
|
/// Return whether this element is an element in the SVG namespace.
|
||||||
|
fn is_svg_element(&self) -> bool;
|
||||||
|
|
||||||
|
/// Return whether this element is an element in the XUL namespace.
|
||||||
|
fn is_xul_element(&self) -> bool { false }
|
||||||
|
|
||||||
/// Return the list of slotted nodes of this node.
|
/// Return the list of slotted nodes of this node.
|
||||||
fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
|
fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
|
||||||
&[]
|
&[]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//! Data needed to style a Gecko document.
|
//! Data needed to style a Gecko document.
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||||
|
use context::QuirksMode;
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
||||||
use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
|
use gecko_bindings::structs::{self, RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
|
||||||
|
@ -17,7 +18,7 @@ use properties::ComputedValues;
|
||||||
use selector_parser::SnapshotMap;
|
use selector_parser::SnapshotMap;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
||||||
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
use stylesheets::{CssRule, Origin, StylesheetContents, StylesheetInDocument};
|
||||||
use stylist::Stylist;
|
use stylist::Stylist;
|
||||||
|
|
||||||
/// Little wrapper to a Gecko style sheet.
|
/// Little wrapper to a Gecko style sheet.
|
||||||
|
@ -58,6 +59,16 @@ impl GeckoStyleSheet {
|
||||||
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
|
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the StylesheetContents for this stylesheet.
|
||||||
|
pub fn contents(&self) -> &StylesheetContents {
|
||||||
|
debug_assert!(!self.inner().mContents.mRawPtr.is_null());
|
||||||
|
unsafe {
|
||||||
|
let contents =
|
||||||
|
(&**StylesheetContents::as_arc(&&*self.inner().mContents.mRawPtr)) as *const _;
|
||||||
|
&*contents
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for GeckoStyleSheet {
|
impl Drop for GeckoStyleSheet {
|
||||||
|
@ -74,13 +85,12 @@ impl Clone for GeckoStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StylesheetInDocument for GeckoStyleSheet {
|
impl StylesheetInDocument for GeckoStyleSheet {
|
||||||
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
|
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
debug_assert!(!self.inner().mContents.mRawPtr.is_null());
|
self.contents().origin
|
||||||
unsafe {
|
}
|
||||||
let contents =
|
|
||||||
(&**StylesheetContents::as_arc(&&*self.inner().mContents.mRawPtr)) as *const _;
|
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
&*contents
|
self.contents().quirks_mode
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
@ -103,6 +113,11 @@ impl StylesheetInDocument for GeckoStyleSheet {
|
||||||
fn enabled(&self) -> bool {
|
fn enabled(&self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
self.contents().rules(guard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The container for data that a Servo-backed Gecko document needs to style
|
/// The container for data that a Servo-backed Gecko document needs to style
|
||||||
|
|
|
@ -18478,7 +18478,7 @@ pub mod root {
|
||||||
eCSSProperty_flex_grow = 105,
|
eCSSProperty_flex_grow = 105,
|
||||||
eCSSProperty_flex_shrink = 106,
|
eCSSProperty_flex_shrink = 106,
|
||||||
eCSSProperty_flex_wrap = 107,
|
eCSSProperty_flex_wrap = 107,
|
||||||
eCSSProperty_float_ = 108,
|
eCSSProperty_float = 108,
|
||||||
eCSSProperty__moz_float_edge = 109,
|
eCSSProperty__moz_float_edge = 109,
|
||||||
eCSSProperty_flood_color = 110,
|
eCSSProperty_flood_color = 110,
|
||||||
eCSSProperty_flood_opacity = 111,
|
eCSSProperty_flood_opacity = 111,
|
||||||
|
|
|
@ -673,11 +673,6 @@ impl<'le> GeckoElement<'le> {
|
||||||
self.as_node().node_info().mInner.mNamespaceID
|
self.as_node().node_info().mInner.mNamespaceID
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn is_xul_element(&self) -> bool {
|
|
||||||
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn has_id(&self) -> bool {
|
fn has_id(&self) -> bool {
|
||||||
self.as_node()
|
self.as_node()
|
||||||
|
@ -826,7 +821,7 @@ impl<'le> GeckoElement<'le> {
|
||||||
match self.parent_element() {
|
match self.parent_element() {
|
||||||
Some(e) => {
|
Some(e) => {
|
||||||
e.local_name() == &*local_name!("use") &&
|
e.local_name() == &*local_name!("use") &&
|
||||||
e.namespace() == &*ns!("http://www.w3.org/2000/svg")
|
e.is_svg_element()
|
||||||
},
|
},
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
|
@ -1058,7 +1053,22 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_html_element(&self) -> bool {
|
fn is_html_element(&self) -> bool {
|
||||||
self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
|
self.namespace_id() == structs::kNameSpaceID_XHTML as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_mathml_element(&self) -> bool {
|
||||||
|
self.namespace_id() == structs::kNameSpaceID_MathML as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_svg_element(&self) -> bool {
|
||||||
|
self.namespace_id() == structs::kNameSpaceID_SVG as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_xul_element(&self) -> bool {
|
||||||
|
self.namespace_id() == structs::root::kNameSpaceID_XUL as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of slotted nodes of this node.
|
/// Return the list of slotted nodes of this node.
|
||||||
|
|
|
@ -311,10 +311,7 @@ class Longhand(object):
|
||||||
return "<{} as ToAnimatedValue>::AnimatedValue".format(computed)
|
return "<{} as ToAnimatedValue>::AnimatedValue".format(computed)
|
||||||
|
|
||||||
def nscsspropertyid(self):
|
def nscsspropertyid(self):
|
||||||
ident = self.ident
|
return "nsCSSPropertyID::eCSSProperty_%s" % self.ident
|
||||||
if ident == "float":
|
|
||||||
ident = "float_"
|
|
||||||
return "nsCSSPropertyID::eCSSProperty_%s" % ident
|
|
||||||
|
|
||||||
|
|
||||||
class Shorthand(object):
|
class Shorthand(object):
|
||||||
|
|
|
@ -23,6 +23,86 @@ pub struct StyleAdjuster<'a, 'b: 'a> {
|
||||||
style: &'a mut StyleBuilder<'b>,
|
style: &'a mut StyleBuilder<'b>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn is_topmost_svg_svg_element<E>(e: E) -> bool
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
debug_assert!(e.is_svg_element());
|
||||||
|
if e.local_name() != &*atom!("svg") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = match e.traversal_parent() {
|
||||||
|
Some(n) => n,
|
||||||
|
None => return true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !parent.is_svg_element() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.local_name() == &*atom!("foreignObject")
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-display/#unbox
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn is_effective_display_none_for_display_contents<E>(element: E) -> bool
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
{
|
||||||
|
use Atom;
|
||||||
|
|
||||||
|
// FIXME(emilio): This should be an actual static.
|
||||||
|
lazy_static! {
|
||||||
|
static ref SPECIAL_HTML_ELEMENTS: [Atom; 16] = [
|
||||||
|
atom!("br"), atom!("wbr"), atom!("meter"), atom!("progress"),
|
||||||
|
atom!("canvas"), atom!("embed"), atom!("object"), atom!("audio"),
|
||||||
|
atom!("iframe"), atom!("img"), atom!("video"), atom!("frame"),
|
||||||
|
atom!("frameset"), atom!("input"), atom!("textarea"),
|
||||||
|
atom!("select"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-display/#unbox-svg
|
||||||
|
//
|
||||||
|
// There's a note about "Unknown elements", but there's not a good way to
|
||||||
|
// know what that means, or to get that information from here, and no other
|
||||||
|
// UA implements this either.
|
||||||
|
lazy_static! {
|
||||||
|
static ref SPECIAL_SVG_ELEMENTS: [Atom; 6] = [
|
||||||
|
atom!("svg"), atom!("a"), atom!("g"), atom!("use"),
|
||||||
|
atom!("tspan"), atom!("textPath"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-display/#unbox-html
|
||||||
|
if element.is_html_element() {
|
||||||
|
let local_name = element.local_name();
|
||||||
|
return SPECIAL_HTML_ELEMENTS.iter().any(|name| &**name == local_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-display/#unbox-svg
|
||||||
|
if element.is_svg_element() {
|
||||||
|
if is_topmost_svg_svg_element(element) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let local_name = element.local_name();
|
||||||
|
return !SPECIAL_SVG_ELEMENTS.iter().any(|name| &**name == local_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://drafts.csswg.org/css-display/#unbox-mathml
|
||||||
|
//
|
||||||
|
// We always treat XUL as display: none. We don't use display:
|
||||||
|
// contents in XUL anyway, so should be fine to be consistent with
|
||||||
|
// MathML unless there's a use case for it.
|
||||||
|
if element.is_mathml_element() || element.is_xul_element() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
/// Trivially constructs a new StyleAdjuster.
|
/// Trivially constructs a new StyleAdjuster.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -377,20 +457,35 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Native anonymous content converts display:contents into display:inline.
|
/// Handles the relevant sections in:
|
||||||
|
///
|
||||||
|
/// https://drafts.csswg.org/css-display/#unbox-html
|
||||||
|
///
|
||||||
|
/// And forbidding display: contents in pseudo-elements, at least for now.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
fn adjust_for_prohibited_display_contents(&mut self) {
|
fn adjust_for_prohibited_display_contents<E>(&mut self, element: Option<E>)
|
||||||
// TODO: We should probably convert display:contents into display:none
|
where
|
||||||
// in some cases too: https://drafts.csswg.org/css-display/#unbox
|
E: TElement,
|
||||||
//
|
{
|
||||||
// FIXME(emilio): ::before and ::after should support display: contents,
|
if self.style.get_box().clone_display() != Display::Contents {
|
||||||
// see bug 1418138.
|
|
||||||
if self.style.pseudo.is_none() || self.style.get_box().clone_display() != Display::Contents
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.style.mutate_box().set_display(Display::Inline);
|
// FIXME(emilio): ::before and ::after should support display: contents,
|
||||||
|
// see bug 1418138.
|
||||||
|
if self.style.pseudo.is_some() {
|
||||||
|
self.style.mutate_box().set_display(Display::Inline);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let element = match element {
|
||||||
|
Some(e) => e,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_effective_display_none_for_display_contents(element) {
|
||||||
|
self.style.mutate_box().set_display(Display::None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a <fieldset> has grid/flex display type, we need to inherit
|
/// If a <fieldset> has grid/flex display type, we need to inherit
|
||||||
|
@ -657,7 +752,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
self.adjust_for_visited(element);
|
self.adjust_for_visited(element);
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
{
|
{
|
||||||
self.adjust_for_prohibited_display_contents();
|
self.adjust_for_prohibited_display_contents(element);
|
||||||
self.adjust_for_fieldset_content(layout_parent_style);
|
self.adjust_for_fieldset_content(layout_parent_style);
|
||||||
}
|
}
|
||||||
self.adjust_for_top_layer();
|
self.adjust_for_top_layer();
|
||||||
|
|
|
@ -478,7 +478,7 @@ where
|
||||||
sheet: &S,
|
sheet: &S,
|
||||||
guard: &SharedRwLockReadGuard,
|
guard: &SharedRwLockReadGuard,
|
||||||
) -> &mut SheetCollection<S> {
|
) -> &mut SheetCollection<S> {
|
||||||
let origin = sheet.contents(guard).origin;
|
let origin = sheet.origin(guard);
|
||||||
self.collections.borrow_mut_for_origin(&origin)
|
self.collections.borrow_mut_for_origin(&origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//!
|
//!
|
||||||
//! [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
//! [import]: https://drafts.csswg.org/css-cascade-3/#at-import
|
||||||
|
|
||||||
|
use context::QuirksMode;
|
||||||
use cssparser::SourceLocation;
|
use cssparser::SourceLocation;
|
||||||
use media_queries::MediaList;
|
use media_queries::MediaList;
|
||||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
use shared_lock::{DeepCloneParams, DeepCloneWithLock};
|
||||||
|
@ -13,13 +14,52 @@ use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use str::CssStringWriter;
|
use str::CssStringWriter;
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
use stylesheets::{StylesheetContents, StylesheetInDocument};
|
use stylesheets::{CssRule, Origin, StylesheetInDocument};
|
||||||
use values::CssUrl;
|
use values::CssUrl;
|
||||||
|
|
||||||
|
/// With asynchronous stylesheet parsing, we can't synchronously create a
|
||||||
|
/// GeckoStyleSheet. So we use this placeholder instead.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PendingSheet {
|
||||||
|
origin: Origin,
|
||||||
|
quirks_mode: QuirksMode,
|
||||||
|
}
|
||||||
|
|
||||||
/// A sheet that is held from an import rule.
|
/// A sheet that is held from an import rule.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportSheet(pub ::gecko::data::GeckoStyleSheet);
|
pub enum ImportSheet {
|
||||||
|
/// A bonafide stylesheet.
|
||||||
|
Sheet(::gecko::data::GeckoStyleSheet),
|
||||||
|
/// An @import created while parsing off-main-thread, whose Gecko sheet has
|
||||||
|
/// yet to be created and attached.
|
||||||
|
Pending(PendingSheet),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl ImportSheet {
|
||||||
|
/// Creates a new ImportSheet from a GeckoStyleSheet.
|
||||||
|
pub fn new(sheet: ::gecko::data::GeckoStyleSheet) -> Self {
|
||||||
|
ImportSheet::Sheet(sheet)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a pending ImportSheet for a load that has not started yet.
|
||||||
|
pub fn new_pending(origin: Origin, quirks_mode: QuirksMode) -> Self {
|
||||||
|
ImportSheet::Pending(PendingSheet {
|
||||||
|
origin,
|
||||||
|
quirks_mode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference to the GeckoStyleSheet in this ImportSheet, if it
|
||||||
|
/// exists.
|
||||||
|
pub fn as_sheet(&self) -> Option<&::gecko::data::GeckoStyleSheet> {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => Some(s),
|
||||||
|
ImportSheet::Pending(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
impl DeepCloneWithLock for ImportSheet {
|
impl DeepCloneWithLock for ImportSheet {
|
||||||
|
@ -31,10 +71,53 @@ impl DeepCloneWithLock for ImportSheet {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
use gecko::data::GeckoStyleSheet;
|
use gecko::data::GeckoStyleSheet;
|
||||||
use gecko_bindings::bindings;
|
use gecko_bindings::bindings;
|
||||||
let clone = unsafe {
|
match *self {
|
||||||
bindings::Gecko_StyleSheet_Clone(self.0.raw() as *const _, params.reference_sheet)
|
ImportSheet::Sheet(ref s) => {
|
||||||
};
|
let clone = unsafe {
|
||||||
ImportSheet(unsafe { GeckoStyleSheet::from_addrefed(clone) })
|
bindings::Gecko_StyleSheet_Clone(s.raw() as *const _, params.reference_sheet)
|
||||||
|
};
|
||||||
|
ImportSheet::Sheet(unsafe { GeckoStyleSheet::from_addrefed(clone) })
|
||||||
|
},
|
||||||
|
ImportSheet::Pending(ref p) => ImportSheet::Pending(p.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
impl StylesheetInDocument for ImportSheet {
|
||||||
|
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => s.contents().origin,
|
||||||
|
ImportSheet::Pending(ref p) => p.origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => s.contents().quirks_mode,
|
||||||
|
ImportSheet::Pending(ref p) => p.quirks_mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enabled(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => s.enabled(),
|
||||||
|
ImportSheet::Pending(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => s.media(guard),
|
||||||
|
ImportSheet::Pending(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
match *self {
|
||||||
|
ImportSheet::Sheet(ref s) => s.contents().rules(guard),
|
||||||
|
ImportSheet::Pending(_) => &[],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,19 +126,27 @@ impl DeepCloneWithLock for ImportSheet {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ImportSheet(pub ::servo_arc::Arc<::stylesheets::Stylesheet>);
|
pub struct ImportSheet(pub ::servo_arc::Arc<::stylesheets::Stylesheet>);
|
||||||
|
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
impl StylesheetInDocument for ImportSheet {
|
impl StylesheetInDocument for ImportSheet {
|
||||||
/// Get the media associated with this stylesheet.
|
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
self.0.origin(guard)
|
||||||
self.0.media(guard)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
|
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
self.0.contents(guard)
|
self.0.quirks_mode(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enabled(&self) -> bool {
|
fn enabled(&self) -> bool {
|
||||||
self.0.enabled()
|
self.0.enabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
self.0.media(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
self.0.rules(guard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
|
|
@ -9,7 +9,7 @@ use media_queries::Device;
|
||||||
use shared_lock::SharedRwLockReadGuard;
|
use shared_lock::SharedRwLockReadGuard;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use stylesheets::{CssRule, CssRules, DocumentRule, ImportRule, MediaRule, SupportsRule};
|
use stylesheets::{CssRule, DocumentRule, ImportRule, MediaRule, SupportsRule};
|
||||||
use stylesheets::StylesheetInDocument;
|
use stylesheets::StylesheetInDocument;
|
||||||
|
|
||||||
/// An iterator over a list of rules.
|
/// An iterator over a list of rules.
|
||||||
|
@ -35,10 +35,10 @@ where
|
||||||
device: &'a Device,
|
device: &'a Device,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
guard: &'a SharedRwLockReadGuard<'b>,
|
guard: &'a SharedRwLockReadGuard<'b>,
|
||||||
rules: &'a CssRules,
|
rules: &'a [CssRule],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut stack = SmallVec::new();
|
let mut stack = SmallVec::new();
|
||||||
stack.push(rules.0.iter());
|
stack.push(rules.iter());
|
||||||
Self {
|
Self {
|
||||||
device: device,
|
device: device,
|
||||||
quirks_mode: quirks_mode,
|
quirks_mode: quirks_mode,
|
||||||
|
@ -102,10 +102,7 @@ where
|
||||||
}
|
}
|
||||||
import_rule
|
import_rule
|
||||||
.stylesheet
|
.stylesheet
|
||||||
.contents(self.guard)
|
.rules(self.guard)
|
||||||
.rules
|
|
||||||
.read_with(self.guard)
|
|
||||||
.0
|
|
||||||
.iter()
|
.iter()
|
||||||
},
|
},
|
||||||
CssRule::Document(ref doc_rule) => {
|
CssRule::Document(ref doc_rule) => {
|
||||||
|
|
|
@ -103,22 +103,10 @@ impl StylesheetContents {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an iterator using the condition `C`.
|
/// Returns a reference to the list of rules.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_rules<'a, 'b, C>(
|
pub fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
&'a self,
|
&self.rules.read_with(guard).0
|
||||||
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),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Measure heap usage.
|
/// Measure heap usage.
|
||||||
|
@ -189,32 +177,20 @@ macro_rules! rule_filter {
|
||||||
|
|
||||||
/// A trait to represent a given stylesheet in a document.
|
/// A trait to represent a given stylesheet in a document.
|
||||||
pub trait StylesheetInDocument {
|
pub trait StylesheetInDocument {
|
||||||
/// Get the contents of this stylesheet.
|
|
||||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents;
|
|
||||||
|
|
||||||
/// Get the stylesheet origin.
|
/// Get the stylesheet origin.
|
||||||
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin;
|
||||||
self.contents(guard).origin
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the stylesheet quirks mode.
|
/// Get the stylesheet quirks mode.
|
||||||
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode;
|
||||||
self.contents(guard).quirks_mode
|
|
||||||
}
|
/// Get whether this stylesheet is enabled.
|
||||||
|
fn enabled(&self) -> bool;
|
||||||
|
|
||||||
/// Get the media associated with this stylesheet.
|
/// Get the media associated with this stylesheet.
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList>;
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList>;
|
||||||
|
|
||||||
/// Returns whether the style-sheet applies for the current device.
|
/// Returns a reference to the list of rules in this stylesheet.
|
||||||
fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule];
|
||||||
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`.
|
/// Return an iterator using the condition `C`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -226,7 +202,15 @@ pub trait StylesheetInDocument {
|
||||||
where
|
where
|
||||||
C: NestedRuleIterationCondition,
|
C: NestedRuleIterationCondition,
|
||||||
{
|
{
|
||||||
self.contents(guard).iter_rules(device, guard)
|
RulesIterator::new(device, self.quirks_mode(guard), guard, self.rules(guard))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the style-sheet applies for the current device.
|
||||||
|
fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
|
||||||
|
match self.media(guard) {
|
||||||
|
Some(medialist) => medialist.evaluate(device, self.quirks_mode(guard)),
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an iterator over the effective rules within the style-sheet, as
|
/// Return an iterator over the effective rules within the style-sheet, as
|
||||||
|
@ -255,8 +239,12 @@ pub trait StylesheetInDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StylesheetInDocument for Stylesheet {
|
impl StylesheetInDocument for Stylesheet {
|
||||||
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
|
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
&self.contents
|
self.contents.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
|
self.contents.quirks_mode
|
||||||
}
|
}
|
||||||
|
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
@ -266,6 +254,11 @@ impl StylesheetInDocument for Stylesheet {
|
||||||
fn enabled(&self) -> bool {
|
fn enabled(&self) -> bool {
|
||||||
!self.disabled()
|
!self.disabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
self.contents.rules(guard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple wrapper over an `Arc<Stylesheet>`, with pointer comparison, and
|
/// A simple wrapper over an `Arc<Stylesheet>`, with pointer comparison, and
|
||||||
|
@ -289,8 +282,12 @@ impl ToMediaListKey for DocumentStyleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StylesheetInDocument for DocumentStyleSheet {
|
impl StylesheetInDocument for DocumentStyleSheet {
|
||||||
fn contents(&self, guard: &SharedRwLockReadGuard) -> &StylesheetContents {
|
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
|
||||||
self.0.contents(guard)
|
self.0.origin(guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
|
||||||
|
self.0.quirks_mode(guard)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
||||||
|
@ -300,6 +297,11 @@ impl StylesheetInDocument for DocumentStyleSheet {
|
||||||
fn enabled(&self) -> bool {
|
fn enabled(&self) -> bool {
|
||||||
self.0.enabled()
|
self.0.enabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
|
||||||
|
self.0.rules(guard)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stylesheet {
|
impl Stylesheet {
|
||||||
|
|
|
@ -2048,7 +2048,7 @@ pub extern "C" fn Servo_ImportRule_GetSheet(
|
||||||
rule: RawServoImportRuleBorrowed,
|
rule: RawServoImportRuleBorrowed,
|
||||||
) -> *const ServoStyleSheet {
|
) -> *const ServoStyleSheet {
|
||||||
read_locked_arc(rule, |rule: &ImportRule| {
|
read_locked_arc(rule, |rule: &ImportRule| {
|
||||||
rule.stylesheet.0.raw() as *const ServoStyleSheet
|
rule.stylesheet.as_sheet().unwrap().raw() as *const ServoStyleSheet
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,8 @@ impl StyleStylesheetLoader for StylesheetLoader {
|
||||||
|
|
||||||
debug_assert!(!child_sheet.is_null(),
|
debug_assert!(!child_sheet.is_null(),
|
||||||
"Import rules should always have a strong sheet");
|
"Import rules should always have a strong sheet");
|
||||||
let stylesheet = unsafe {
|
let sheet = unsafe { GeckoStyleSheet::from_addrefed(child_sheet) };
|
||||||
ImportSheet(GeckoStyleSheet::from_addrefed(child_sheet))
|
let stylesheet = ImportSheet::new(sheet);
|
||||||
};
|
|
||||||
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
|
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue