servo: Merge #15761 - Have shorthand parsing functions not return Option for their longhands (from upsuper:shorthand); r=Manishearth
authorXidorn Quan <me@upsuper.org>
Mon, 27 Feb 2017 23:08:33 -0800
changeset 374178 ff962f4a7c6a3a8c95c369332f8c2060efd754e9
parent 374177 ace3041492115096392a36c13240e3c0111eed47
child 374179 eb8f83fd7a7cffd77f49d4767b428e5674fb5cf5
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersManishearth
milestone54.0a1
servo: Merge #15761 - Have shorthand parsing functions not return Option for their longhands (from upsuper:shorthand); r=Manishearth Source-Repo: https://github.com/servo/servo Source-Revision: 7ee629492280289fdd19c812389e833d5905e508
servo/components/script/dom/element.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/color.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/list.mako.rs
servo/components/style/properties/longhand/outline.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/properties/shorthand/background.mako.rs
servo/components/style/properties/shorthand/border.mako.rs
servo/components/style/properties/shorthand/box.mako.rs
servo/components/style/properties/shorthand/column.mako.rs
servo/components/style/properties/shorthand/font.mako.rs
servo/components/style/properties/shorthand/inherited_svg.mako.rs
servo/components/style/properties/shorthand/inherited_text.mako.rs
servo/components/style/properties/shorthand/list.mako.rs
servo/components/style/properties/shorthand/mask.mako.rs
servo/components/style/properties/shorthand/outline.mako.rs
servo/components/style/properties/shorthand/position.mako.rs
servo/components/style/properties/shorthand/serialize.mako.rs
servo/components/style/properties/shorthand/text.mako.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/mod.rs
servo/ports/geckolib/glue.rs
servo/tests/unit/style/parsing/background.rs
servo/tests/unit/style/parsing/border.rs
servo/tests/unit/style/parsing/inherited_text.rs
servo/tests/unit/style/parsing/mask.rs
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -98,25 +98,25 @@ use std::rc::Rc;
 use std::sync::Arc;
 use style::attr::{AttrValue, LengthOrPercentageOrAuto};
 use style::context::{QuirksMode, ReflowGoal};
 use style::element_state::*;
 use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
 use style::parser::ParserContextExtraData;
 use style::properties::{DeclaredValue, Importance};
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
-use style::properties::longhands::{background_image, border_spacing, font_family, font_size, overflow_x};
+use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size, overflow_x};
 use style::restyle_hints::RESTYLE_SELF;
 use style::rule_tree::CascadeLevel;
 use style::selector_parser::{NonTSPseudoClass, RestyleDamage, SelectorImpl, SelectorParser};
 use style::sink::Push;
 use style::stylist::ApplicableDeclarationBlock;
 use style::thread_state;
 use style::values::CSSFloat;
-use style::values::specified::{self, CSSColor, CSSRGBA};
+use style::values::specified::{self, CSSColor};
 use stylesheet_loader::StylesheetOwner;
 
 // TODO: Update focus state when the top-level browsing context gains or loses system focus,
 // and when the element enters or leaves a browsing context container.
 // https://html.spec.whatwg.org/multipage/#selector-focus
 
 #[dom_struct]
 pub struct Element {
@@ -437,20 +437,23 @@ impl LayoutElementHelpers for LayoutJS<E
             // https://html.spec.whatwg.org/multipage/#the-hr-element-2:presentational-hints-5
             this.get_color()
         } else {
             None
         };
 
         if let Some(color) = color {
             hints.push(from_declaration(
-                PropertyDeclaration::Color(DeclaredValue::Value(CSSRGBA {
-                    parsed: color,
-                    authored: None,
-                }))));
+                PropertyDeclaration::Color(DeclaredValue::Value(
+                    longhands::color::SpecifiedValue(CSSColor {
+                        parsed: Color::RGBA(color),
+                        authored: None,
+                    })
+                ))
+            ));
         }
 
         let font_family = if let Some(this) = self.downcast::<HTMLFontElement>() {
             this.get_face()
         } else {
             None
         };
 
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -1,42 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%! from data import Keyword, to_rust_ident, to_camel_case, LOGICAL_SIDES, PHYSICAL_SIDES, LOGICAL_SIZES %>
 
-<%def name="longhand(name, **kwargs)">
-    <%call expr="raw_longhand(name, **kwargs)">
-        ${caller.body()}
-        % if not data.longhands_by_name[name].derived_from:
-            pub fn parse_specified(context: &ParserContext, input: &mut Parser)
-                % if data.longhands_by_name[name].boxed:
-                                   -> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
-                    parse(context, input).map(|result| DeclaredValue::Value(Box::new(result)))
-                % else:
-                                   -> Result<DeclaredValue<SpecifiedValue>, ()> {
-                    parse(context, input).map(DeclaredValue::Value)
-                % endif
-            }
-        % endif
-    </%call>
-</%def>
-
 <%def name="predefined_type(name, type, initial_value, parse_method='parse',
-            needs_context=True, vector=False, **kwargs)">
+            needs_context=True, vector=False, initial_specified_value=None, **kwargs)">
     <%def name="predefined_type_inner(name, type, initial_value, parse_method)">
         #[allow(unused_imports)]
         use app_units::Au;
         use cssparser::{Color as CSSParserColor, RGBA};
         pub use values::specified::${type} as SpecifiedValue;
         pub mod computed_value {
             pub use values::computed::${type} as T;
         }
         #[inline] pub fn get_initial_value() -> computed_value::T { ${initial_value} }
+        % if initial_specified_value:
+        #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { ${initial_specified_value} }
+        % endif
         #[allow(unused_variables)]
         #[inline] pub fn parse(context: &ParserContext, input: &mut Parser)
                                -> Result<SpecifiedValue, ()> {
             % if needs_context:
             specified::${type}::${parse_method}(context, input)
             % else:
             specified::${type}::${parse_method}(input)
             % endif
@@ -207,17 +193,17 @@
                 }
             }
         % else:
             ${caller.body()}
         % endif
     </%call>
 </%def>
 
-<%def name="raw_longhand(*args, **kwargs)">
+<%def name="longhand(*args, **kwargs)">
     <%
         property = data.declare_longhand(*args, **kwargs)
         if property is None:
             return ""
     %>
     /// ${property.spec}
     pub mod ${property.ident} {
         #![allow(unused_imports)]
@@ -317,16 +303,25 @@
                                             cacheable,
                                             error_reporter);
                 % endif
             % else:
                 // Do not allow stylesheets to set derived properties.
             % endif
         }
         % if not property.derived_from:
