mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Stylo: Bug 1355408 - add support for @-moz-document
This commit is contained in:
parent
9c9bd17871
commit
b22e0e9494
12 changed files with 338 additions and 24 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -963,6 +963,7 @@ dependencies = [
|
|||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nsstring_vendor 0.1.0",
|
||||
"parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.18.0",
|
||||
"style 0.0.1",
|
||||
|
|
|
@ -85,6 +85,7 @@ impl CSSRule {
|
|||
StyleCssRule::Viewport(s) => Root::upcast(CSSViewportRule::new(window, parent_stylesheet, s)),
|
||||
StyleCssRule::Supports(s) => Root::upcast(CSSSupportsRule::new(window, parent_stylesheet, s)),
|
||||
StyleCssRule::Page(_) => unreachable!(),
|
||||
StyleCssRule::Document(_) => unimplemented!(), // TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -349,6 +349,7 @@ mod bindings {
|
|||
"mozilla::ServoElementSnapshot.*",
|
||||
"mozilla::CSSPseudoClassType",
|
||||
"mozilla::css::SheetParsingMode",
|
||||
"mozilla::css::URLMatchingFunction",
|
||||
"mozilla::HalfCorner",
|
||||
"mozilla::PropertyStyleAnimationValuePair",
|
||||
"mozilla::TraversalRestyleBehavior",
|
||||
|
@ -739,6 +740,7 @@ mod bindings {
|
|||
"UpdateAnimationsTasks",
|
||||
"LengthParsingMode",
|
||||
"InheritTarget",
|
||||
"URLMatchingFunction",
|
||||
];
|
||||
struct ArrayType {
|
||||
cpp_type: &'static str,
|
||||
|
|
176
components/style/document_condition.rs
Normal file
176
components/style/document_condition.rs
Normal file
|
@ -0,0 +1,176 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
//! [@document rules](https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document)
|
||||
//! initially in CSS Conditional Rules Module Level 3, @document has been postponed to the level 4.
|
||||
//! We implement the prefixed `@-moz-document`.
|
||||
|
||||
use cssparser::{Parser, Token, serialize_string};
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::bindings::Gecko_DocumentRule_UseForPresentation;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::URLMatchingFunction as GeckoUrlMatchingFunction;
|
||||
use media_queries::Device;
|
||||
#[cfg(feature = "gecko")]
|
||||
use nsstring::nsCString;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
/// A URL matching function for a `@document` rule's condition.
|
||||
#[derive(Debug)]
|
||||
pub enum UrlMatchingFunction {
|
||||
/// Exact URL matching function. It evaluates to true whenever the
|
||||
/// URL of the document being styled is exactly the URL given.
|
||||
Url(SpecifiedUrl),
|
||||
/// URL prefix matching function. It evaluates to true whenever the
|
||||
/// URL of the document being styled has the argument to the
|
||||
/// function as an initial substring (which is true when the two
|
||||
/// strings are equal). When the argument is the empty string,
|
||||
/// it evaluates to true for all documents.
|
||||
UrlPrefix(String),
|
||||
/// Domain matching function. It evaluates to true whenever the URL
|
||||
/// of the document being styled has a host subcomponent and that
|
||||
/// host subcomponent is exactly the argument to the ‘domain()’
|
||||
/// function or a final substring of the host component is a
|
||||
/// period (U+002E) immediately followed by the argument to the
|
||||
/// ‘domain()’ function.
|
||||
Domain(String),
|
||||
/// Regular expression matching function. It evaluates to true
|
||||
/// whenever the regular expression matches the entirety of the URL
|
||||
/// of the document being styled.
|
||||
RegExp(String),
|
||||
}
|
||||
|
||||
macro_rules! parse_quoted_or_unquoted_string {
|
||||
($input:ident, $url_matching_function:expr) => {
|
||||
$input.parse_nested_block(|input| {
|
||||
let start = input.position();
|
||||
input.parse_entirely(|input| {
|
||||
match input.next() {
|
||||
Ok(Token::QuotedString(value)) =>
|
||||
Ok($url_matching_function(value.into_owned())),
|
||||
_ => Err(()),
|
||||
}
|
||||
}).or_else(|_| {
|
||||
while let Ok(_) = input.next() {}
|
||||
Ok($url_matching_function(input.slice_from(start).to_string()))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UrlMatchingFunction {
|
||||
/// Parse a URL matching function for a`@document` rule's condition.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<UrlMatchingFunction, ()> {
|
||||
if input.try(|input| input.expect_function_matching("url-prefix")).is_ok() {
|
||||
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::UrlPrefix)
|
||||
} else if input.try(|input| input.expect_function_matching("domain")).is_ok() {
|
||||
parse_quoted_or_unquoted_string!(input, UrlMatchingFunction::Domain)
|
||||
} else if input.try(|input| input.expect_function_matching("regexp")).is_ok() {
|
||||
input.parse_nested_block(|input| {
|
||||
Ok(UrlMatchingFunction::RegExp(input.expect_string()?.into_owned()))
|
||||
})
|
||||
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||
Ok(UrlMatchingFunction::Url(url))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Evaluate a URL matching function.
|
||||
pub fn evaluate(&self, device: &Device) -> bool {
|
||||
let func = match *self {
|
||||
UrlMatchingFunction::Url(_) => GeckoUrlMatchingFunction::eURL,
|
||||
UrlMatchingFunction::UrlPrefix(_) => GeckoUrlMatchingFunction::eURLPrefix,
|
||||
UrlMatchingFunction::Domain(_) => GeckoUrlMatchingFunction::eDomain,
|
||||
UrlMatchingFunction::RegExp(_) => GeckoUrlMatchingFunction::eRegExp,
|
||||
};
|
||||
let pattern = nsCString::from(match *self {
|
||||
UrlMatchingFunction::Url(ref url) => url.as_str(),
|
||||
UrlMatchingFunction::UrlPrefix(ref pat) |
|
||||
UrlMatchingFunction::Domain(ref pat) |
|
||||
UrlMatchingFunction::RegExp(ref pat) => pat,
|
||||
});
|
||||
unsafe {
|
||||
Gecko_DocumentRule_UseForPresentation(&*device.pres_context, &*pattern, func)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
/// Evaluate a URL matching function.
|
||||
pub fn evaluate(&self, _: &Device) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for UrlMatchingFunction {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write {
|
||||
match *self {
|
||||
UrlMatchingFunction::Url(ref url) => {
|
||||
url.to_css(dest)
|
||||
},
|
||||
UrlMatchingFunction::UrlPrefix(ref url_prefix) => {
|
||||
dest.write_str("url-prefix(")?;
|
||||
serialize_string(url_prefix, dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
UrlMatchingFunction::Domain(ref domain) => {
|
||||
dest.write_str("domain(")?;
|
||||
serialize_string(domain, dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
UrlMatchingFunction::RegExp(ref regex) => {
|
||||
dest.write_str("regexp(")?;
|
||||
serialize_string(regex, dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `@document` rule's condition.
|
||||
///
|
||||
/// https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document
|
||||
///
|
||||
/// The `@document` rule's condition is written as a comma-separated list of
|
||||
/// URL matching functions, and the condition evaluates to true whenever any
|
||||
/// one of those functions evaluates to true.
|
||||
#[derive(Debug)]
|
||||
pub struct DocumentCondition(Vec<UrlMatchingFunction>);
|
||||
|
||||
impl DocumentCondition {
|
||||
/// Parse a document condition.
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
-> Result<Self, ()> {
|
||||
input.parse_comma_separated(|input| UrlMatchingFunction::parse(context, input))
|
||||
.map(DocumentCondition)
|
||||
}
|
||||
|
||||
/// Evaluate a document condition.
|
||||
pub fn evaluate(&self, device: &Device) -> bool {
|
||||
self.0.iter().any(|ref url_matching_function|
|
||||
url_matching_function.evaluate(device)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for DocumentCondition {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write {
|
||||
let mut iter = self.0.iter();
|
||||
let first = iter.next()
|
||||
.expect("Empty DocumentCondition, should contain at least one URL matching function");
|
||||
first.to_css(dest)?;
|
||||
for url_matching_function in iter {
|
||||
dest.write_str(", ")?;
|
||||
url_matching_function.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -194,6 +194,7 @@ use gecko_bindings::structs::EffectCompositor_CascadeLevel;
|
|||
use gecko_bindings::structs::UpdateAnimationsTasks;
|
||||
use gecko_bindings::structs::LengthParsingMode;
|
||||
use gecko_bindings::structs::InheritTarget;
|
||||
use gecko_bindings::structs::URLMatchingFunction;
|
||||
pub type nsTArrayBorrowed_uintptr_t<'a> = &'a mut ::gecko_bindings::structs::nsTArray<usize>;
|
||||
pub type ServoCssRulesStrong = ::gecko_bindings::sugar::ownership::Strong<ServoCssRules>;
|
||||
pub type ServoCssRulesBorrowed<'a> = &'a ServoCssRules;
|
||||
|
@ -1549,6 +1550,14 @@ extern "C" {
|
|||
extern "C" {
|
||||
pub fn Gecko_UnregisterProfilerThread();
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Gecko_DocumentRule_UseForPresentation(arg1:
|
||||
RawGeckoPresContextBorrowed,
|
||||
aPattern: *const nsACString,
|
||||
aURLMatchingFunction:
|
||||
URLMatchingFunction)
|
||||
-> bool;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn Servo_Element_ClearData(node: RawGeckoElementBorrowed);
|
||||
}
|
||||
|
|
|
@ -2130,6 +2130,18 @@ pub mod root {
|
|||
ComplexColorValue ) , "::" , stringify ! (
|
||||
_mOwningThread ) ));
|
||||
}
|
||||
#[repr(i32)]
|
||||
/**
|
||||
* Enum defining the type of URL matching function for a @-moz-document rule
|
||||
* condition.
|
||||
*/
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum URLMatchingFunction {
|
||||
eURL = 0,
|
||||
eURLPrefix = 1,
|
||||
eDomain = 2,
|
||||
eRegExp = 3,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DocumentRule {
|
||||
|
|
|
@ -2036,6 +2036,18 @@ pub mod root {
|
|||
ComplexColorValue ) , "::" , stringify ! ( mRefCnt
|
||||
) ));
|
||||
}
|
||||
#[repr(i32)]
|
||||
/**
|
||||
* Enum defining the type of URL matching function for a @-moz-document rule
|
||||
* condition.
|
||||
*/
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum URLMatchingFunction {
|
||||
eURL = 0,
|
||||
eURLPrefix = 1,
|
||||
eDomain = 2,
|
||||
eRegExp = 3,
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct DocumentRule {
|
||||
|
|
|
@ -93,6 +93,7 @@ pub mod context;
|
|||
pub mod counter_style;
|
||||
pub mod custom_properties;
|
||||
pub mod data;
|
||||
pub mod document_condition;
|
||||
pub mod dom;
|
||||
pub mod element_state;
|
||||
#[cfg(feature = "servo")] mod encoding_support;
|
||||
|
|
|
@ -12,6 +12,7 @@ use counter_style::{CounterStyleRule, parse_counter_style_name, parse_counter_st
|
|||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser};
|
||||
use cssparser::{AtRuleType, RuleListParser, parse_one_rule};
|
||||
use cssparser::ToCss as ParserToCss;
|
||||
use document_condition::DocumentCondition;
|
||||
use error_reporting::{ParseErrorReporter, NullReporter};
|
||||
#[cfg(feature = "servo")]
|
||||
use font_face::FontFaceRuleData;
|
||||
|
@ -299,6 +300,7 @@ pub enum CssRule {
|
|||
Keyframes(Arc<Locked<KeyframesRule>>),
|
||||
Supports(Arc<Locked<SupportsRule>>),
|
||||
Page(Arc<Locked<PageRule>>),
|
||||
Document(Arc<Locked<DocumentRule>>),
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
|
@ -321,12 +323,24 @@ pub enum CssRuleType {
|
|||
CounterStyle = 11,
|
||||
// https://drafts.csswg.org/css-conditional-3/#extentions-to-cssrule-interface
|
||||
Supports = 12,
|
||||
// https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#extentions-to-cssrule-interface
|
||||
Document = 13,
|
||||
// https://drafts.csswg.org/css-fonts-3/#om-fontfeaturevalues
|
||||
FontFeatureValues = 14,
|
||||
// https://drafts.csswg.org/css-device-adapt/#css-rule-interface
|
||||
Viewport = 15,
|
||||
}
|
||||
|
||||
/// Result type for with_nested_rules_mq_and_doc_rule()
|
||||
pub enum NestedRulesResult<'a> {
|
||||
/// Only rules
|
||||
Rules(&'a [CssRule]),
|
||||
/// Rules with media queries
|
||||
RulesWithMediaQueries(&'a [CssRule], &'a MediaList),
|
||||
/// Rules with document rule
|
||||
RulesWithDocument(&'a [CssRule], &'a DocumentRule)
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub enum SingleRuleParseError {
|
||||
Syntax,
|
||||
|
@ -347,6 +361,7 @@ impl CssRule {
|
|||
CssRule::Viewport(_) => CssRuleType::Viewport,
|
||||
CssRule::Supports(_) => CssRuleType::Supports,
|
||||
CssRule::Page(_) => CssRuleType::Page,
|
||||
CssRule::Document(_) => CssRuleType::Document,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,8 +380,8 @@ impl CssRule {
|
|||
/// used for others.
|
||||
///
|
||||
/// This will not recurse down unsupported @supports rules
|
||||
pub fn with_nested_rules_and_mq<F, R>(&self, guard: &SharedRwLockReadGuard, mut f: F) -> R
|
||||
where F: FnMut(&[CssRule], Option<&MediaList>) -> R {
|
||||
pub fn with_nested_rules_mq_and_doc_rule<F, R>(&self, guard: &SharedRwLockReadGuard, mut f: F) -> R
|
||||
where F: FnMut(NestedRulesResult) -> R {
|
||||
match *self {
|
||||
CssRule::Import(ref lock) => {
|
||||
let rule = lock.read_with(guard);
|
||||
|
@ -374,7 +389,7 @@ impl CssRule {
|
|||
let rules = rule.stylesheet.rules.read_with(guard);
|
||||
// FIXME(emilio): Include the nested rules if the stylesheet is
|
||||
// loaded.
|
||||
f(&rules.0, Some(&media))
|
||||
f(NestedRulesResult::RulesWithMediaQueries(&rules.0, &media))
|
||||
}
|
||||
CssRule::Namespace(_) |
|
||||
CssRule::Style(_) |
|
||||
|
@ -383,22 +398,31 @@ impl CssRule {
|
|||
CssRule::Viewport(_) |
|
||||
CssRule::Keyframes(_) |
|
||||
CssRule::Page(_) => {
|
||||
f(&[], None)
|
||||
f(NestedRulesResult::Rules(&[]))
|
||||
}
|
||||
CssRule::Media(ref lock) => {
|
||||
let media_rule = lock.read_with(guard);
|
||||
let mq = media_rule.media_queries.read_with(guard);
|
||||
let rules = &media_rule.rules.read_with(guard).0;
|
||||
f(rules, Some(&mq))
|
||||
f(NestedRulesResult::RulesWithMediaQueries(rules, &mq))
|
||||
}
|
||||
CssRule::Supports(ref lock) => {
|
||||
let supports_rule = lock.read_with(guard);
|
||||
let enabled = supports_rule.enabled;
|
||||
if enabled {
|
||||
let rules = &supports_rule.rules.read_with(guard).0;
|
||||
f(rules, None)
|
||||
f(NestedRulesResult::Rules(rules))
|
||||
} else {
|
||||
f(&[], None)
|
||||
f(NestedRulesResult::Rules(&[]))
|
||||
}
|
||||
}
|
||||
CssRule::Document(ref lock) => {
|
||||
if cfg!(feature = "gecko") {
|
||||
let document_rule = lock.read_with(guard);
|
||||
let rules = &document_rule.rules.read_with(guard).0;
|
||||
f(NestedRulesResult::RulesWithDocument(rules, &document_rule))
|
||||
} else {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,6 +484,7 @@ impl ToCssWithGuard for CssRule {
|
|||
CssRule::Media(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||
CssRule::Supports(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||
CssRule::Page(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||
CssRule::Document(ref lock) => lock.read_with(guard).to_css(guard, dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,6 +679,29 @@ impl ToCssWithGuard for StyleRule {
|
|||
#[cfg(feature = "servo")]
|
||||
pub type FontFaceRule = FontFaceRuleData;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A @-moz-document rule
|
||||
pub struct DocumentRule {
|
||||
/// The parsed condition
|
||||
pub condition: DocumentCondition,
|
||||
/// Child rules
|
||||
pub rules: Arc<Locked<CssRules>>,
|
||||
}
|
||||
|
||||
impl ToCssWithGuard for DocumentRule {
|
||||
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write {
|
||||
try!(dest.write_str("@-moz-document "));
|
||||
try!(self.condition.to_css(dest));
|
||||
try!(dest.write_str(" {"));
|
||||
for rule in self.rules.read_with(guard).0.iter() {
|
||||
try!(dest.write_str(" "));
|
||||
try!(rule.to_css(guard, dest));
|
||||
}
|
||||
dest.write_str(" }")
|
||||
}
|
||||
}
|
||||
|
||||
impl Stylesheet {
|
||||
/// Updates an empty stylesheet from a given string of text.
|
||||
pub fn update_from_str(existing: &Stylesheet,
|
||||
|
@ -820,12 +868,24 @@ fn effective_rules<F>(rules: &[CssRule],
|
|||
{
|
||||
for rule in rules {
|
||||
f(rule);
|
||||
rule.with_nested_rules_and_mq(guard, |rules, mq| {
|
||||
if let Some(media_queries) = mq {
|
||||
if !media_queries.evaluate(device, quirks_mode) {
|
||||
return
|
||||
}
|
||||
}
|
||||
rule.with_nested_rules_mq_and_doc_rule(guard, |result| {
|
||||
let rules = match result {
|
||||
NestedRulesResult::Rules(rules) => {
|
||||
rules
|
||||
},
|
||||
NestedRulesResult::RulesWithMediaQueries(rules, media_queries) => {
|
||||
if !media_queries.evaluate(device, quirks_mode) {
|
||||
return;
|
||||
}
|
||||
rules
|
||||
},
|
||||
NestedRulesResult::RulesWithDocument(rules, doc_rule) => {
|
||||
if !doc_rule.condition.evaluate(device) {
|
||||
return;
|
||||
}
|
||||
rules
|
||||
},
|
||||
};
|
||||
effective_rules(rules, device, quirks_mode, guard, f)
|
||||
})
|
||||
}
|
||||
|
@ -859,6 +919,7 @@ rule_filter! {
|
|||
effective_keyframes_rules(Keyframes => KeyframesRule),
|
||||
effective_supports_rules(Supports => SupportsRule),
|
||||
effective_page_rules(Page => PageRule),
|
||||
effective_document_rules(Document => DocumentRule),
|
||||
}
|
||||
|
||||
/// The stylesheet loader is the abstraction used to trigger network requests
|
||||
|
@ -948,6 +1009,8 @@ enum AtRulePrelude {
|
|||
Keyframes(KeyframesName, Option<VendorPrefix>),
|
||||
/// A @page rule prelude.
|
||||
Page,
|
||||
/// A @document rule, with its conditional.
|
||||
Document(DocumentCondition),
|
||||
}
|
||||
|
||||
|
||||
|
@ -1171,6 +1234,14 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
Err(())
|
||||
}
|
||||
},
|
||||
"-moz-document" => {
|
||||
if cfg!(feature = "gecko") {
|
||||
let cond = DocumentCondition::parse(self.context, input)?;
|
||||
Ok(AtRuleType::WithBlock(AtRulePrelude::Document(cond)))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -1221,6 +1292,16 @@ impl<'a, 'b> AtRuleParser for NestedRuleParser<'a, 'b> {
|
|||
Arc::new(self.shared_lock.wrap(declarations))
|
||||
)))))
|
||||
}
|
||||
AtRulePrelude::Document(cond) => {
|
||||
if cfg!(feature = "gecko") {
|
||||
Ok(CssRule::Document(Arc::new(self.shared_lock.wrap(DocumentRule {
|
||||
condition: cond,
|
||||
rules: self.parse_nested_rules(input, CssRuleType::Document),
|
||||
}))))
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ use std::marker::PhantomData;
|
|||
use style_traits::viewport::ViewportConstraints;
|
||||
use stylearc::Arc;
|
||||
use stylesheets::{CssRule, FontFaceRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
|
||||
#[cfg(feature = "servo")]
|
||||
use stylesheets::NestedRulesResult;
|
||||
use thread_state;
|
||||
use viewport::{self, MaybeNew, ViewportRule};
|
||||
|
||||
|
@ -596,12 +598,23 @@ impl Stylist {
|
|||
fn mq_eval_changed(guard: &SharedRwLockReadGuard, rules: &[CssRule],
|
||||
before: &Device, after: &Device, quirks_mode: QuirksMode) -> bool {
|
||||
for rule in rules {
|
||||
let changed = rule.with_nested_rules_and_mq(guard, |rules, mq| {
|
||||
if let Some(mq) = mq {
|
||||
if mq.evaluate(before, quirks_mode) != mq.evaluate(after, quirks_mode) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
let changed = rule.with_nested_rules_mq_and_doc_rule(guard,
|
||||
|result| {
|
||||
let rules = match result {
|
||||
NestedRulesResult::Rules(rules) => rules,
|
||||
NestedRulesResult::RulesWithMediaQueries(rules, mq) => {
|
||||
if mq.evaluate(before, quirks_mode) != mq.evaluate(after, quirks_mode) {
|
||||
return true;
|
||||
}
|
||||
rules
|
||||
},
|
||||
NestedRulesResult::RulesWithDocument(rules, doc_rule) => {
|
||||
if !doc_rule.condition.evaluate(before) {
|
||||
return false;
|
||||
}
|
||||
rules
|
||||
},
|
||||
};
|
||||
mq_eval_changed(guard, rules, before, after, quirks_mode)
|
||||
});
|
||||
if changed {
|
||||
|
|
|
@ -20,6 +20,7 @@ cssparser = "0.13"
|
|||
env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
|
||||
libc = "0.2"
|
||||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
nsstring_vendor = {path = "../../components/style/gecko_bindings/nsstring_vendor"}
|
||||
parking_lot = "0.3"
|
||||
selectors = {path = "../../components/selectors"}
|
||||
style = {path = "../../components/style", features = ["gecko"]}
|
||||
|
|
|
@ -13,7 +13,7 @@ use style::media_queries::*;
|
|||
use style::servo::media_queries::*;
|
||||
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
|
||||
use style::stylearc::Arc;
|
||||
use style::stylesheets::{Stylesheet, Origin, CssRule};
|
||||
use style::stylesheets::{Stylesheet, Origin, CssRule, NestedRulesResult};
|
||||
use style::values::specified;
|
||||
use style_traits::ToCss;
|
||||
|
||||
|
@ -52,11 +52,16 @@ fn media_queries<F>(guard: &SharedRwLockReadGuard, rules: &[CssRule], f: &mut F)
|
|||
where F: FnMut(&MediaList),
|
||||
{
|
||||
for rule in rules {
|
||||
rule.with_nested_rules_and_mq(guard, |rules, mq| {
|
||||
if let Some(mq) = mq {
|
||||
f(mq)
|
||||
rule.with_nested_rules_mq_and_doc_rule(guard, |result| {
|
||||
match result {
|
||||
NestedRulesResult::Rules(rules) |
|
||||
NestedRulesResult::RulesWithDocument(rules, _) => {
|
||||
media_queries(guard, rules, f)
|
||||
},
|
||||
NestedRulesResult::RulesWithMediaQueries(_, mq) => {
|
||||
f(mq)
|
||||
}
|
||||
}
|
||||
media_queries(guard, rules, f)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue