diff --git a/components/style/supports.rs b/components/style/supports.rs index bbbfec9f4fc5..455772a9eedc 100644 --- a/components/style/supports.rs +++ b/components/style/supports.rs @@ -44,7 +44,7 @@ impl SupportsCondition { let (keyword, wrapper) = match input.next() { Err(()) => { // End of input - return Ok(SupportsCondition::Parenthesized(Box::new(in_parens))) + return Ok(in_parens) } Ok(Token::Ident(ident)) => { match_ignore_ascii_case! { ident, @@ -71,6 +71,9 @@ impl SupportsCondition { /// https://drafts.csswg.org/css-conditional-3/#supports_condition_in_parens fn parse_in_parens(input: &mut Parser) -> Result { + // Whitespace is normally taken care of in `Parser::next`, + // but we want to not include it in `pos` for the SupportsCondition::FutureSyntax cases. + while input.try(Parser::expect_whitespace).is_ok() {} let pos = input.position(); match input.next()? { Token::ParenthesisBlock => { @@ -106,9 +109,11 @@ impl SupportsCondition { /// supports_condition | declaration /// https://drafts.csswg.org/css-conditional/#dom-css-supports-conditiontext-conditiontext pub fn parse_condition_or_declaration(input: &mut Parser) -> Result { - input.try(SupportsCondition::parse).or_else(|()| { + if let Ok(condition) = input.try(SupportsCondition::parse) { + Ok(SupportsCondition::Parenthesized(Box::new(condition))) + } else { Declaration::parse(input).map(SupportsCondition::Declaration) - }) + } } impl ToCss for SupportsCondition { @@ -116,9 +121,8 @@ impl ToCss for SupportsCondition { where W: fmt::Write { match *self { SupportsCondition::Not(ref cond) => { - dest.write_str("not (")?; - cond.to_css(dest)?; - dest.write_str(")") + dest.write_str("not ")?; + cond.to_css(dest) } SupportsCondition::Parenthesized(ref cond) => { dest.write_str("(")?; @@ -132,9 +136,7 @@ impl ToCss for SupportsCondition { dest.write_str(" and ")?; } first = false; - dest.write_str("(")?; cond.to_css(dest)?; - dest.write_str(")")?; } Ok(()) } @@ -145,13 +147,15 @@ impl ToCss for SupportsCondition { dest.write_str(" or ")?; } first = false; - dest.write_str("(")?; cond.to_css(dest)?; - dest.write_str(")")?; } Ok(()) } - SupportsCondition::Declaration(ref decl) => decl.to_css(dest), + SupportsCondition::Declaration(ref decl) => { + dest.write_str("(")?; + decl.to_css(dest)?; + dest.write_str(")") + } SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s), } } diff --git a/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs index 1fede915771e..2521f5a9822d 100644 --- a/tests/unit/style/parsing/mod.rs +++ b/tests/unit/style/parsing/mod.rs @@ -39,6 +39,25 @@ macro_rules! assert_roundtrip_with_context { } } +macro_rules! assert_roundtrip { + ($fun:expr, $string:expr) => { + assert_roundtrip!($fun, $string, $string); + }; + ($fun:expr,$input:expr, $output:expr) => { + let mut parser = Parser::new($input); + let parsed = $fun(&mut parser) + .expect(&format!("Failed to parse {}", $input)); + let serialized = ToCss::to_css_string(&parsed); + assert_eq!(serialized, $output); + + let mut parser = Parser::new(&serialized); + let re_parsed = $fun(&mut parser) + .expect(&format!("Failed to parse serialization {}", $input)); + let re_serialized = ToCss::to_css_string(&re_parsed); + assert_eq!(serialized, re_serialized); + } +} + macro_rules! parse_longhand { ($name:ident, $s:expr) => {{ let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap(); @@ -58,3 +77,4 @@ mod inherited_text; mod mask; mod position; mod selectors; +mod supports; diff --git a/tests/unit/style/parsing/supports.rs b/tests/unit/style/parsing/supports.rs new file mode 100644 index 000000000000..b38f1b09bc0d --- /dev/null +++ b/tests/unit/style/parsing/supports.rs @@ -0,0 +1,14 @@ +/* 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/. */ + +use cssparser::Parser; +use style::supports::SupportsCondition; +use style_traits::ToCss; + +#[test] +fn test_supports_condition() { + assert_roundtrip!(SupportsCondition::parse, "(margin: 1px)"); + assert_roundtrip!(SupportsCondition::parse, "not (--be: to be)"); + assert_roundtrip!(SupportsCondition::parse, "(color: blue) and future-extension(4)"); +}