diff --git a/components/style/properties/shorthand/background.mako.rs b/components/style/properties/shorthand/background.mako.rs index 8eaa94772f1..ab19507702f 100644 --- a/components/style/properties/shorthand/background.mako.rs +++ b/components/style/properties/shorthand/background.mako.rs @@ -194,8 +194,8 @@ sub_properties="background-position-x background-position-y" spec="https://drafts.csswg.org/css-backgrounds-4/#the-background-position"> use properties::longhands::{background_position_x,background_position_y}; + use values::specified::AllowQuirks; use values::specified::position::Position; - use parser::Parse; pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result { let mut position_x = background_position_x::SpecifiedValue(Vec::new()); @@ -204,7 +204,7 @@ try!(input.parse_comma_separated(|input| { loop { - if let Ok(value) = input.try(|input| Position::parse(context, input)) { + if let Ok(value) = input.try(|input| Position::parse_quirky(context, input, AllowQuirks::Yes)) { position_x.0.push(value.horizontal); position_y.0.push(value.vertical); any = true; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index ff8bdaa548e..e161b5fc589 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -17,7 +17,7 @@ use std::ops::Mul; use style_traits::ToCss; use style_traits::values::specified::AllowedLengthType; use stylesheets::CssRuleType; -use super::{Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time, ToComputedValue}; +use super::{AllowQuirks, Angle, Number, SimplifiedValueNode, SimplifiedSumNode, Time, ToComputedValue}; use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, HasViewportPercentage, None_, Normal}; use values::ExtremumLength; use values::computed::{ComputedValueAsSpecified, Context}; @@ -1154,7 +1154,10 @@ impl LengthOrPercentage { LengthOrPercentage::Length(NoCalcLength::zero()) } - fn parse_internal(context: &ParserContext, input: &mut Parser, num_context: AllowedLengthType) + fn parse_internal(context: &ParserContext, + input: &mut Parser, + num_context: AllowedLengthType, + allow_quirks: AllowQuirks) -> Result { match try!(input.next()) { @@ -1162,12 +1165,9 @@ impl LengthOrPercentage { NoCalcLength::parse_dimension(context, value.value, unit).map(LengthOrPercentage::Length), Token::Percentage(ref value) if num_context.is_ok(value.unit_value) => Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))), - Token::Number(ref value) => { - if value.value != 0. && !context.length_parsing_mode.allows_unitless_lengths() { - return Err(()) - } - Ok(LengthOrPercentage::Length(NoCalcLength::Absolute(AbsoluteLength::Px(value.value)))) - } + Token::Number(value) if value.value == 0. || + (num_context.is_ok(value.value) && allow_quirks.allowed(context.quirks_mode)) => + Ok(LengthOrPercentage::Length(NoCalcLength::from_px(value.value))), Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { let calc = try!(input.parse_nested_block(|i| { CalcLengthOrPercentage::parse_length_or_percentage(context, i) @@ -1181,14 +1181,14 @@ impl LengthOrPercentage { /// Parse a non-negative length. #[inline] pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result { - Self::parse_internal(context, input, AllowedLengthType::NonNegative) + Self::parse_internal(context, input, AllowedLengthType::NonNegative, AllowQuirks::No) } /// Parse a length, treating dimensionless numbers as pixels /// /// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value pub fn parse_numbers_are_pixels(context: &ParserContext, input: &mut Parser) -> Result { - if let Ok(lop) = input.try(|i| Self::parse_internal(context, i, AllowedLengthType::All)) { + if let Ok(lop) = input.try(|i| Self::parse(context, i)) { return Ok(lop) } @@ -1204,7 +1204,7 @@ impl LengthOrPercentage { pub fn parse_numbers_are_pixels_non_negative(context: &ParserContext, input: &mut Parser) -> Result { - if let Ok(lop) = input.try(|i| Self::parse_internal(context, i, AllowedLengthType::NonNegative)) { + if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) { return Ok(lop) } @@ -1230,7 +1230,18 @@ impl LengthOrPercentage { impl Parse for LengthOrPercentage { #[inline] fn parse(context: &ParserContext, input: &mut Parser) -> Result { - Self::parse_internal(context, input, AllowedLengthType::All) + Self::parse_quirky(context, input, AllowQuirks::No) + } +} + +impl LengthOrPercentage { + /// Parses a length or a percentage, allowing the unitless length quirk. + /// https://quirks.spec.whatwg.org/#the-unitless-length-quirk + #[inline] + pub fn parse_quirky(context: &ParserContext, + input: &mut Parser, + allow_quirks: AllowQuirks) -> Result { + Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks) } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index b610401ac32..6519613bf6b 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -7,6 +7,7 @@ //! TODO(emilio): Enhance docs. use app_units::Au; +use context::QuirksMode; use cssparser::{self, Parser, Token}; use euclid::size::Size2D; use parser::{ParserContext, Parse}; @@ -1326,3 +1327,19 @@ pub type ClipRectOrAuto = Either; /// | auto pub type ColorOrAuto = Either; + +/// Whether quirks are allowed in this context. +#[derive(Clone, Copy, PartialEq)] +pub enum AllowQuirks { + /// Quirks are allowed. + Yes, + /// Quirks are not allowed. + No, +} + +impl AllowQuirks { + /// Returns `true` if quirks are allowed in this context. + pub fn allowed(self, quirks_mode: QuirksMode) -> bool { + self == AllowQuirks::Yes && quirks_mode == QuirksMode::Quirks + } +} diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index f8501e870c2..dfa05b36609 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -19,7 +19,7 @@ use values::computed::position as computed_position; use values::generics::position::{Position as GenericPosition, PositionValue, PositionWithKeyword}; use values::generics::position::HorizontalPosition as GenericHorizontalPosition; use values::generics::position::VerticalPosition as GenericVerticalPosition; -use values::specified::{LengthOrPercentage, Percentage}; +use values::specified::{AllowQuirks, LengthOrPercentage, Percentage}; pub use values::generics::position::Keyword; @@ -132,13 +132,23 @@ impl Position { impl Parse for Position { fn parse(context: &ParserContext, input: &mut Parser) -> Result { - let first = input.try(|i| PositionComponent::parse(context, i))?; - let second = input.try(|i| PositionComponent::parse(context, i)) + Position::parse_quirky(context, input, AllowQuirks::No) + } +} + +impl Position { + /// Parses, with quirks. + pub fn parse_quirky(context: &ParserContext, + input: &mut Parser, + allow_quirks: AllowQuirks) + -> Result { + let first = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks))?; + let second = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) .unwrap_or(Either::Second(Keyword::Center)); - if let Ok(third) = input.try(|i| PositionComponent::parse(context, i)) { + if let Ok(third) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) { // There's a 3rd value. - if let Ok(fourth) = input.try(|i| PositionComponent::parse(context, i)) { + if let Ok(fourth) = input.try(|i| PositionComponent::parse_quirky(context, i, allow_quirks)) { // There's a 4th value. Position::from_components(Some(second), Some(fourth), Some(first), Some(third)) } else { @@ -173,6 +183,17 @@ impl Parse for Position { } } +impl PositionComponent { + /// Parses, with quirks. + fn parse_quirky(context: &ParserContext, + input: &mut Parser, + allow_quirks: AllowQuirks) -> Result { + input.try(|i| LengthOrPercentage::parse_quirky(context, i, allow_quirks)) + .map(Either::First) + .or_else(|()| input.try(Keyword::parse).map(Either::Second)) + } +} + impl PositionValue { /// Generic function for the computed value of a position. fn computed_value(&self, context: &Context) -> ComputedLengthOrPercentage {