Auto merge of #16342 - emilio:media-query-parsing, r=SimonSapin

Fix a few media query parsing bugs.

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16342)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-04-11 10:12:13 -05:00 committed by GitHub
commit df67977704
2 changed files with 25 additions and 13 deletions

View file

@ -409,11 +409,12 @@ impl Expression {
// If there's no colon, this is a media query of the form
// '(<feature>)', that is, there's no value specified.
//
// FIXME(emilio): We need to check for range operators too here when
// we support them, see:
//
// https://drafts.csswg.org/mediaqueries/#mq-ranges
// Gecko doesn't allow ranged expressions without a value, so just
// reject them here too.
if input.try(|i| i.expect_colon()).is_err() {
if range != nsMediaExpression_Range::eEqual {
return Err(())
}
return Ok(Expression::new(feature, None, range));
}

View file

@ -56,10 +56,10 @@ impl ToCss for Qualifier {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
{
match *self {
Qualifier::Not => write!(dest, "not"),
Qualifier::Only => write!(dest, "only"),
}
dest.write_str(match *self {
Qualifier::Not => "not",
Qualifier::Only => "only",
})
}
}
@ -152,15 +152,26 @@ pub enum MediaQueryType {
}
impl MediaQueryType {
fn parse(ident: &str) -> Self {
fn parse(ident: &str) -> Result<Self, ()> {
if ident.eq_ignore_ascii_case("all") {
return MediaQueryType::All;
return Ok(MediaQueryType::All);
}
match MediaType::parse(ident) {
// From https://drafts.csswg.org/mediaqueries/#mq-syntax:
//
// The <media-type> production does not include the keywords only,
// not, and, and or.
if ident.eq_ignore_ascii_case("not") ||
ident.eq_ignore_ascii_case("or") ||
ident.eq_ignore_ascii_case("and") ||
ident.eq_ignore_ascii_case("only") {
return Err(())
}
Ok(match MediaType::parse(ident) {
Some(media_type) => MediaQueryType::Known(media_type),
None => MediaQueryType::Unknown(Atom::from(ident)),
}
})
}
fn matches(&self, other: MediaType) -> bool {
@ -207,7 +218,7 @@ impl MediaQuery {
};
let media_type = match input.try(|input| input.expect_ident()) {
Ok(ident) => MediaQueryType::parse(&*ident),
Ok(ident) => try!(MediaQueryType::parse(&*ident)),
Err(()) => {
// Media type is only optional if qualifier is not specified.
if qualifier.is_some() {