Add @supports -moz-bool-pref() support for stylo.

This commit is contained in:
Xidorn Quan 2017-12-08 11:29:54 -06:00
parent 07bd84ecc8
commit d2042d7ed1
2 changed files with 52 additions and 1 deletions

View file

@ -1595,4 +1595,6 @@ extern "C" {
pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ; pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ;
} extern "C" { } extern "C" {
pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ; pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ;
} extern "C" {
pub fn Gecko_GetBoolPrefValue ( pref_name : * const :: std :: os :: raw :: c_char , ) -> bool ;
} }

View file

@ -13,7 +13,10 @@ use properties::{PropertyId, PropertyDeclaration, SourcePropertyDeclaration};
use selectors::parser::SelectorParseErrorKind; use selectors::parser::SelectorParseErrorKind;
use servo_arc::Arc; use servo_arc::Arc;
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard}; use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
#[allow(unused_imports)] use std::ascii::AsciiExt;
use std::ffi::{CStr, CString};
use std::fmt; use std::fmt;
use std::str;
use style_traits::{ToCss, ParseError}; use style_traits::{ToCss, ParseError};
use stylesheets::{CssRuleType, CssRules}; use stylesheets::{CssRuleType, CssRules};
@ -83,6 +86,10 @@ pub enum SupportsCondition {
Or(Vec<SupportsCondition>), Or(Vec<SupportsCondition>),
/// `property-ident: value` (value can be any tokens) /// `property-ident: value` (value can be any tokens)
Declaration(Declaration), Declaration(Declaration),
/// `-moz-bool-pref("pref-name")`
/// Since we need to pass it through FFI to get the pref value,
/// we store it as CString directly.
MozBoolPref(CString),
/// `(any tokens)` or `func(any tokens)` /// `(any tokens)` or `func(any tokens)`
FutureSyntax(String), FutureSyntax(String),
} }
@ -145,7 +152,26 @@ impl SupportsCondition {
return nested; return nested;
} }
} }
Token::Function(_) => {} Token::Function(ident) => {
// Although this is an internal syntax, it is not necessary to check
// parsing context as far as we accept any unexpected token as future
// syntax, and evaluate it to false when not in chrome / ua sheet.
// See https://drafts.csswg.org/css-conditional-3/#general_enclosed
if ident.eq_ignore_ascii_case("-moz-bool-pref") {
if let Ok(name) = input.try(|i| {
i.parse_nested_block(|i| {
i.expect_string()
.map(|s| s.to_string())
.map_err(CssParseError::<()>::from)
}).and_then(|s| {
CString::new(s)
.map_err(|_| location.new_custom_error(()))
})
}) {
return Ok(SupportsCondition::MozBoolPref(name));
}
}
}
t => return Err(location.new_unexpected_token_error(t)), t => return Err(location.new_unexpected_token_error(t)),
} }
input.parse_nested_block(|i| consume_any_value(i))?; input.parse_nested_block(|i| consume_any_value(i))?;
@ -160,11 +186,27 @@ impl SupportsCondition {
SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)), SupportsCondition::And(ref vec) => vec.iter().all(|c| c.eval(cx)),
SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)), SupportsCondition::Or(ref vec) => vec.iter().any(|c| c.eval(cx)),
SupportsCondition::Declaration(ref decl) => decl.eval(cx), SupportsCondition::Declaration(ref decl) => decl.eval(cx),
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
SupportsCondition::FutureSyntax(_) => false SupportsCondition::FutureSyntax(_) => false
} }
} }
} }
#[cfg(feature = "gecko")]
fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool {
use gecko_bindings::bindings;
use stylesheets::Origin;
if cx.stylesheet_origin != Origin::UserAgent && !cx.chrome_rules_enabled() {
return false;
}
unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) }
}
#[cfg(feature = "servo")]
fn eval_moz_bool_pref(_: &CStr, _: &ParserContext) -> bool {
false
}
/// supports_condition | declaration /// supports_condition | declaration
/// <https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext> /// <https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext>
pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>) pub fn parse_condition_or_declaration<'i, 't>(input: &mut Parser<'i, 't>)
@ -217,6 +259,13 @@ impl ToCss for SupportsCondition {
decl.to_css(dest)?; decl.to_css(dest)?;
dest.write_str(")") dest.write_str(")")
} }
SupportsCondition::MozBoolPref(ref name) => {
dest.write_str("-moz-bool-pref(")?;
let name = str::from_utf8(name.as_bytes())
.expect("Should be parsed from valid UTF-8");
name.to_css(dest)?;
dest.write_str(")")
}
SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s), SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s),
} }
} }