+            pub fn parse_specified(context: &ParserContext, input: &mut Parser)
+                % if property.boxed:
+                                   -> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
+                    parse(context, input).map(|result| DeclaredValue::Value(Box::new(result)))
+                % else:
+                                   -> Result<DeclaredValue<SpecifiedValue>, ()> {
+                    parse(context, input).map(DeclaredValue::Value)
+                % endif
+            }
             pub fn parse_declared(context: &ParserContext, input: &mut Parser)
                                % if property.boxed:
                                    -> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
                                % else:
                                    -> Result<DeclaredValue<SpecifiedValue>, ()> {
                                % endif
                 match input.try(|i| CSSWideKeyword::parse(context, i)) {
                     Ok(CSSWideKeyword::InheritKeyword) => Ok(DeclaredValue::Inherit),
@@ -492,18 +487,17 @@
         use properties::{ShorthandId, longhands};
         use properties::declaration_block::Importance;
         use std::fmt;
         use style_traits::ToCss;
         use super::{SerializeFlags, ALL_INHERIT, ALL_INITIAL, ALL_UNSET};
 
         pub struct Longhands {
             % for sub_property in shorthand.sub_properties:
-                pub ${sub_property.ident}:
-                    Option<longhands::${sub_property.ident}::SpecifiedValue>,
+                pub ${sub_property.ident}: longhands::${sub_property.ident}::SpecifiedValue,
             % endfor
         }
 
         /// Represents a serializable set of all of the longhand properties that
         /// correspond to a shorthand.
         pub struct LonghandsToSerialize<'a> {
             % for sub_property in shorthand.sub_properties:
                 % if sub_property.boxed:
@@ -606,24 +600,21 @@
             let value = input.parse_entirely(|input| parse_value(context, input));
             if value.is_err() {
                 while let Ok(_) = input.next() {}  // Look for var() after the error.
             }
             let var = input.seen_var_functions();
             if let Ok(value) = value {
                 % for sub_property in shorthand.sub_properties:
                     declarations.push((PropertyDeclaration::${sub_property.camel_case}(
-                        match value.${sub_property.ident} {
-                            % if sub_property.boxed:
-                                Some(value) => DeclaredValue::Value(Box::new(value)),
-                            % else:
-                                Some(value) => DeclaredValue::Value(value),
-                            % endif
-                            None => DeclaredValue::Initial,
-                        }
+                        % if sub_property.boxed:
+                            DeclaredValue::Value(Box::new(value.${sub_property.ident}))
+                        % else:
+                            DeclaredValue::Value(value.${sub_property.ident})
+                        % endif
                     ), Importance::Normal));
                 % endfor
                 Ok(())
             } else if var {
                 input.reset(start);
                 let (first_token_type, css) = try!(
                     ::custom_properties::parse_non_custom_with_var(input));
                 % for sub_property in shorthand.sub_properties:
@@ -660,17 +651,17 @@
             % if needs_context:
                 try!(parse_four_sides(input, |i| ${parser_function}(context, i)));
             % else:
                 try!(parse_four_sides(input, ${parser_function}));
                 let _unused = context;
             % endif
             Ok(Longhands {
                 % for side in ["top", "right", "bottom", "left"]:
-                    ${to_rust_ident(sub_property_pattern % side)}: Some(${side}),
+                    ${to_rust_ident(sub_property_pattern % side)}: ${side},
                 % endfor
             })
         }
 
         impl<'a> LonghandsToSerialize<'a> {
             fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                 super::serialize_four_sides(
                     dest,
--- a/servo/components/style/properties/longhand/background.mako.rs
+++ b/servo/components/style/properties/longhand/background.mako.rs
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("Background", inherited=False) %>
 
 ${helpers.predefined_type("background-color", "CSSColor",
     "::cssparser::Color::RGBA(::cssparser::RGBA::transparent())",
+    initial_specified_value="SpecifiedValue::transparent()",
     spec="https://drafts.csswg.org/css-backgrounds/#background-color",
     animatable=True, complex_color=True)}
 
 <%helpers:vector_longhand name="background-image" animatable="False"
                           spec="https://drafts.csswg.org/css-backgrounds/#the-background-image"
                           has_uncacheable_values="${product == 'gecko'}">
     use std::fmt;
     use style_traits::ToCss;
--- a/servo/components/style/properties/longhand/color.mako.rs
+++ b/servo/components/style/properties/longhand/color.mako.rs
@@ -1,53 +1,60 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("Color", inherited=True) %>
 
-<%helpers:raw_longhand name="color" need_clone="True" animatable="True"
-                       spec="https://drafts.csswg.org/css-color/#color">
+<%helpers:longhand name="color" need_clone="True" animatable="True"
+                   spec="https://drafts.csswg.org/css-color/#color">
     use cssparser::Color as CSSParserColor;
     use cssparser::RGBA;
+    use std::fmt;
+    use style_traits::ToCss;
+    use values::HasViewportPercentage;
     use values::specified::{CSSColor, CSSRGBA};
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
-        fn to_computed_value(&self, _context: &Context) -> computed_value::T {
-            self.parsed
+        fn to_computed_value(&self, context: &Context) -> computed_value::T {
+            match self.0.parsed {
+                CSSParserColor::RGBA(rgba) => rgba,
+                CSSParserColor::CurrentColor => context.inherited_style.get_color().clone_color(),
+            }
         }
 
         #[inline]
         fn from_computed_value(computed: &computed_value::T) -> Self {
-            CSSRGBA {
-                parsed: *computed,
+            SpecifiedValue(CSSColor {
+                parsed: CSSParserColor::RGBA(*computed),
                 authored: None,
-            }
+            })
         }
     }
 
-    pub type SpecifiedValue = CSSRGBA;
+    #[derive(Clone, PartialEq, Debug)]
+    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+    pub struct SpecifiedValue(pub CSSColor);
+    no_viewport_percentage!(SpecifiedValue);
+
+    impl ToCss for SpecifiedValue {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            self.0.to_css(dest)
+        }
+    }
+
     pub mod computed_value {
         use cssparser;
         pub type T = cssparser::RGBA;
     }
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         RGBA::new(0, 0, 0, 255) // black
     }
-    pub fn parse_specified(context: &ParserContext, input: &mut Parser)
-                           -> Result<DeclaredValue<SpecifiedValue>, ()> {
-        let value = try!(CSSColor::parse(context, input));
-        let rgba = match value.parsed {
-            CSSParserColor::RGBA(rgba) => rgba,
-            CSSParserColor::CurrentColor => return Ok(DeclaredValue::Inherit)
-        };
-        Ok(DeclaredValue::Value(CSSRGBA {
-            parsed: rgba,
-            authored: value.authored,
-        }))
+    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+        CSSColor::parse(context, input).map(SpecifiedValue)
     }
-</%helpers:raw_longhand>
+</%helpers:longhand>
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -5,16 +5,17 @@
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("Column", inherited=False) %>
 
 // FIXME: This prop should be animatable.
 ${helpers.predefined_type("column-width",
                           "length::LengthOrAuto",
                           "Either::Second(Auto)",
+                          initial_specified_value="Either::Second(Auto)",
                           parse_method="parse_non_negative_length",
                           extra_prefixes="moz",
                           animatable=False,
                           experimental=True,
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}
 
 
 // FIXME: This prop should be animatable.
@@ -57,16 +58,21 @@
         }
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T(None)
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::Auto
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, _context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Auto => computed_value::T(None),
                 SpecifiedValue::Specified(count) =>
@@ -141,16 +147,17 @@
     pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         BorderWidth::parse(context, input)
     }
 </%helpers:longhand>
 
 // https://drafts.csswg.org/css-multicol-1/#crc
 ${helpers.predefined_type("column-rule-color", "CSSColor",
                           "::cssparser::Color::CurrentColor",
+                          initial_specified_value="specified::CSSColor::currentcolor()",
                           products="gecko", animatable=True, extra_prefixes="moz",
                           complex_color=True, need_clone=True,
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}
 
 // It's not implemented in servo or gecko yet.
 ${helpers.single_keyword("column-span", "none all",
                          products="none", animatable=False,
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -321,16 +321,21 @@
             }
         }
     }
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T::Weight400  // normal
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::Normal
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 % for weight in range(100, 901, 100):
                     SpecifiedValue::Weight${weight} => computed_value::T::Weight${weight},
@@ -402,16 +407,21 @@
     }
 
     #[inline]
     #[allow(missing_docs)]
     pub fn get_initial_value() -> computed_value::T {
         Au::from_px(FONT_MEDIUM_PX)
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue(specified::LengthOrPercentage::Length(NoCalcLength::medium()))
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match self.0 {
                 LengthOrPercentage::Length(NoCalcLength::FontRelative(value)) => {
                     value.to_computed_value(context, /* use inherited */ true)
@@ -497,16 +507,21 @@
             }
         }
     }
 
     #[inline] pub fn get_initial_value() -> computed_value::T {
         computed_value::T::None
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::None
+    }
+
     /// none | <number>
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         use values::specified::Number;
 
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(SpecifiedValue::None);
         }
 
