diff --git a/components/script/dom/css.rs b/components/script/dom/css.rs index adc542bd3a47..0e4a7f85065e 100644 --- a/components/script/dom/css.rs +++ b/components/script/dom/css.rs @@ -9,7 +9,7 @@ use dom::bindings::reflector::Reflector; use dom::bindings::str::DOMString; use dom::window::Window; use dom_struct::dom_struct; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::stylesheets::CssRuleType; use style::supports::{Declaration, parse_condition_or_declaration}; @@ -30,7 +30,8 @@ impl CSS { pub fn Supports(win: &Window, property: DOMString, value: DOMString) -> bool { let decl = Declaration { prop: property.into(), val: value.into() }; let url = win.Document().url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports), + LengthParsingMode::Default); decl.eval(&context) } @@ -40,7 +41,8 @@ impl CSS { let cond = parse_condition_or_declaration(&mut input); if let Ok(cond) = cond { let url = win.Document().url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports), + LengthParsingMode::Default); cond.eval(&context) } else { false diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs index a151ee81cec5..aff12e2e2ad0 100644 --- a/components/script/dom/cssmediarule.rs +++ b/components/script/dom/cssmediarule.rs @@ -16,7 +16,7 @@ use dom::window::Window; use dom_struct::dom_struct; use std::sync::Arc; use style::media_queries::parse_media_query_list; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{Locked, ToCssWithGuard}; use style::stylesheets::{CssRuleType, MediaRule}; use style_traits::ToCss; @@ -72,7 +72,8 @@ impl CSSMediaRule { let global = self.global(); let win = global.as_window(); let url = win.get_url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); let new_medialist = parse_media_query_list(&context, &mut input); let mut guard = self.cssconditionrule.shared_lock().write(); diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs index bad93e621b56..3ac60a00e06a 100644 --- a/components/script/dom/csssupportsrule.rs +++ b/components/script/dom/csssupportsrule.rs @@ -14,7 +14,7 @@ use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; use std::sync::Arc; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{Locked, ToCssWithGuard}; use style::stylesheets::{CssRuleType, SupportsRule}; use style::supports::SupportsCondition; @@ -61,7 +61,8 @@ impl CSSSupportsRule { let global = self.global(); let win = global.as_window(); let url = win.Document().url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Supports), + LengthParsingMode::Default); let enabled = cond.eval(&context); let mut guard = self.cssconditionrule.shared_lock().write(); let rule = self.supportsrule.write_with(&mut guard); diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 28f72832e9ab..c0d0d12a7757 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -33,7 +33,7 @@ use std::default::Default; use std::sync::Arc; use style::attr::AttrValue; use style::media_queries::parse_media_query_list; -use style::parser::ParserContext as CssParserContext; +use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; use style::str::HTML_SPACE_CHARACTERS; use style::stylesheets::{CssRuleType, Stylesheet}; use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner}; @@ -281,7 +281,8 @@ impl HTMLLinkElement { let mut css_parser = CssParser::new(&mq_str); let win = document.window(); let doc_url = document.url(); - let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media)); + let context = CssParserContext::new_for_cssom(&doc_url, win.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); let media = parse_media_query_list(&context, &mut css_parser); let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity")); diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index c0f2e5b4e796..0c026fcfe9a2 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -25,7 +25,7 @@ use script_layout_interface::message::Msg; use std::cell::Cell; use std::sync::Arc; use style::media_queries::parse_media_query_list; -use style::parser::ParserContext as CssParserContext; +use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; @@ -87,7 +87,8 @@ impl HTMLStyleElement { let url = win.get_url(); let context = CssParserContext::new_for_cssom(&url, win.css_error_reporter(), - Some(CssRuleType::Media)); + Some(CssRuleType::Media), + LengthParsingMode::Default); let shared_lock = node.owner_doc().style_shared_lock().clone(); let mq = Arc::new(shared_lock.wrap( parse_media_query_list(&context, &mut CssParser::new(&mq_str)))); diff --git a/components/script/dom/medialist.rs b/components/script/dom/medialist.rs index da10d5d2a147..134e3a3f270a 100644 --- a/components/script/dom/medialist.rs +++ b/components/script/dom/medialist.rs @@ -15,7 +15,7 @@ use dom_struct::dom_struct; use std::sync::Arc; use style::media_queries::{MediaQuery, parse_media_query_list}; use style::media_queries::MediaList as StyleMediaList; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{SharedRwLock, Locked}; use style::stylesheets::CssRuleType; use style_traits::ToCss; @@ -75,7 +75,8 @@ impl MediaListMethods for MediaList { let global = self.global(); let win = global.as_window(); let url = win.get_url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); *media_queries = parse_media_query_list(&context, &mut parser); } @@ -108,7 +109,8 @@ impl MediaListMethods for MediaList { let global = self.global(); let win = global.as_window(); let url = win.get_url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); let m = MediaQuery::parse(&context, &mut parser); // Step 2 if let Err(_) = m { @@ -133,7 +135,8 @@ impl MediaListMethods for MediaList { let global = self.global(); let win = global.as_window(); let url = win.get_url(); - let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(&url, win.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); let m = MediaQuery::parse(&context, &mut parser); // Step 2 if let Err(_) = m { diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index ac39049b8dda..0c8ea1a6594b 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -105,7 +105,7 @@ use std::sync::mpsc::TryRecvError::{Disconnected, Empty}; use style::context::ReflowGoal; use style::error_reporting::ParseErrorReporter; use style::media_queries; -use style::parser::ParserContext as CssParserContext; +use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; use style::properties::PropertyId; use style::properties::longhands::overflow_x; use style::selector_parser::PseudoElement; @@ -972,7 +972,8 @@ impl WindowMethods for Window { fn MatchMedia(&self, query: DOMString) -> Root { let mut parser = Parser::new(&query); let url = self.get_url(); - let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media)); + let context = CssParserContext::new_for_cssom(&url, self.css_error_reporter(), Some(CssRuleType::Media), + LengthParsingMode::Default); let media_query_list = media_queries::parse_media_query_list(&context, &mut parser); let document = self.Document(); let mql = MediaQueryList::new(&document, media_query_list); diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index cc8a9229b855..49f2cad25b78 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -8,7 +8,7 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule}; -use parser::{ParserContext, log_css_error}; +use parser::{LengthParsingMode, ParserContext, log_css_error}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId}; use properties::{PropertyDeclarationId, LonghandId, ParsedDeclaration}; use properties::LonghandIdSet; @@ -129,7 +129,8 @@ impl Keyframe { let context = ParserContext::new(parent_stylesheet.origin, &parent_stylesheet.url_data, &error_reporter, - Some(CssRuleType::Keyframe)); + Some(CssRuleType::Keyframe), + LengthParsingMode::Default); let mut input = Parser::new(css); let mut rule_parser = KeyframeListParser { diff --git a/components/style/parser.rs b/components/style/parser.rs index ff650062e147..b82d21ace4f2 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -11,6 +11,24 @@ use error_reporting::ParseErrorReporter; use style_traits::OneOrMoreCommaSeparated; use stylesheets::{CssRuleType, Origin, UrlExtraData}; +/// The mode to use when parsing lengths. +#[derive(PartialEq, Eq, Copy, Clone)] +pub enum LengthParsingMode { + /// In CSS, lengths must have units, except for zero values, where the unit can be omitted. + /// https://www.w3.org/TR/css3-values/#lengths + Default, + /// In SVG, a coordinate or length value without a unit identifier (e.g., "25") is assumed to be in user units (px). + /// https://www.w3.org/TR/SVG/coords.html#Units + SVG, +} + +impl LengthParsingMode { + /// Whether the parsing mode allows unitless lengths for non-zero values to be intpreted as px. + pub fn allows_unitless_lengths(&self) -> bool { + *self == LengthParsingMode::SVG + } +} + /// The data that the parser needs from outside in order to parse a stylesheet. pub struct ParserContext<'a> { /// The `Origin` of the stylesheet, whether it's a user, author or @@ -22,8 +40,10 @@ pub struct ParserContext<'a> { pub error_reporter: &'a ParseErrorReporter, /// The current rule type, if any. pub rule_type: Option, - /// line number offsets for inline stylesheets + /// Line number offsets for inline stylesheets pub line_number_offset: u64, + /// The mode to use when parsing lengths. + pub length_parsing_mode: LengthParsingMode, } impl<'a> ParserContext<'a> { @@ -31,7 +51,8 @@ impl<'a> ParserContext<'a> { pub fn new(stylesheet_origin: Origin, url_data: &'a UrlExtraData, error_reporter: &'a ParseErrorReporter, - rule_type: Option) + rule_type: Option, + length_parsing_mode: LengthParsingMode) -> ParserContext<'a> { ParserContext { stylesheet_origin: stylesheet_origin, @@ -39,15 +60,17 @@ impl<'a> ParserContext<'a> { error_reporter: error_reporter, rule_type: rule_type, line_number_offset: 0u64, + length_parsing_mode: length_parsing_mode, } } /// Create a parser context for on-the-fly parsing in CSSOM pub fn new_for_cssom(url_data: &'a UrlExtraData, error_reporter: &'a ParseErrorReporter, - rule_type: Option) + rule_type: Option, + length_parsing_mode: LengthParsingMode) -> ParserContext<'a> { - Self::new(Origin::Author, url_data, error_reporter, rule_type) + Self::new(Origin::Author, url_data, error_reporter, rule_type, length_parsing_mode) } /// Create a parser context based on a previous context, but with a modified rule type. @@ -60,19 +83,16 @@ impl<'a> ParserContext<'a> { error_reporter: context.error_reporter, rule_type: rule_type, line_number_offset: context.line_number_offset, + length_parsing_mode: context.length_parsing_mode, } } - /// Get the rule type, which assumes that one is available. - pub fn rule_type(&self) -> CssRuleType { - self.rule_type.expect("Rule type expected, but none was found.") - } - /// Create a parser context for inline CSS which accepts additional line offset argument. pub fn new_with_line_number_offset(stylesheet_origin: Origin, url_data: &'a UrlExtraData, error_reporter: &'a ParseErrorReporter, - line_number_offset: u64) + line_number_offset: u64, + length_parsing_mode: LengthParsingMode) -> ParserContext<'a> { ParserContext { stylesheet_origin: stylesheet_origin, @@ -80,8 +100,14 @@ impl<'a> ParserContext<'a> { error_reporter: error_reporter, rule_type: None, line_number_offset: line_number_offset, + length_parsing_mode: length_parsing_mode, } } + + /// Get the rule type, which assumes that one is available. + pub fn rule_type(&self) -> CssRuleType { + self.rule_type.expect("Rule type expected, but none was found.") + } } /// Defaults to a no-op. diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 09448ab67f96..1eaa49321f36 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -9,7 +9,7 @@ use cssparser::{DeclarationListParser, parse_important}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter}; use error_reporting::ParseErrorReporter; -use parser::{ParserContext, log_css_error}; +use parser::{LengthParsingMode, ParserContext, log_css_error}; use std::fmt; use style_traits::ToCss; use stylesheets::{CssRuleType, Origin, UrlExtraData}; @@ -617,7 +617,11 @@ pub fn parse_style_attribute(input: &str, url_data: &UrlExtraData, error_reporter: &ParseErrorReporter) -> PropertyDeclarationBlock { - let context = ParserContext::new(Origin::Author, url_data, error_reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, + url_data, + error_reporter, + Some(CssRuleType::Style), + LengthParsingMode::Default); parse_property_declaration_list(&context, &mut Parser::new(input)) } @@ -631,7 +635,11 @@ pub fn parse_one_declaration(id: PropertyId, url_data: &UrlExtraData, error_reporter: &ParseErrorReporter) -> Result { - let context = ParserContext::new(Origin::Author, url_data, error_reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, + url_data, + error_reporter, + Some(CssRuleType::Style), + LengthParsingMode::Default); Parser::new(input).parse_entirely(|parser| { ParsedDeclaration::parse(id, &context, parser) .map_err(|_| ()) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index bdbb09bdfcca..9f5e6816fee9 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -27,7 +27,7 @@ use font_metrics::FontMetricsProvider; #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide}; use logical_geometry::WritingMode; use media_queries::Device; -use parser::{Parse, ParserContext}; +use parser::{LengthParsingMode, Parse, ParserContext}; use properties::animated_properties::TransitionProperty; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; use shared_lock::StylesheetGuards; @@ -369,7 +369,11 @@ impl PropertyDeclarationIdSet { // // FIXME(pcwalton): Cloning the error reporter is slow! But so are custom // properties, so whatever... - let context = ParserContext::new(Origin::Author, url_data, error_reporter, None); + let context = ParserContext::new(Origin::Author, + url_data, + error_reporter, + None, + LengthParsingMode::Default); Parser::new(&css).parse_entirely(|input| { match from_shorthand { None => { diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index ec7bb9812043..53abf04ef691 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -23,7 +23,7 @@ use gecko_bindings::sugar::refptr::RefPtr; use keyframes::{Keyframe, parse_keyframe_list}; use media_queries::{Device, MediaList, parse_media_query_list}; use parking_lot::RwLock; -use parser::{Parse, ParserContext, log_css_error}; +use parser::{LengthParsingMode, Parse, ParserContext, log_css_error}; use properties::{PropertyDeclarationBlock, parse_property_declaration_list}; use selector_parser::{SelectorImpl, SelectorParser}; use selectors::parser::SelectorList; @@ -422,7 +422,8 @@ impl CssRule { let context = ParserContext::new(parent_stylesheet.origin, &parent_stylesheet.url_data, &error_reporter, - None); + None, + LengthParsingMode::Default); let mut input = Parser::new(css); // nested rules are in the body state @@ -695,7 +696,7 @@ impl Stylesheet { shared_lock: shared_lock, loader: stylesheet_loader, context: ParserContext::new_with_line_number_offset(origin, url_data, error_reporter, - line_number_offset), + line_number_offset, LengthParsingMode::Default), state: Cell::new(State::Start), }; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 2b75201e0a02..4c4c46966368 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -551,7 +551,12 @@ impl Length { match try!(input.next()) { Token::Dimension(ref value, ref unit) if num_context.is_ok(value.value) => Length::parse_dimension(context, value.value, unit), - Token::Number(ref value) if value.value == 0. => Ok(Length::zero()), + Token::Number(ref value) => { + if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() { + return Err(()) + } + Ok(Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(value.value)))) + }, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => input.parse_nested_block(|input| { CalcLengthOrPercentage::parse_length(context, input, num_context) diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 0d0d2379d77a..b3ee9f14374d 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -1003,7 +1003,8 @@ pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const let url_data = unsafe { RefPtr::from_ptr_ref(&data) }; let reporter = StdoutErrorReporter; - let context = ParserContext::new(Origin::Author, url_data, &reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, url_data, &reporter, + Some(CssRuleType::Style), LengthMode::Default); match ParsedDeclaration::parse(id, &context, &mut Parser::new(value)) { Ok(parsed) => { @@ -1025,7 +1026,8 @@ pub extern "C" fn Servo_ParseEasing(easing: *const nsAString, let url_data = unsafe { RefPtr::from_ptr_ref(&data) }; let reporter = StdoutErrorReporter; - let context = ParserContext::new(Origin::Author, url_data, &reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, url_data, &reporter, + Some(CssRuleType::Style), LengthMode::Default); let easing = unsafe { (*easing).to_string() }; match transition_timing_function::single_value::parse(&context, &mut Parser::new(&easing)) { Ok(parsed_easing) => { @@ -1246,7 +1248,7 @@ pub extern "C" fn Servo_MediaList_SetText(list: RawServoMediaListBorrowed, text: let mut parser = Parser::new(&text); let url_data = unsafe { dummy_url_data() }; let reporter = StdoutErrorReporter; - let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media), LengthMode::Default); write_locked_arc(list, |list: &mut MediaList| { *list = parse_media_query_list(&context, &mut parser); }) @@ -1276,7 +1278,7 @@ pub extern "C" fn Servo_MediaList_AppendMedium(list: RawServoMediaListBorrowed, let new_medium = unsafe { new_medium.as_ref().unwrap().as_str_unchecked() }; let url_data = unsafe { dummy_url_data() }; let reporter = StdoutErrorReporter; - let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media), LengthMode::Default); write_locked_arc(list, |list: &mut MediaList| { list.append_medium(&context, new_medium); }) @@ -1288,7 +1290,7 @@ pub extern "C" fn Servo_MediaList_DeleteMedium(list: RawServoMediaListBorrowed, let old_medium = unsafe { old_medium.as_ref().unwrap().as_str_unchecked() }; let url_data = unsafe { dummy_url_data() }; let reporter = StdoutErrorReporter; - let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media)); + let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Media), LengthMode::Default); write_locked_arc(list, |list: &mut MediaList| list.delete_medium(&context, old_medium)) } @@ -1639,7 +1641,8 @@ pub extern "C" fn Servo_DeclarationBlock_SetBackgroundImage(declarations: let url_data = unsafe { RefPtr::from_ptr_ref(&raw_extra_data) }; let string = unsafe { (*value).to_string() }; let error_reporter = StdoutErrorReporter; - let context = ParserContext::new(Origin::Author, url_data, &error_reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, url_data, &error_reporter, + Some(CssRuleType::Style), LengthMode::Default); if let Ok(url) = SpecifiedUrl::parse_from_string(string.into(), &context) { let decl = PropertyDeclaration::BackgroundImage(BackgroundImage( vec![SingleBackgroundImage( @@ -1688,7 +1691,7 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool { if let Ok(cond) = cond { let url_data = unsafe { dummy_url_data() }; let reporter = StdoutErrorReporter; - let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Style)); + let context = ParserContext::new_for_cssom(url_data, &reporter, Some(CssRuleType::Style), LengthMode::Default); cond.eval(&context) } else { false diff --git a/tests/unit/style/parsing/length.rs b/tests/unit/style/parsing/length.rs index bc94ab5ba917..ad0b77d2e01b 100644 --- a/tests/unit/style/parsing/length.rs +++ b/tests/unit/style/parsing/length.rs @@ -5,9 +5,9 @@ use cssparser::Parser; use media_queries::CSSErrorReporterTest; use parsing::parse; -use style::parser::{Parse, ParserContext}; +use style::parser::{LengthParsingMode, Parse, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; -use style::values::specified::length::Length; +use style::values::specified::length::{AbsoluteLength, Length, NoCalcLength}; use style_traits::ToCss; #[test] @@ -28,3 +28,19 @@ fn test_length_literals() { assert_roundtrip_with_context!(Length::parse, "0.33pt", "0.33pt"); assert_roundtrip_with_context!(Length::parse, "0.33pc", "0.33pc"); } + +#[test] +fn test_length_parsing_modes() { + // In default length mode, non-zero lengths must have a unit. + assert!(parse(Length::parse, "1").is_err()); + + // In SVG length mode, non-zero lengths are assumed to be px. + let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap(); + let reporter = CSSErrorReporterTest; + let context = ParserContext::new(Origin::Author, &url, &reporter, + Some(CssRuleType::Style), LengthParsingMode::SVG); + let mut parser = Parser::new("1"); + let result = Length::parse(&context, &mut parser); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Length::NoCalc(NoCalcLength::Absolute(AbsoluteLength::Px(1.)))); +} diff --git a/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs index 48a08ff10738..bf641e625d67 100644 --- a/tests/unit/style/parsing/mod.rs +++ b/tests/unit/style/parsing/mod.rs @@ -6,13 +6,14 @@ use cssparser::Parser; use media_queries::CSSErrorReporterTest; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; fn parse Result>(f: F, s: &str) -> Result { let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap(); let reporter = CSSErrorReporterTest; - let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Style), + LengthParsingMode::Default); let mut parser = Parser::new(s); f(&context, &mut parser) } diff --git a/tests/unit/style/properties/mod.rs b/tests/unit/style/properties/mod.rs index 8836d96d0d04..68aae4daccaf 100644 --- a/tests/unit/style/properties/mod.rs +++ b/tests/unit/style/properties/mod.rs @@ -4,13 +4,14 @@ use cssparser::Parser; use media_queries::CSSErrorReporterTest; -use style::parser::ParserContext; +use style::parser::{LengthParsingMode, ParserContext}; use style::stylesheets::{CssRuleType, Origin}; fn parse Result>(f: F, s: &str) -> Result { let url = ::servo_url::ServoUrl::parse("http://localhost").unwrap(); let reporter = CSSErrorReporterTest; - let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Style)); + let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Style), + LengthParsingMode::Default); let mut parser = Parser::new(s); f(&context, &mut parser) } diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index 14a68be6115b..150546ee5889 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -9,7 +9,7 @@ use servo_config::prefs::{PREFS, PrefValue}; use servo_url::ServoUrl; use std::sync::Arc; use style::media_queries::{Device, MediaList, MediaType}; -use style::parser::{Parse, ParserContext}; +use style::parser::{LengthParsingMode, Parse, ParserContext}; use style::shared_lock::SharedRwLock; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; use style::values::specified::LengthOrPercentageOrAuto::{self, Auto}; @@ -292,7 +292,8 @@ fn multiple_stylesheets_cascading() { fn constrain_viewport() { let url = ServoUrl::parse("http://localhost").unwrap(); let reporter = CSSErrorReporterTest; - let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Viewport)); + let context = ParserContext::new(Origin::Author, &url, &reporter, Some(CssRuleType::Viewport), + LengthParsingMode::Default); macro_rules! from_css { ($css:expr) => {