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 345151 ff962f4a7c6a3a8c95c369332f8c2060efd754e9
parent 345150 ace3041492115096392a36c13240e3c0111eed47
child 345152 eb8f83fd7a7cffd77f49d4767b428e5674fb5cf5
push id31433
push usercbook@mozilla.com
push dateWed, 01 Mar 2017 10:39:33 +0000
treeherdermozilla-central@e1b741382dc0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersManishearth
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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());