@@ -745,16 +760,21 @@
         }
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         computed_value::T::Normal
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::Normal
+    }
+
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
             Ok(SpecifiedValue::Normal)
         } else {
             input.expect_string().map(|cow| {
                 SpecifiedValue::Override(cow.into_owned())
             })
         }
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -96,16 +96,21 @@
                 computed_value::T::Length(length) => length.to_css(dest),
                 computed_value::T::Number(number) => write!(dest, "{}", number),
             }
         }
     }
      #[inline]
     pub fn get_initial_value() -> computed_value::T { computed_value::T::Normal }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::Normal
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             match *self {
                 SpecifiedValue::Normal => computed_value::T::Normal,
                 % if product == "gecko":
@@ -1026,16 +1031,17 @@
             try!(dest.write_char(' '));
             vertical.to_css(dest)
         }
     }
 </%helpers:longhand>
 
 ${helpers.predefined_type("text-emphasis-color", "CSSColor",
                           "::cssparser::Color::CurrentColor",
+                          initial_specified_value="specified::CSSColor::currentcolor()",
                           products="gecko", animatable=True,
                           complex_color=True, need_clone=True,
                           spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")}
 
 
 ${helpers.predefined_type(
     "-moz-tab-size", "LengthOrNumber",
     "::values::Either::Second(8.0)",
@@ -1051,42 +1057,47 @@
     "CSSParserColor::CurrentColor",
     products="gecko", animatable=True,
     complex_color=True, need_clone=True,
     spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")}
 
 ${helpers.predefined_type(
     "-webkit-text-stroke-color", "CSSColor",
     "CSSParserColor::CurrentColor",
+    initial_specified_value="specified::CSSColor::currentcolor()",
     products="gecko", animatable=True,
     complex_color=True, need_clone=True,
     spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")}
 
 <%helpers:longhand products="gecko" name="-webkit-text-stroke-width" animatable="False"
                    spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width">
     use app_units::Au;
     use std::fmt;
     use style_traits::ToCss;
     use values::HasViewportPercentage;
-    use values::specified::BorderWidth;
+    use values::specified::{BorderWidth, Length};
 
     pub type SpecifiedValue = BorderWidth;
 
     #[inline]
     pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         BorderWidth::parse(context, input)
     }
 
     pub mod computed_value {
         use app_units::Au;
         pub type T = Au;
     }
     #[inline] pub fn get_initial_value() -> computed_value::T {
         Au::from_px(0)
     }
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        BorderWidth::from_length(Length::zero())
+    }
 </%helpers:longhand>
 
 
 // CSS Ruby Layout Module Level 1
 // https://drafts.csswg.org/css-ruby/
 ${helpers.single_keyword("ruby-align", "start center space-between space-around",
                          products="gecko", animatable=False,
                          spec="https://drafts.csswg.org/css-ruby/#ruby-align-property")}
--- a/servo/components/style/properties/longhand/list.mako.rs
+++ b/servo/components/style/properties/longhand/list.mako.rs
@@ -33,17 +33,17 @@
     trad-chinese-informal trad-chinese-formal ethiopic-numeric upper-roman lower-roman
     """,
     gecko_constant_prefix="NS_STYLE_LIST_STYLE",
     needs_conversion="True",
     animatable=False,
     spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
 
 ${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_)",
-                          animatable=False,
+                          initial_specified_value="Either::Second(None_)", animatable=False,
                           spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")}
 
 <%helpers:longhand name="quotes" animatable="False"
                    spec="https://drafts.csswg.org/css-content/#propdef-quotes">
     use cssparser::Token;
     use std::borrow::Cow;
     use std::fmt;
     use style_traits::ToCss;
--- a/servo/components/style/properties/longhand/outline.mako.rs
+++ b/servo/components/style/properties/longhand/outline.mako.rs
@@ -6,16 +6,17 @@
 <% from data import Method %>
 
 <% data.new_style_struct("Outline",
                          inherited=False,
                          additional_methods=[Method("outline_has_nonzero_width", "bool")]) %>
 
 // TODO(pcwalton): `invert`
 ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::CurrentColor",
+                          initial_specified_value="specified::CSSColor::currentcolor()",
                           animatable=True, complex_color=True, need_clone=True,
                           spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")}
 
 <%helpers:longhand name="outline-style" need_clone="True" animatable="False"
                    spec="https://drafts.csswg.org/css-ui/#propdef-outline-style">
 
     use std::fmt;
     use style_traits::ToCss;
@@ -34,16 +35,21 @@
         }
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
         Either::Second(BorderStyle::none)
     }
 
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        Either::Second(BorderStyle::none)
+    }
+
     pub mod computed_value {
         pub type T = super::SpecifiedValue;
     }
 
     pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         SpecifiedValue::parse(context, input)
             .and_then(|result| {
                 if let Either::Second(BorderStyle::hidden) = result {
@@ -83,17 +89,23 @@
 
     #[derive(Debug, Clone, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub struct SpecifiedValue(pub specified::Length);
     pub mod computed_value {
         use app_units::Au;
         pub type T = Au;
     }
+
     pub use super::border_top_width::get_initial_value;
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue(specified::Length::NoCalc(specified::NoCalcLength::medium()))
+    }
+
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             self.0.to_computed_value(context)
         }
 
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -164,16 +164,20 @@
         #[allow(non_upper_case_globals)]
         pub const none: T = super::SpecifiedValue {
             bits: 0
         };
     }
     #[inline] pub fn get_initial_value() -> computed_value::T {
         computed_value::none
     }
+    #[inline]
+    pub fn get_initial_specified_value() -> SpecifiedValue {
+        SpecifiedValue::empty()
+    }
     /// none | [ underline || overline || line-through || blink ]
     pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
         let mut result = SpecifiedValue::empty();
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(result)
         }
         let mut empty = true;
 
@@ -214,13 +218,14 @@
 ${helpers.single_keyword("text-decoration-style",
                          "solid double dotted dashed wavy -moz-none",
                          products="gecko",
                          animatable=False,
                          spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")}
 
 ${helpers.predefined_type(
     "text-decoration-color", "CSSColor",
-    "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
+    "::cssparser::Color::CurrentColor",
+    initial_specified_value="specified::CSSColor::currentcolor()",
     complex_color=True,
     products="gecko",
     animatable=True,
     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")}
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -83,16 +83,22 @@ pub mod longhands {
     <%include file="/longhand/table.mako.rs" />
     <%include file="/longhand/text.mako.rs" />
     <%include file="/longhand/ui.mako.rs" />
     <%include file="/longhand/inherited_svg.mako.rs" />
     <%include file="/longhand/svg.mako.rs" />
     <%include file="/longhand/xul.mako.rs" />
 }
 
+macro_rules! unwrap_or_initial {
+    ($prop: ident) => (unwrap_or_initial!($prop, $prop));
+    ($prop: ident, $expr: expr) =>
+        ($expr.unwrap_or_else(|| $prop::get_initial_specified_value()));
+}
+
 /// A module with code for all the shorthand css properties, and a few
 /// serialization helpers.
 #[allow(missing_docs)]
 pub mod shorthands {
     use cssparser::Parser;
     use parser::{Parse, ParserContext};
     use values::specified;
 
@@ -338,23 +344,22 @@ impl PropertyDeclarationIdSet {
                         match from_shorthand {
                             None => {
                                 longhands::${property.ident}::parse_specified(&context, input)
                             }
                             % for shorthand in data.shorthands:
                                 % if property in shorthand.sub_properties:
                                     Some(ShorthandId::${shorthand.camel_case}) => {
                                         shorthands::${shorthand.ident}::parse_value(&context, input)
-                                        .map(|result| match result.${property.ident} {
+                                        .map(|result| {
                                             % if property.boxed:
-                                                Some(value) => DeclaredValue::Value(Box::new(value)),
+                                                DeclaredValue::Value(Box::new(result.${property.ident}))
                                             % else:
-                                                Some(value) => DeclaredValue::Value(value),
+                                                DeclaredValue::Value(result.${property.ident})
                                             % endif
-                                            None => DeclaredValue::Initial,
                                         })
                                     }
                                 % endif
                             % endfor
                             _ => unreachable!()
                         }
                     })
                 })
--- a/servo/components/style/properties/shorthand/background.mako.rs
+++ b/servo/components/style/properties/shorthand/background.mako.rs
@@ -110,25 +110,25 @@
                 % endfor
                 Ok(())
             } else {
                 Err(())
             }
         }));
 
         Ok(Longhands {
-             background_color: background_color,
-             background_image: Some(background_image),
-             background_position_x: Some(background_position_x),
-             background_position_y: Some(background_position_y),
-             background_repeat: Some(background_repeat),
-             background_attachment: Some(background_attachment),
-             background_size: Some(background_size),
-             background_origin: Some(background_origin),
-             background_clip: Some(background_clip),
+             background_color: unwrap_or_initial!(background_color),
+             background_image: background_image,
+             background_position_x: background_position_x,
+             background_position_y: background_position_y,
+             background_repeat: background_repeat,
+             background_attachment: background_attachment,
+             background_size: background_size,
+             background_origin: background_origin,
+             background_clip: background_clip,
          })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             // mako doesn't like ampersands following `<`
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
                 match *x {
@@ -241,18 +241,18 @@
             }
             Ok(())
         }));
         if any == false {
             return Err(());
         }
 
         Ok(Longhands {
-            background_position_x: Some(position_x),
-            background_position_y: Some(position_y),
+            background_position_x: position_x,
+            background_position_y: position_y,
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             // mako doesn't like ampersands following `<`
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
                 match *x {
--- a/servo/components/style/properties/shorthand/border.mako.rs
+++ b/servo/components/style/properties/shorthand/border.mako.rs
@@ -19,17 +19,17 @@
     use super::parse_four_sides;
     use parser::Parse;
     use values::specified;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let (top, right, bottom, left) = try!(parse_four_sides(input, |i| specified::BorderWidth::parse(context, i)));
         Ok(Longhands {
             % for side in ["top", "right", "bottom", "left"]:
-                ${to_rust_ident('border-%s-width' % side)}: Some(${side}),
+                ${to_rust_ident('border-%s-width' % side)}: ${side},
             % endfor
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             % for side in ["top", "right", "bottom", "left"]:
                 let ${side} = self.border_${side}_width.clone();
@@ -37,50 +37,56 @@
 
             super::serialize_four_sides(dest, &top, &right, &bottom, &left)
         }
     }
 </%helpers:shorthand>
 
 
 pub fn parse_border(context: &ParserContext, input: &mut Parser)
-                 -> Result<(Option<specified::CSSColor>,
-                            Option<specified::BorderStyle>,
-                            Option<specified::BorderWidth>), ()> {
-    use values::specified;
+                 -> Result<(specified::CSSColor,
+                            specified::BorderStyle,
+                            specified::BorderWidth), ()> {
+    use values::specified::{CSSColor, BorderStyle, BorderWidth};
     let _unused = context;
     let mut color = None;
     let mut style = None;
     let mut width = None;
     let mut any = false;
     loop {
         if color.is_none() {
-            if let Ok(value) = input.try(|i| specified::CSSColor::parse(context, i)) {
+            if let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
                 color = Some(value);
                 any = true;
                 continue
             }
         }
         if style.is_none() {
-            if let Ok(value) = input.try(|i| specified::BorderStyle::parse(context, i)) {
+            if let Ok(value) = input.try(|i| BorderStyle::parse(context, i)) {
                 style = Some(value);
                 any = true;
                 continue
             }
         }
         if width.is_none() {
-            if let Ok(value) = input.try(|i| specified::BorderWidth::parse(context, i)) {
+            if let Ok(value) = input.try(|i| BorderWidth::parse(context, i)) {
                 width = Some(value);
                 any = true;
                 continue
             }
         }
         break
     }
-    if any { Ok((color, style, width)) } else { Err(()) }
+    if any {
+        Ok((color.unwrap_or_else(|| CSSColor::currentcolor()),
+            style.unwrap_or(BorderStyle::none),
+            width.unwrap_or(BorderWidth::Medium)))
+    } else {
+        Err(())
+    }
 }
 
 % for side, logical in ALL_SIDES:
     <%
         spec = "https://drafts.csswg.org/css-backgrounds/#border-%s" % side
         if logical:
             spec = "https://drafts.csswg.org/css-logical-props/#propdef-border-%s" % side
     %>
@@ -153,20 +159,20 @@ pub fn parse_border(context: &ParserCont
      for corner in ['top-left', 'top-right', 'bottom-right', 'bottom-left']
 )}" extra_prefixes="webkit" spec="https://drafts.csswg.org/css-backgrounds/#border-radius">
     use values::specified::basic_shape::BorderRadius;
     use parser::Parse;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let radii = try!(BorderRadius::parse(context, input));
         Ok(Longhands {
-            border_top_left_radius: Some(radii.top_left),
-            border_top_right_radius: Some(radii.top_right),
-            border_bottom_right_radius: Some(radii.bottom_right),
-            border_bottom_left_radius: Some(radii.bottom_left),
+            border_top_left_radius: radii.top_left,
+            border_top_right_radius: radii.top_right,
+            border_bottom_right_radius: radii.bottom_right,
+            border_bottom_left_radius: radii.bottom_left,
         })
     }
 
     // TODO: I do not understand how border radius works with respect to the slashes /,
     // so putting a default generic impl for now
     // https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@@ -249,17 +255,17 @@ pub fn parse_border(context: &ParserCont
                 Ok(())
             } else {
                 Err(())
             }
         }));
 
         Ok(Longhands {
             % for name in "outset repeat slice source width".split():
-                border_image_${name}: Some(border_image_${name}),
+                border_image_${name}: border_image_${name},
             % endfor
          })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             % for name in "outset repeat slice source width".split():
                 let ${name} = if let DeclaredValue::Value(ref value) = *self.border_image_${name} {
--- a/servo/components/style/properties/shorthand/box.mako.rs
+++ b/servo/components/style/properties/shorthand/box.mako.rs
@@ -6,18 +6,18 @@
 
 <%helpers:shorthand name="overflow" sub_properties="overflow-x overflow-y"
                     spec="https://drafts.csswg.org/css-overflow/#propdef-overflow">
     use properties::longhands::{overflow_x, overflow_y};
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let overflow = try!(overflow_x::parse(context, input));
         Ok(Longhands {
-            overflow_x: Some(overflow),
-            overflow_y: Some(overflow_y::SpecifiedValue(overflow)),
+            overflow_x: overflow,
+            overflow_y: overflow_y::SpecifiedValue(overflow),
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             let x_and_y_equal = match (self.overflow_x, self.overflow_y) {
                 (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
                     *x_value == y_container.0
@@ -98,41 +98,35 @@ macro_rules! try_parse_one {
                     transition_delay:
                         delay.unwrap_or_else(transition_delay::single_value::get_initial_value),
                 })
             } else {
                 Err(())
             }
         }
 
-        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
-            return Ok(Longhands {
-                transition_property: None,
-                transition_duration: None,
-                transition_timing_function: None,
-                transition_delay: None,
-            })
-        }
-
-        let results = try!(input.parse_comma_separated(|i| parse_one_transition(context, i)));
         let (mut properties, mut durations) = (Vec::new(), Vec::new());
         let (mut timing_functions, mut delays) = (Vec::new(), Vec::new());
-        for result in results {
-            properties.push(result.transition_property);
-            durations.push(result.transition_duration);
-            timing_functions.push(result.transition_timing_function);
-            delays.push(result.transition_delay);
+
+        if input.try(|input| input.expect_ident_matching("none")).is_err() {
+            let results = try!(input.parse_comma_separated(|i| parse_one_transition(context, i)));
+            for result in results {
+                properties.push(result.transition_property);
+                durations.push(result.transition_duration);
+                timing_functions.push(result.transition_timing_function);
+                delays.push(result.transition_delay);
+            }
         }
 
         Ok(Longhands {
-            transition_property: Some(transition_property::SpecifiedValue(properties)),
-            transition_duration: Some(transition_duration::SpecifiedValue(durations)),
+            transition_property: transition_property::SpecifiedValue(properties),
+            transition_duration: transition_duration::SpecifiedValue(durations),
             transition_timing_function:
-                Some(transition_timing_function::SpecifiedValue(timing_functions)),
-            transition_delay: Some(transition_delay::SpecifiedValue(delays)),
+                transition_timing_function::SpecifiedValue(timing_functions),
+            transition_delay: transition_delay::SpecifiedValue(delays),
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
                 match *x {
                     DeclaredValue::Value(ref val) => Some(val),
@@ -253,60 +247,48 @@ macro_rules! try_parse_one {
                     animation_play_state:
                         play_state.unwrap_or_else(animation_play_state::single_value::get_initial_value),
                 })
             } else {
                 Err(())
             }
         }
 
-        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
-            return Ok(Longhands {
-                animation_name: None,
-                animation_duration: None,
-                animation_timing_function: None,
-                animation_delay: None,
-                animation_iteration_count: None,
-                animation_direction: None,
-                animation_fill_mode: None,
-                animation_play_state: None,
-            })
-        }
-
-        let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i)));
-
         let mut names = vec![];
         let mut durations = vec![];
         let mut timing_functions = vec![];
         let mut delays = vec![];
         let mut iteration_counts = vec![];
         let mut directions = vec![];
         let mut fill_modes = vec![];
         let mut play_states = vec![];
 
-        for result in results.into_iter() {
-            names.push(result.animation_name);
-            durations.push(result.animation_duration);
-            timing_functions.push(result.animation_timing_function);
-            delays.push(result.animation_delay);
-            iteration_counts.push(result.animation_iteration_count);
-            directions.push(result.animation_direction);
-            fill_modes.push(result.animation_fill_mode);
-            play_states.push(result.animation_play_state);
+        if input.try(|input| input.expect_ident_matching("none")).is_err() {
+            let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i)));
+            for result in results.into_iter() {
+                names.push(result.animation_name);
+                durations.push(result.animation_duration);
+                timing_functions.push(result.animation_timing_function);
+                delays.push(result.animation_delay);
+                iteration_counts.push(result.animation_iteration_count);
+                directions.push(result.animation_direction);
+                fill_modes.push(result.animation_fill_mode);
+                play_states.push(result.animation_play_state);
+            }
         }
 
         Ok(Longhands {
-            animation_name: Some(animation_name::SpecifiedValue(names)),
-            animation_duration: Some(animation_duration::SpecifiedValue(durations)),
-            animation_timing_function: Some(animation_timing_function::SpecifiedValue(timing_functions)),
-            animation_delay: Some(animation_delay::SpecifiedValue(delays)),
-            animation_iteration_count: Some(animation_iteration_count::SpecifiedValue(iteration_counts)),
-            animation_direction: Some(animation_direction::SpecifiedValue(directions)),
-            animation_fill_mode: Some(animation_fill_mode::SpecifiedValue(fill_modes)),
-            animation_play_state: Some(animation_play_state::SpecifiedValue(play_states)),
+            animation_name: animation_name::SpecifiedValue(names),
+            animation_duration: animation_duration::SpecifiedValue(durations),
+            animation_timing_function: animation_timing_function::SpecifiedValue(timing_functions),
+            animation_delay: animation_delay::SpecifiedValue(delays),
+            animation_iteration_count: animation_iteration_count::SpecifiedValue(iteration_counts),
+            animation_direction: animation_direction::SpecifiedValue(directions),
+            animation_fill_mode: animation_fill_mode::SpecifiedValue(fill_modes),
+            animation_play_state: animation_play_state::SpecifiedValue(play_states),
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
                 match *x {
                     DeclaredValue::Value(ref val) => Some(val),
@@ -359,18 +341,18 @@ macro_rules! try_parse_one {
 <%helpers:shorthand name="scroll-snap-type" products="gecko"
                     sub_properties="scroll-snap-type-x scroll-snap-type-y"
                     spec="https://drafts.csswg.org/css-scroll-snap/#propdef-scroll-snap-type">
     use properties::longhands::scroll_snap_type_x;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let result = try!(scroll_snap_type_x::parse(context, input));
         Ok(Longhands {
-            scroll_snap_type_x: Some(result),
-            scroll_snap_type_y: Some(result),
+            scroll_snap_type_x: result,
+            scroll_snap_type_y: result,
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         // Serializes into the single keyword value if both scroll-snap-type and scroll-snap-type-y are same.
         // Otherwise into an empty string. This is done to match Gecko's behaviour.
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             let x_and_y_equal = match (self.scroll_snap_type_x, self.scroll_snap_type_y) {
--- a/servo/components/style/properties/shorthand/column.mako.rs
+++ b/servo/components/style/properties/shorthand/column.mako.rs
@@ -38,18 +38,18 @@
             break
         }
 
         let values = autos + column_count.iter().len() + column_width.iter().len();
         if values == 0 || values > 2 {
             Err(())
         } else {
             Ok(Longhands {
-                column_count: column_count,
-                column_width: column_width,
+                column_count: unwrap_or_initial!(column_count),
+                column_width: unwrap_or_initial!(column_width),
             })
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             try!(self.column_width.to_css(dest));
             try!(write!(dest, " "));
@@ -82,21 +82,19 @@
                 }
             }
             % endfor
 
             break
         }
         if any {
             Ok(Longhands {
-                % for name in "width style".split():
-                    column_rule_${name}: column_rule_${name}
-                        .or(Some(column_rule_${name}::get_initial_specified_value())),
-                % endfor
-                column_rule_color: column_rule_color,
+                column_rule_width: unwrap_or_initial!(column_rule_width),
+                column_rule_style: unwrap_or_initial!(column_rule_style),
+                column_rule_color: unwrap_or_initial!(column_rule_color),
             })
         } else {
             Err(())
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -9,16 +9,22 @@
                                                 ${'font-size-adjust' if product == 'gecko' else ''}
                                                 ${'font-kerning' if product == 'gecko' else ''}
                                                 ${'font-variant-caps' if product == 'gecko' else ''}
                                                 ${'font-variant-position' if product == 'gecko' else ''}
                                                 ${'font-language-override' if product == 'none' else ''}"
                     spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
     use properties::longhands::{font_style, font_variant, font_weight, font_stretch};
     use properties::longhands::{font_size, line_height};
+    % if product == "gecko":
+    use properties::longhands::{font_size_adjust, font_kerning, font_variant_caps, font_variant_position};
+    % endif
+    % if product == "none":
+    use properties::longhands::font_language_override;
+    % endif
     use properties::longhands::font_family::SpecifiedValue as FontFamily;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let mut nb_normals = 0;
         let mut style = None;
         let mut variant = None;
         let mut weight = None;
         let mut stretch = None;
@@ -67,32 +73,29 @@
         }
         let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
             Some(try!(line_height::parse(context, input)))
         } else {
             None
         };
         let family = FontFamily::parse(input)?;
         Ok(Longhands {
-            font_style: style,
-            font_variant: variant,
-            font_weight: weight,
-            font_stretch: stretch,
-            font_size: size,
-            line_height: line_height,
-            font_family: Some(family),
-    % if product == "gecko":
-            font_size_adjust: None,
-            font_kerning: None,
-            font_variant_caps: None,
-            font_variant_position: None,
-    % endif
-    % if product == "none":
-            font_language_override: None,
-    % endif
+            % for name in "style variant weight stretch size".split():
+                font_${name}: unwrap_or_initial!(font_${name}, ${name}),
+            % endfor
+            line_height: unwrap_or_initial!(line_height),
+            font_family: family,
+            % if product == "gecko":
+                % for name in "size_adjust kerning variant_caps variant_position".split():
+                    font_${name}: font_${name}::get_initial_specified_value(),
+                % endfor
+            % endif
+            % if product == "none":
+                font_language_override: font_language_override::get_initial_specified_value(),
+            % endif
         })
     }
 
     // This may be a bit off, unsure, possibly needs changes
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             if let DeclaredValue::Value(ref style) = *self.font_style {
                 try!(style.to_css(dest));
--- a/servo/components/style/properties/shorthand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/shorthand/inherited_svg.mako.rs
@@ -9,19 +9,19 @@
     spec="https://www.w3.org/TR/SVG2/painting.html#MarkerShorthand">
     use values::specified::UrlOrNone;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         use parser::Parse;
         let url = UrlOrNone::parse(context, input)?;
 
         Ok(Longhands {
-            marker_start: Some(url.clone()),
-            marker_mid: Some(url.clone()),
-            marker_end: Some(url),
+            marker_start: url.clone(),
+            marker_mid: url.clone(),
+            marker_end: url,
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             if let DeclaredValue::Value(ref start) = *self.marker_start {
                 if let DeclaredValue::Value(ref mid) = *self.marker_mid {
                     if let DeclaredValue::Value(ref end) = *self.marker_end {
--- a/servo/components/style/properties/shorthand/inherited_text.mako.rs
+++ b/servo/components/style/properties/shorthand/inherited_text.mako.rs
@@ -24,23 +24,19 @@
                 if let Ok(value) = input.try(|input| text_emphasis_style::parse(context, input)) {
                     style = Some(value);
                     continue
                 }
             }
             break
         }
         if color.is_some() || style.is_some() {
-            if style.is_none() {
-                style = Some(text_emphasis_style::get_initial_specified_value());
-            }
-
             Ok(Longhands {
-                text_emphasis_color: color,
-                text_emphasis_style: style,
+                text_emphasis_color: unwrap_or_initial!(text_emphasis_color, color),
+                text_emphasis_style: unwrap_or_initial!(text_emphasis_style, style),
             })
         } else {
             Err(())
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@@ -63,23 +59,19 @@
 
 // CSS Compatibility
 // https://compat.spec.whatwg.org/
 <%helpers:shorthand name="-webkit-text-stroke"
                     sub_properties="-webkit-text-stroke-color
                                     -webkit-text-stroke-width"
                     products="gecko"
                     spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke">
-    use cssparser::Color as CSSParserColor;
     use properties::longhands::{_webkit_text_stroke_color, _webkit_text_stroke_width};
-    use values::specified::CSSColor;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
-        use values::specified::{BorderWidth, Length};
-
         let mut color = None;
         let mut width = None;
         loop {
             if color.is_none() {
                 if let Ok(value) = input.try(|input| _webkit_text_stroke_color::parse(context, input)) {
                     color = Some(value);
                     continue
                 }
@@ -91,19 +83,18 @@
                     continue
                 }
             }
             break
         }
 
         if color.is_some() || width.is_some() {
             Ok(Longhands {
-                _webkit_text_stroke_color: color.or(Some(CSSColor { parsed: CSSParserColor::CurrentColor,
-                    authored: None })),
-                _webkit_text_stroke_width: width.or(Some(BorderWidth::from_length(Length::zero()))),
+                _webkit_text_stroke_color: unwrap_or_initial!(_webkit_text_stroke_color, color),
+                _webkit_text_stroke_width: unwrap_or_initial!(_webkit_text_stroke_width, width),
             })
         } else {
             Err(())
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/properties/shorthand/list.mako.rs
+++ b/servo/components/style/properties/shorthand/list.mako.rs
@@ -46,53 +46,55 @@
                     position = Some(value);
                     any = true;
                     continue
                 }
             }
             break
         }
 
+        let position = unwrap_or_initial!(list_style_position, position);
+
         // If there are two `none`s, then we can't have a type or image; if there is one `none`,
         // then we can't have both a type *and* an image; if there is no `none` then we're fine as
         // long as we parsed something.
         match (any, nones, list_style_type, image) {
             (true, 2, None, None) => {
                 Ok(Longhands {
                     list_style_position: position,
-                    list_style_image: Some(Either::Second(None_)),
-                    list_style_type: Some(list_style_type::SpecifiedValue::none),
+                    list_style_image: Either::Second(None_),
+                    list_style_type: list_style_type::SpecifiedValue::none,
                 })
             }
             (true, 1, None, Some(image)) => {
                 Ok(Longhands {
                     list_style_position: position,
-                    list_style_image: Some(image),
-                    list_style_type: Some(list_style_type::SpecifiedValue::none),
+                    list_style_image: image,
+                    list_style_type: list_style_type::SpecifiedValue::none,
                 })
             }
             (true, 1, Some(list_style_type), None) => {
                 Ok(Longhands {
                     list_style_position: position,
-                    list_style_image: Some(Either::Second(None_)),
-                    list_style_type: Some(list_style_type),
+                    list_style_image: Either::Second(None_),
+                    list_style_type: list_style_type,
                 })
             }
             (true, 1, None, None) => {
                 Ok(Longhands {
                     list_style_position: position,
-                    list_style_image: Some(Either::Second(None_)),
-                    list_style_type: Some(list_style_type::SpecifiedValue::none),
+                    list_style_image: Either::Second(None_),
+                    list_style_type: list_style_type::SpecifiedValue::none,
                 })
             }
             (true, 0, list_style_type, image) => {
                 Ok(Longhands {
                     list_style_position: position,
-                    list_style_image: image,
-                    list_style_type: list_style_type,
+                    list_style_image: unwrap_or_initial!(list_style_image, image),
+                    list_style_type: unwrap_or_initial!(list_style_type),
                 })
             }
             _ => Err(()),
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/properties/shorthand/mask.mako.rs
+++ b/servo/components/style/properties/shorthand/mask.mako.rs
@@ -110,17 +110,17 @@
                 Ok(())
             } else {
                 Err(())
             }
         }));
 
         Ok(Longhands {
             % for name in "image mode position_x position_y size repeat origin clip composite".split():
-                mask_${name}: Some(mask_${name}),
+                mask_${name}: mask_${name},
             % endfor
          })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             // mako doesn't like ampersands following `<`
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
@@ -258,18 +258,18 @@
             }
             Ok(())
         }));
         if any == false {
             return Err(());
         }
 
         Ok(Longhands {
-            mask_position_x: Some(position_x),
-            mask_position_y: Some(position_y),
+            mask_position_x: position_x,
+            mask_position_y: position_y,
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             // mako doesn't like ampersands following `<`
             fn extract_value<T>(x: &DeclaredValue<T>) -> Option< &T> {
                 match *x {
--- a/servo/components/style/properties/shorthand/outline.mako.rs
+++ b/servo/components/style/properties/shorthand/outline.mako.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <%helpers:shorthand name="outline" sub_properties="outline-color outline-style outline-width"
                     spec="https://drafts.csswg.org/css-ui/#propdef-outline">
-    use properties::longhands::{outline_width, outline_style};
+    use properties::longhands::{outline_color, outline_width, outline_style};
     use values::specified;
     use parser::Parse;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let _unused = context;
         let mut color = None;
         let mut style = None;
         let mut width = None;
@@ -37,19 +37,19 @@
                     any = true;
                     continue
                 }
             }
             break
         }
         if any {
             Ok(Longhands {
-                outline_color: color,
-                outline_style: style,
-                outline_width: width,
+                outline_color: unwrap_or_initial!(outline_color, color),
+                outline_style: unwrap_or_initial!(outline_style, style),
+                outline_width: unwrap_or_initial!(outline_width, width),
             })
         } else {
             Err(())
         }
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
--- a/servo/components/style/properties/shorthand/position.mako.rs
+++ b/servo/components/style/properties/shorthand/position.mako.rs
@@ -26,18 +26,18 @@
             }
             break
         }
 
         if direction.is_none() && wrap.is_none() {
             return Err(())
         }
         Ok(Longhands {
-            flex_direction: direction,
-            flex_wrap: wrap,
+            flex_direction: unwrap_or_initial!(flex_direction, direction),
+            flex_wrap: unwrap_or_initial!(flex_wrap, wrap),
         })
     }
 
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self.flex_direction {
                 DeclaredValue::Initial => try!(write!(dest, "row")),
@@ -68,19 +68,19 @@
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let mut grow = None;
         let mut shrink = None;
         let mut basis = None;
 
         if input.try(|input| input.expect_ident_matching("none")).is_ok() {
             return Ok(Longhands {
-                flex_grow: Some(Number(0.0)),
-                flex_shrink: Some(Number(0.0)),
-                flex_basis: Some(LengthOrPercentageOrAutoOrContent::Auto)
+                flex_grow: Number(0.0),
+                flex_shrink: Number(0.0),
+                flex_basis: LengthOrPercentageOrAutoOrContent::Auto
             })
         }
         loop {
             if grow.is_none() {
                 if let Ok((flex_grow, flex_shrink)) = input.try(parse_flexibility) {
                     grow = Some(flex_grow);
                     shrink = flex_shrink;
                     continue
@@ -94,19 +94,19 @@
             }
             break
         }
 
         if grow.is_none() && basis.is_none() {
             return Err(())
         }
         Ok(Longhands {
-            flex_grow: grow.or(Some(Number(1.0))),
-            flex_shrink: shrink.or(Some(Number(1.0))),
-            flex_basis: basis.or(Some(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero())))
+            flex_grow: grow.unwrap_or(Number(1.0)),
+            flex_shrink: shrink.unwrap_or(Number(1.0)),
+            flex_basis: basis.unwrap_or(LengthOrPercentageOrAutoOrContent::Length(NoCalcLength::zero()))
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             try!(self.flex_grow.to_css(dest));
             try!(write!(dest, " "));
 
--- a/servo/components/style/properties/shorthand/serialize.mako.rs
+++ b/servo/components/style/properties/shorthand/serialize.mako.rs
@@ -1,12 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+use cssparser::Color;
 use properties::DeclaredValue;
 use style_traits::ToCss;
 use values::specified::{BorderStyle, CSSColor};
 use std::fmt;
 
 #[allow(missing_docs)]
 pub fn serialize_four_sides<W, I>(dest: &mut W,
                                   top: &I,
@@ -79,15 +80,15 @@ fn serialize_directional_border<W, I,>(d
             try!(style.to_css(dest));
         },
         _ => {
             try!(write!(dest, "none"));
         }
     };
 
     match *color {
-        DeclaredValue::Value(ref color) => {
+        DeclaredValue::Value(ref color) if color.parsed != Color::CurrentColor => {
             try!(write!(dest, " "));
             color.to_css(dest)
         },
         _ => Ok(())
     }
 }
--- a/servo/components/style/properties/shorthand/text.mako.rs
+++ b/servo/components/style/properties/shorthand/text.mako.rs
@@ -8,17 +8,16 @@
                     sub_properties="text-decoration-color
                                     text-decoration-line
                                     text-decoration-style"
                     products="gecko"
                     disable_when_testing="True"
                     spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration">
     use cssparser::Color as CSSParserColor;
     use properties::longhands::{text_decoration_color, text_decoration_line, text_decoration_style};
-    use values::specified::CSSColor;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let (mut color, mut line, mut style, mut any) = (None, None, None, false);
         loop {
             macro_rules! parse_component {
                 ($value:ident, $module:ident) => (
                     if $value.is_none() {
                         if let Ok(value) = input.try(|input| $module::parse(context, input)) {
@@ -36,20 +35,19 @@
             break;
         }
 
         if !any {
             return Err(());
         }
 
         Ok(Longhands {
-            text_decoration_color: color.or(Some(CSSColor { parsed: CSSParserColor::CurrentColor,
-                                                            authored: None })),
-            text_decoration_line: line.or(Some(text_decoration_line::computed_value::none)),
-            text_decoration_style: style.or(Some(text_decoration_style::computed_value::T::solid)),
+            text_decoration_color: unwrap_or_initial!(text_decoration_color, color),
+            text_decoration_line: unwrap_or_initial!(text_decoration_line, line),
+            text_decoration_style: unwrap_or_initial!(text_decoration_style, style),
         })
     }
 
     impl<'a> LonghandsToSerialize<'a>  {
         fn to_css_declared<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self.text_decoration_line {
                 DeclaredValue::Value(ref line) => {
                     try!(line.to_css(dest));
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -339,16 +339,22 @@ impl NoCalcLength {
     }
 
     #[inline]
     /// Checks whether the length value is zero.
     pub fn is_zero(&self) -> bool {
         *self == NoCalcLength::Absolute(Au(0))
     }
 
+    #[inline]
+    /// Returns a `medium` length.
+    pub fn medium() -> NoCalcLength {
+        NoCalcLength::Absolute(Au::from_px(FONT_MEDIUM_PX))
+    }
+
     /// Get an absolute length from a px value.
     #[inline]
     pub fn from_px(px_value: CSSFloat) -> NoCalcLength {
         NoCalcLength::Absolute(Au((px_value * AU_PER_PX) as i32))
     }
 }
 
 /// An extension to `NoCalcLength` to parse `calc` expressions.
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -73,16 +73,37 @@ impl ToCss for CSSColor {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match self.authored {
             Some(ref s) => dest.write_str(s),
             None => self.parsed.to_css(dest),
         }
     }
 }
 
+impl CSSColor {
+    #[inline]
+    /// Returns currentcolor value.
+    pub fn currentcolor() -> CSSColor {
+        CSSColor {
+            parsed: cssparser::Color::CurrentColor,
+            authored: None,
+        }
+    }
+
+    #[inline]
+    /// Returns transparent value.
+    pub fn transparent() -> CSSColor {
+        CSSColor {
+            parsed: cssparser::Color::RGBA(cssparser::RGBA::transparent()),
+            // This should probably be "transparent", but maybe it doesn't matter.
+            authored: None,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Debug)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub struct CSSRGBA {
     pub parsed: cssparser::RGBA,
     pub authored: Option<Box<str>>,
 }
 
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1097,29 +1097,30 @@ pub extern "C" fn Servo_DeclarationBlock
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations:
                                                        RawServoDeclarationBlockBorrowed,
                                                        property: nsCSSPropertyID,
                                                        value: structs::nscolor) {
     use cssparser::Color;
     use style::gecko::values::convert_nscolor_to_rgba;
     use style::properties::{DeclaredValue, PropertyDeclaration, LonghandId};
-    use style::values::specified::{CSSColor, CSSRGBA};
+    use style::properties::longhands;
+    use style::values::specified::CSSColor;
 
     let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
     let long = get_longhand_from_id!(property);
     let rgba = convert_nscolor_to_rgba(value);
     let color = CSSColor { parsed: Color::RGBA(rgba), authored: None };
 
     let prop = match_wrap_declared! { long,
         BorderTopColor => color,
         BorderRightColor => color,
         BorderBottomColor => color,
         BorderLeftColor => color,
-        Color => CSSRGBA { parsed: rgba, authored: None },
+        Color => longhands::color::SpecifiedValue(color),
         BackgroundColor => color,
     };
     declarations.write().declarations.push((prop, Default::default()));
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(declarations:
                                                        RawServoDeclarationBlockBorrowed,
--- a/servo/tests/unit/style/parsing/background.rs
+++ b/servo/tests/unit/style/parsing/background.rs
@@ -15,116 +15,116 @@ use style::stylesheets::Origin;
 #[test]
 fn background_shorthand_should_parse_all_available_properties_when_specified() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("url(\"http://servo/test.png\") top center / 200px 200px repeat-x fixed padding-box \
         content-box red");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_image.unwrap(), parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
-    assert_eq!(result.background_position_x.unwrap(), parse_longhand!(background_position_x, "center"));
-    assert_eq!(result.background_position_y.unwrap(), parse_longhand!(background_position_y, "top"));
-    assert_eq!(result.background_size.unwrap(), parse_longhand!(background_size, "200px 200px"));
-    assert_eq!(result.background_repeat.unwrap(), parse_longhand!(background_repeat, "repeat-x"));
-    assert_eq!(result.background_attachment.unwrap(), parse_longhand!(background_attachment, "fixed"));
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "content-box"));
-    assert_eq!(result.background_color.unwrap(), parse_longhand!(background_color, "red"));
+    assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "center"));
+    assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "top"));
+    assert_eq!(result.background_size, parse_longhand!(background_size, "200px 200px"));
+    assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat-x"));
+    assert_eq!(result.background_attachment, parse_longhand!(background_attachment, "fixed"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "content-box"));
+    assert_eq!(result.background_color, parse_longhand!(background_color, "red"));
 }
 
 #[test]
 fn background_shorthand_should_parse_when_some_fields_set() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("14px 40px repeat-y");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_position_x.unwrap(), parse_longhand!(background_position_x, "14px"));
-    assert_eq!(result.background_position_y.unwrap(), parse_longhand!(background_position_y, "40px"));
-    assert_eq!(result.background_repeat.unwrap(), parse_longhand!(background_repeat, "repeat-y"));
+    assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "14px"));
+    assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "40px"));
+    assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat-y"));
 
     let mut parser = Parser::new("url(\"http://servo/test.png\") repeat blue");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_image.unwrap(), parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
-    assert_eq!(result.background_repeat.unwrap(), parse_longhand!(background_repeat, "repeat"));
-    assert_eq!(result.background_color.unwrap(), parse_longhand!(background_color, "blue"));
+    assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "repeat"));
+    assert_eq!(result.background_color, parse_longhand!(background_color, "blue"));
 
     let mut parser = Parser::new("padding-box");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "padding-box"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
 
     let mut parser = Parser::new("url(\"http://servo/test.png\")");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_image.unwrap(), parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\")"));
 }
 
 #[test]
 fn background_shorthand_should_parse_comma_separated_declarations() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("url(\"http://servo/test.png\") top left no-repeat, url(\"http://servo/test.png\") \
         center / 100% 100% no-repeat, white");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_image.unwrap(), parse_longhand!(background_image, "url(\"http://servo/test.png\"), \
+    assert_eq!(result.background_image, parse_longhand!(background_image, "url(\"http://servo/test.png\"), \
         url(\"http://servo/test.png\"), none"));
-    assert_eq!(result.background_position_x.unwrap(), parse_longhand!(background_position_x, "left, center, 0%"));
-    assert_eq!(result.background_position_y.unwrap(), parse_longhand!(background_position_y, "top, center, 0%"));
-    assert_eq!(result.background_repeat.unwrap(), parse_longhand!(background_repeat, "no-repeat, no-repeat, repeat"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "border-box, border-box, border-box"));
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box, padding-box, \
+    assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "left, center, 0%"));
+    assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "top, center, 0%"));
+    assert_eq!(result.background_repeat, parse_longhand!(background_repeat, "no-repeat, no-repeat, repeat"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "border-box, border-box, border-box"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box, padding-box, \
         padding-box"));
-    assert_eq!(result.background_size.unwrap(), parse_longhand!(background_size, "auto auto, 100% 100%, auto auto"));
-    assert_eq!(result.background_attachment.unwrap(), parse_longhand!(background_attachment, "scroll, scroll, scroll"));
-    assert_eq!(result.background_color.unwrap(), parse_longhand!(background_color, "white"));
+    assert_eq!(result.background_size, parse_longhand!(background_size, "auto auto, 100% 100%, auto auto"));
+    assert_eq!(result.background_attachment, parse_longhand!(background_attachment, "scroll, scroll, scroll"));
+    assert_eq!(result.background_color, parse_longhand!(background_color, "white"));
 }
 
 #[test]
 fn background_shorthand_should_parse_position_and_size_correctly() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("7px 4px");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_position_x.unwrap(), parse_longhand!(background_position_x, "7px"));
-    assert_eq!(result.background_position_y.unwrap(), parse_longhand!(background_position_y, "4px"));
+    assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "7px"));
+    assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "4px"));
 
     let mut parser = Parser::new("7px 4px / 30px 20px");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_position_x.unwrap(), parse_longhand!(background_position_x, "7px"));
-    assert_eq!(result.background_position_y.unwrap(), parse_longhand!(background_position_y, "4px"));
-    assert_eq!(result.background_size.unwrap(), parse_longhand!(background_size, "30px 20px"));
+    assert_eq!(result.background_position_x, parse_longhand!(background_position_x, "7px"));
+    assert_eq!(result.background_position_y, parse_longhand!(background_position_y, "4px"));
+    assert_eq!(result.background_size, parse_longhand!(background_size, "30px 20px"));
 
     let mut parser = Parser::new("/ 30px 20px");
     assert!(background::parse_value(&context, &mut parser).is_err());
 
     let mut parser = Parser::new("repeat-x / 30px 20px");
     assert!(background::parse_value(&context, &mut parser).is_err());
 }
 
 #[test]
 fn background_shorthand_should_parse_origin_and_clip_correctly() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("padding-box content-box");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "content-box"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "content-box"));
 
     let mut parser = Parser::new("padding-box padding-box");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "padding-box"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
 
     let mut parser = Parser::new("padding-box");
     let result = background::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.background_origin.unwrap(), parse_longhand!(background_origin, "padding-box"));
-    assert_eq!(result.background_clip.unwrap(), parse_longhand!(background_clip, "padding-box"));
+    assert_eq!(result.background_origin, parse_longhand!(background_origin, "padding-box"));
+    assert_eq!(result.background_clip, parse_longhand!(background_clip, "padding-box"));
 }
--- a/servo/tests/unit/style/parsing/border.rs
+++ b/servo/tests/unit/style/parsing/border.rs
@@ -15,82 +15,82 @@ use style_traits::ToCss;
 #[test]
 fn border_image_shorthand_should_parse_when_all_properties_specified() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("linear-gradient(red, blue) 30 30% 45 fill / 20px 40px / 10px \
                                  round stretch");
     let result = border_image::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.border_image_source.unwrap(),
+    assert_eq!(result.border_image_source,
                parse_longhand!(border_image_source, "linear-gradient(red, blue)"));
-    assert_eq!(result.border_image_slice.unwrap(), parse_longhand!(border_image_slice, "30 30% 45 fill"));
-    assert_eq!(result.border_image_width.unwrap(), parse_longhand!(border_image_width, "20px 40px"));
-    assert_eq!(result.border_image_outset.unwrap(), parse_longhand!(border_image_outset, "10px"));
-    assert_eq!(result.border_image_repeat.unwrap(), parse_longhand!(border_image_repeat, "round stretch"));
+    assert_eq!(result.border_image_slice, parse_longhand!(border_image_slice, "30 30% 45 fill"));
+    assert_eq!(result.border_image_width, parse_longhand!(border_image_width, "20px 40px"));
+    assert_eq!(result.border_image_outset, parse_longhand!(border_image_outset, "10px"));
+    assert_eq!(result.border_image_repeat, parse_longhand!(border_image_repeat, "round stretch"));
 }
 
 #[test]
 fn border_image_shorthand_should_parse_without_width() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("linear-gradient(red, blue) 30 30% 45 fill / / 10px round stretch");
     let result = border_image::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.border_image_source.unwrap(),
+    assert_eq!(result.border_image_source,
                parse_longhand!(border_image_source, "linear-gradient(red, blue)"));
-    assert_eq!(result.border_image_slice.unwrap(), parse_longhand!(border_image_slice, "30 30% 45 fill"));
-    assert_eq!(result.border_image_outset.unwrap(), parse_longhand!(border_image_outset, "10px"));
-    assert_eq!(result.border_image_repeat.unwrap(), parse_longhand!(border_image_repeat, "round stretch"));
-    assert_eq!(result.border_image_width.unwrap(), border_image_width::get_initial_specified_value());
+    assert_eq!(result.border_image_slice, parse_longhand!(border_image_slice, "30 30% 45 fill"));
+    assert_eq!(result.border_image_outset, parse_longhand!(border_image_outset, "10px"));
+    assert_eq!(result.border_image_repeat, parse_longhand!(border_image_repeat, "round stretch"));
+    assert_eq!(result.border_image_width, border_image_width::get_initial_specified_value());
 }
 
 #[test]
 fn border_image_shorthand_should_parse_without_outset() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("linear-gradient(red, blue) 30 30% 45 fill / 20px 40px round");
     let result = border_image::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.border_image_source.unwrap(),
+    assert_eq!(result.border_image_source,
                parse_longhand!(border_image_source, "linear-gradient(red, blue)"));
-    assert_eq!(result.border_image_slice.unwrap(), parse_longhand!(border_image_slice, "30 30% 45 fill"));
-    assert_eq!(result.border_image_width.unwrap(), parse_longhand!(border_image_width, "20px 40px"));
-    assert_eq!(result.border_image_repeat.unwrap(), parse_longhand!(border_image_repeat, "round"));
-    assert_eq!(result.border_image_outset.unwrap(), border_image_outset::get_initial_specified_value());
+    assert_eq!(result.border_image_slice, parse_longhand!(border_image_slice, "30 30% 45 fill"));
+    assert_eq!(result.border_image_width, parse_longhand!(border_image_width, "20px 40px"));
+    assert_eq!(result.border_image_repeat, parse_longhand!(border_image_repeat, "round"));
+    assert_eq!(result.border_image_outset, border_image_outset::get_initial_specified_value());
 }
 
 #[test]
 fn border_image_shorthand_should_parse_without_width_or_outset() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("linear-gradient(red, blue) 30 30% 45 fill round");
     let result = border_image::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.border_image_source.unwrap(),
+    assert_eq!(result.border_image_source,
                parse_longhand!(border_image_source, "linear-gradient(red, blue)"));
-    assert_eq!(result.border_image_slice.unwrap(), parse_longhand!(border_image_slice, "30 30% 45 fill"));
-    assert_eq!(result.border_image_repeat.unwrap(), parse_longhand!(border_image_repeat, "round"));
-    assert_eq!(result.border_image_width.unwrap(), border_image_width::get_initial_specified_value());
-    assert_eq!(result.border_image_outset.unwrap(), border_image_outset::get_initial_specified_value());
+    assert_eq!(result.border_image_slice, parse_longhand!(border_image_slice, "30 30% 45 fill"));
+    assert_eq!(result.border_image_repeat, parse_longhand!(border_image_repeat, "round"));
+    assert_eq!(result.border_image_width, border_image_width::get_initial_specified_value());
+    assert_eq!(result.border_image_outset, border_image_outset::get_initial_specified_value());
 }
 
 #[test]
 fn border_image_shorthand_should_parse_with_just_source() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("linear-gradient(red, blue)");
     let result = border_image::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.border_image_source.unwrap(),
+    assert_eq!(result.border_image_source,
                parse_longhand!(border_image_source, "linear-gradient(red, blue)"));
-    assert_eq!(result.border_image_slice.unwrap(), border_image_slice::get_initial_specified_value());
-    assert_eq!(result.border_image_width.unwrap(), border_image_width::get_initial_specified_value());
-    assert_eq!(result.border_image_outset.unwrap(), border_image_outset::get_initial_specified_value());
-    assert_eq!(result.border_image_repeat.unwrap(), border_image_repeat::get_initial_specified_value());
+    assert_eq!(result.border_image_slice, border_image_slice::get_initial_specified_value());
+    assert_eq!(result.border_image_width, border_image_width::get_initial_specified_value());
+    assert_eq!(result.border_image_outset, border_image_outset::get_initial_specified_value());
+    assert_eq!(result.border_image_repeat, border_image_repeat::get_initial_specified_value());
 }
 
 #[test]
 fn border_image_outset_should_error_on_negative_length() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("-1em");
     let result = border_image_outset::parse(&context, &mut parser);
--- a/servo/tests/unit/style/parsing/inherited_text.rs
+++ b/servo/tests/unit/style/parsing/inherited_text.rs
@@ -110,24 +110,24 @@ fn webkit_text_stroke_shorthand_should_p
     use style::properties::longhands::_webkit_text_stroke_width;
     use style::properties::shorthands::_webkit_text_stroke;
 
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
 
     let mut parser = Parser::new("thin red");
     let result = _webkit_text_stroke::parse_value(&context, &mut parser).unwrap();
-    assert_eq!(result._webkit_text_stroke_color.unwrap(), parse_longhand!(_webkit_text_stroke_color, "red"));
-    assert_eq!(result._webkit_text_stroke_width.unwrap(), parse_longhand!(_webkit_text_stroke_width, "thin"));
+    assert_eq!(result._webkit_text_stroke_color, parse_longhand!(_webkit_text_stroke_color, "red"));
+    assert_eq!(result._webkit_text_stroke_width, parse_longhand!(_webkit_text_stroke_width, "thin"));
 
     // ensure its no longer sensitive to order
     let mut parser = Parser::new("red thin");
     let result = _webkit_text_stroke::parse_value(&context, &mut parser).unwrap();
-    assert_eq!(result._webkit_text_stroke_color.unwrap(), parse_longhand!(_webkit_text_stroke_color, "red"));
-    assert_eq!(result._webkit_text_stroke_width.unwrap(), parse_longhand!(_webkit_text_stroke_width, "thin"));
+    assert_eq!(result._webkit_text_stroke_color, parse_longhand!(_webkit_text_stroke_color, "red"));
+    assert_eq!(result._webkit_text_stroke_width, parse_longhand!(_webkit_text_stroke_width, "thin"));
 }
 
 #[test]
 fn line_height_should_return_number_on_plain_zero() {
     use media_queries::CSSErrorReporterTest;
     use servo_url::ServoUrl;
     use style::properties::longhands::line_height;
 
--- a/servo/tests/unit/style/parsing/mask.rs
+++ b/servo/tests/unit/style/parsing/mask.rs
@@ -14,101 +14,101 @@ use style::stylesheets::Origin;
 #[test]
 fn mask_shorthand_should_parse_all_available_properties_when_specified() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("url(\"http://servo/test.png\") luminance 7px 4px / 70px 50px \
                                  repeat-x padding-box border-box subtract");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_image.unwrap(), parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
-    assert_eq!(result.mask_mode.unwrap(), parse_longhand!(mask_mode, "luminance"));
-    assert_eq!(result.mask_position_x.unwrap(), parse_longhand!(mask_position_x, "7px"));
-    assert_eq!(result.mask_position_y.unwrap(), parse_longhand!(mask_position_y, "4px"));
-    assert_eq!(result.mask_size.unwrap(), parse_longhand!(mask_size, "70px 50px"));
-    assert_eq!(result.mask_repeat.unwrap(), parse_longhand!(mask_repeat, "repeat-x"));
-    assert_eq!(result.mask_origin.unwrap(), parse_longhand!(mask_origin, "padding-box"));
-    assert_eq!(result.mask_clip.unwrap(), parse_longhand!(mask_clip, "border-box"));
-    assert_eq!(result.mask_composite.unwrap(), parse_longhand!(mask_composite, "subtract"));
+    assert_eq!(result.mask_image, parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.mask_mode, parse_longhand!(mask_mode, "luminance"));
+    assert_eq!(result.mask_position_x, parse_longhand!(mask_position_x, "7px"));
+    assert_eq!(result.mask_position_y, parse_longhand!(mask_position_y, "4px"));
+    assert_eq!(result.mask_size, parse_longhand!(mask_size, "70px 50px"));
+    assert_eq!(result.mask_repeat, parse_longhand!(mask_repeat, "repeat-x"));
+    assert_eq!(result.mask_origin, parse_longhand!(mask_origin, "padding-box"));
+    assert_eq!(result.mask_clip, parse_longhand!(mask_clip, "border-box"));
+    assert_eq!(result.mask_composite, parse_longhand!(mask_composite, "subtract"));
 }
 
 #[test]
 fn mask_shorthand_should_parse_when_some_fields_set() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("14px 40px repeat-y");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_position_x.unwrap(), parse_longhand!(mask_position_x, "14px"));
-    assert_eq!(result.mask_position_y.unwrap(), parse_longhand!(mask_position_y, "40px"));
-    assert_eq!(result.mask_repeat.unwrap(), parse_longhand!(mask_repeat, "repeat-y"));
+    assert_eq!(result.mask_position_x, parse_longhand!(mask_position_x, "14px"));
+    assert_eq!(result.mask_position_y, parse_longhand!(mask_position_y, "40px"));
+    assert_eq!(result.mask_repeat, parse_longhand!(mask_repeat, "repeat-y"));
 
     let mut parser = Parser::new("url(\"http://servo/test.png\") repeat add");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_image.unwrap(), parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
-    assert_eq!(result.mask_repeat.unwrap(), parse_longhand!(mask_repeat, "repeat"));
-    assert_eq!(result.mask_composite.unwrap(), parse_longhand!(mask_composite, "add"));
+    assert_eq!(result.mask_image, parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.mask_repeat, parse_longhand!(mask_repeat, "repeat"));
+    assert_eq!(result.mask_composite, parse_longhand!(mask_composite, "add"));
 
     let mut parser = Parser::new("intersect");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_composite.unwrap(), parse_longhand!(mask_composite, "intersect"));
+    assert_eq!(result.mask_composite, parse_longhand!(mask_composite, "intersect"));
 
     let mut parser = Parser::new("url(\"http://servo/test.png\")");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_image.unwrap(), parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
+    assert_eq!(result.mask_image, parse_longhand!(mask_image, "url(\"http://servo/test.png\")"));
 }
 
 #[test]
 fn mask_shorthand_should_parse_position_and_size_correctly() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("7px 4px");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_position_x.unwrap(), parse_longhand!(mask_position_x, "7px"));
-    assert_eq!(result.mask_position_y.unwrap(), parse_longhand!(mask_position_y, "4px"));
+    assert_eq!(result.mask_position_x, parse_longhand!(mask_position_x, "7px"));
+    assert_eq!(result.mask_position_y, parse_longhand!(mask_position_y, "4px"));
 
     let mut parser = Parser::new("7px 4px / 30px 20px");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_position_x.unwrap(), parse_longhand!(mask_position_x, "7px"));
-    assert_eq!(result.mask_position_y.unwrap(), parse_longhand!(mask_position_y, "4px"));
-    assert_eq!(result.mask_size.unwrap(), parse_longhand!(mask_size, "30px 20px"));
+    assert_eq!(result.mask_position_x, parse_longhand!(mask_position_x, "7px"));
+    assert_eq!(result.mask_position_y, parse_longhand!(mask_position_y, "4px"));
+    assert_eq!(result.mask_size, parse_longhand!(mask_size, "30px 20px"));
 
     let mut parser = Parser::new("/ 30px 20px");
     assert!(mask::parse_value(&context, &mut parser).is_err());
 
     let mut parser = Parser::new("match-source repeat-x / 30px 20px");
     assert!(mask::parse_value(&context, &mut parser).is_err());
 }
 
 #[test]
 fn mask_shorthand_should_parse_origin_and_clip_correctly() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("padding-box content-box");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_origin.unwrap(), parse_longhand!(mask_origin, "padding-box"));
-    assert_eq!(result.mask_clip.unwrap(), parse_longhand!(mask_clip, "content-box"));
+    assert_eq!(result.mask_origin, parse_longhand!(mask_origin, "padding-box"));
+    assert_eq!(result.mask_clip, parse_longhand!(mask_clip, "content-box"));
 
     let mut parser = Parser::new("padding-box padding-box");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_origin.unwrap(), parse_longhand!(mask_origin, "padding-box"));
-    assert_eq!(result.mask_clip.unwrap(), parse_longhand!(mask_clip, "padding-box"));
+    assert_eq!(result.mask_origin, parse_longhand!(mask_origin, "padding-box"));
+    assert_eq!(result.mask_clip, parse_longhand!(mask_clip, "padding-box"));
 
     let mut parser = Parser::new("padding-box");
     let result = mask::parse_value(&context, &mut parser).unwrap();
 
-    assert_eq!(result.mask_origin.unwrap(), parse_longhand!(mask_origin, "padding-box"));
-    assert_eq!(result.mask_clip.unwrap(), parse_longhand!(mask_clip, "padding-box"));
+    assert_eq!(result.mask_origin, parse_longhand!(mask_origin, "padding-box"));
+    assert_eq!(result.mask_clip, parse_longhand!(mask_clip, "padding-box"));
 }
 
 #[test]
 fn mask_shorthand_should_parse_mode_everywhere() {
     let url = ServoUrl::parse("http://localhost").unwrap();
     let context = ParserContext::new(Origin::Author, &url, Box::new(CSSErrorReporterTest));
     let mut parser = Parser::new("luminance 7px 4px repeat-x padding-box");
     assert!(mask::parse_value(&context, &mut parser).is_ok());