From 3631b1e19705c71b63fa702c19dc3c05f1276a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 2 Dec 2017 15:30:20 +0100 Subject: [PATCH] style: Deduplicate Angle parsing code. --- components/style/values/specified/angle.rs | 59 +++++++++++-------- components/style/values/specified/image.rs | 2 + .../style/values/specified/transform.rs | 6 +- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/components/style/values/specified/angle.rs b/components/style/values/specified/angle.rs index 1a89e8235ac..67f3463a474 100644 --- a/components/style/values/specified/angle.rs +++ b/components/style/values/specified/angle.rs @@ -102,23 +102,25 @@ impl AsRef for Angle { } } +/// Whether to allow parsing an unitless zero as a valid angle. +/// +/// This should always be `No`, except for exceptions like: +/// +/// https://github.com/w3c/fxtf-drafts/issues/228 +/// +/// See also: https://github.com/w3c/csswg-drafts/issues/1162. +enum AllowUnitlessZeroAngle { + Yes, + No, +} + impl Parse for Angle { /// Parses an angle according to CSS-VALUES ยง 6.1. fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - // FIXME: remove clone() when lifetimes are non-lexical - let token = input.next()?.clone(); - match token { - Token::Dimension { value, ref unit, .. } => { - Angle::parse_dimension(value, unit, /* from_calc = */ false) - } - Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { - return input.parse_nested_block(|i| CalcNode::parse_angle(context, i)) - } - _ => Err(()) - }.map_err(|()| input.new_unexpected_token_error(token.clone())) + Self::parse_internal(context, input, AllowUnitlessZeroAngle::No) } } @@ -127,9 +129,8 @@ impl Angle { pub fn parse_dimension( value: CSSFloat, unit: &str, - from_calc: bool) - -> Result - { + from_calc: bool, + ) -> Result { let angle = match_ignore_ascii_case! { unit, "deg" => Angle::from_degrees(value, from_calc), "grad" => Angle::from_gradians(value, from_calc), @@ -140,23 +141,33 @@ impl Angle { Ok(angle) } - /// Parse an angle, including unitless 0 degree. + /// Parse an `` allowing unitless zero to represent a zero angle. /// - /// Note that numbers without any AngleUnit, including unitless 0 angle, - /// should be invalid. However, some properties still accept unitless 0 - /// angle and stores it as '0deg'. - /// - /// We can remove this and get back to the unified version Angle::parse once - /// https://github.com/w3c/csswg-drafts/issues/1162 is resolved. - pub fn parse_with_unitless<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { + /// See the comment in `AllowUnitlessZeroAngle` for why. + pub fn parse_with_unitless<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Self::parse_internal(context, input, AllowUnitlessZeroAngle::Yes) + } + + fn parse_internal<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + allow_unitless_zero: AllowUnitlessZeroAngle, + ) -> Result> { // FIXME: remove clone() when lifetimes are non-lexical let token = input.next()?.clone(); match token { Token::Dimension { value, ref unit, .. } => { Angle::parse_dimension(value, unit, /* from_calc = */ false) } - Token::Number { value, .. } if value == 0. => Ok(Angle::zero()), + Token::Number { value, .. } if value == 0. => { + match allow_unitless_zero { + AllowUnitlessZeroAngle::Yes => Ok(Angle::zero()), + AllowUnitlessZeroAngle::No => Err(()), + } + }, Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { return input.parse_nested_block(|i| CalcNode::parse_angle(context, i)) } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index cd772db0d28..188b3239a7e 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -714,6 +714,8 @@ impl LineDirection { let mut _angle = if *compat_mode == CompatMode::Moz { input.try(|i| Angle::parse(context, i)).ok() } else { + // Gradients allow unitless zero angles as an exception, see: + // https://github.com/w3c/csswg-drafts/issues/1162 if let Ok(angle) = input.try(|i| Angle::parse_with_unitless(context, i)) { return Ok(LineDirection::Angle(angle)); } diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index ca77bd7a723..baa5048c51f 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -29,16 +29,18 @@ pub type TransformOperation = GenericTransformOperation< LengthOrPercentage, LengthOrPercentageOrNumber, >; + /// A specified CSS `transform` pub type Transform = GenericTransform; /// The specified value of a CSS `` pub type TransformOrigin = GenericTransformOrigin, OriginComponent, Length>; - impl Transform { /// Internal parse function for deciding if we wish to accept prefixed values or not - // Allow unitless zero angle for rotate() and skew() to align with gecko + /// + /// `transform` allows unitless zero angles as an exception, see: + /// https://github.com/w3c/csswg-drafts/issues/1162 fn parse_internal<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>,