Skip to content

Commit dfcfc1d

Browse files
author
bors-servo
authored
Auto merge of #15278 - atheed:zero-parsing, r=Wafflespeanut
Parsing "0" as Number for line-height and border-image-outset Fixes #15171 by correctly parsing `0` as `0` (rather than as `0px`, as was the case earlier) for the `line-height` and `border-image-outset` CSS properties. Wrote unit tests for both; `./mach test-unit -p style` passes all tests. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #15171 - [X] There are tests for these changes. --- This change is [https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15278)
2 parents 0459e1a + beeca12 commit dfcfc1d

File tree

4 files changed

+69
-18
lines changed

4 files changed

+69
-18
lines changed

components/style/properties/longhand/inherited_text.mako.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,27 @@
4848
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
4949
use cssparser::Token;
5050
use std::ascii::AsciiExt;
51-
input.try(specified::LengthOrPercentage::parse_non_negative)
52-
.map(SpecifiedValue::LengthOrPercentage)
51+
// We try to parse as a Number first because, for 'line-height', we want "0" to be
52+
// parsed as a plain Number rather than a Length (0px); this matches the behaviour
53+
// of all major browsers
54+
input.try(specified::Number::parse_non_negative)
55+
.map(|n| SpecifiedValue::Number(n.0))
5356
.or_else(|()| {
54-
match try!(input.next()) {
55-
Token::Number(ref value) if value.value >= 0. => {
56-
Ok(SpecifiedValue::Number(value.value))
57-
}
58-
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
59-
Ok(SpecifiedValue::Normal)
60-
}
61-
% if product == "gecko":
62-
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
63-
Ok(SpecifiedValue::MozBlockHeight)
57+
input.try(specified::LengthOrPercentage::parse_non_negative)
58+
.map(SpecifiedValue::LengthOrPercentage)
59+
.or_else(|()| {
60+
match try!(input.next()) {
61+
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
62+
Ok(SpecifiedValue::Normal)
63+
}
64+
% if product == "gecko":
65+
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
66+
Ok(SpecifiedValue::MozBlockHeight)
67+
}
68+
% endif
69+
_ => Err(()),
6470
}
65-
% endif
66-
_ => Err(()),
67-
}
71+
})
6872
})
6973
}
7074
pub mod computed_value {

components/style/values/specified/length.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,10 +1196,13 @@ pub type LengthOrNumber = Either;
11961196
impl LengthOrNumber {
11971197
/// Parse a non-negative LengthOrNumber.
11981198
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
1199-
if let Ok(v) = input.try(Length::parse_non_negative) {
1200-
Ok(Either::First(v))
1199+
// We try to parse as a Number first because, for cases like LengthOrNumber,
1200+
// we want "0" to be parsed as a plain Number rather than a Length (0px); this
1201+
// matches the behaviour of all major browsers
1202+
if let Ok(v) = input.try(Number::parse_non_negative) {
1203+
Ok(Either::Second(v))
12011204
} else {
1202-
Number::parse_non_negative(input).map(Either::Second)
1205+
Length::parse_non_negative(input).map(Either::First)
12031206
}
12041207
}
12051208
}

tests/unit/style/parsing/border.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,21 @@ fn border_image_outset_should_error_on_negative_number() {
104104
let result = border_image_outset::parse(&context, &mut parser);
105105
assert_eq!(result, Err(()));
106106
}
107+
108+
#[test]
109+
fn border_image_outset_should_return_number_on_plain_zero() {
110+
let url = ServoUrl::parse("http://localhost").unwrap();
111+
let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
112+
let mut parser = Parser::new("0");
113+
let result = border_image_outset::parse(&context, &mut parser);
114+
assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0"));
115+
}
116+
117+
#[test]
118+
fn border_image_outset_should_return_length_on_length_zero() {
119+
let url = ServoUrl::parse("http://localhost").unwrap();
120+
let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
121+
let mut parser = Parser::new("0em");
122+
let result = border_image_outset::parse(&context, &mut parser);
123+
assert_eq!(result.unwrap(), parse_longhand!(border_image_outset, "0em"));
124+
}

tests/unit/style/parsing/inherited_text.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,29 @@ fn webkit_text_stroke_shorthand_should_parse_properly() {
102102
assert_eq!(result._webkit_text_stroke_color.unwrap(), parse_longhand!(_webkit_text_stroke_color, "red"));
103103
assert_eq!(result._webkit_text_stroke_width.unwrap(), parse_longhand!(_webkit_text_stroke_width, "thin"));
104104
}
105+
106+
#[test]
107+
fn line_height_should_return_number_on_plain_zero() {
108+
use media_queries::CSSErrorReporterTest;
109+
use servo_url::ServoUrl;
110+
use style::properties::longhands::line_height;
111+
112+
let url = ServoUrl::parse("http://localhost").unwrap();
113+
let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
114+
let mut parser = Parser::new("0");
115+
let result = line_height::parse(&context, &mut parser);
116+
assert_eq!(result.unwrap(), parse_longhand!(line_height, "0"));
117+
}
118+
119+
#[test]
120+
fn line_height_should_return_length_on_length_zero() {
121+
use media_queries::CSSErrorReporterTest;
122+
use servo_url::ServoUrl;
123+
use style::properties::longhands::line_height;
124+
125+
let url = ServoUrl::parse("http://localhost").unwrap();
126+
let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
127+
let mut parser = Parser::new("0px");
128+
let result = line_height::parse(&context, &mut parser);
129+
assert_eq!(result.unwrap(), parse_longhand!(line_height, "0px"));
130+
}

0 commit comments

Comments
 (0)