Bug 1345688 - WIP. draft
authorCameron McCormack <cam@mcc.id.au>
Tue, 14 Nov 2017 17:44:25 +0800
changeset 697648 6d653d94dfac4f1a14288f5f8e6ba7a2d4004d07
parent 696951 6371e71153c8c3d32d31c8eb92ac296f353dd860
child 740169 1a3e4faba8fda3129fe6ed99729ba3ab8205f169
push id89056
push userbmo:cam@mcc.id.au
push dateTue, 14 Nov 2017 09:48:16 +0000
bugs1345688
milestone59.0a1
Bug 1345688 - WIP. MozReview-Commit-ID: 2djHubYWSOx
layout/style/nsStyleConsts.h
servo/components/style/properties/data.py
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_box.mako.rs
servo/components/style/properties/longhand/inherited_svg.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/text.mako.rs
servo/components/style/values/specified/mod.rs
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -135,18 +135,18 @@ enum class StyleFloat : uint8_t {
 // float-edge
 enum class StyleFloatEdge : uint8_t {
   ContentBox,
   MarginBox,
 };
 
 // Hyphens
 enum class StyleHyphens : uint8_t {
+  Manual,
   None,
-  Manual,
   Auto,
 };
 
 // <shape-radius> for <basic-shape>
 enum class StyleShapeRadius : uint8_t {
   ClosestSide,
   FarthestSide,
 };
@@ -156,62 +156,62 @@ enum class StyleShapeSourceType : uint8_
   None,
   URL,
   Shape,
   Box,
 };
 
 // -moz-stack-sizing
 enum class StyleStackSizing : uint8_t {
+  StretchToFit,
   Ignore,
-  StretchToFit,
   IgnoreHorizontal,
   IgnoreVertical,
 };
 
 // text-justify
 enum class StyleTextJustify : uint8_t {
+  Auto,
   None,
-  Auto,
   InterWord,
   InterCharacter,
 };
 
 // user-focus
 enum class StyleUserFocus : uint8_t {
   None,
   Ignore,
   Normal,
-  SelectAll,
+  SelectAfter,
   SelectBefore,
-  SelectAfter,
+  SelectMenu,
   SelectSame,
-  SelectMenu,
+  SelectAll,
 };
 
 // user-select
 enum class StyleUserSelect : uint8_t {
+  Auto,     // internal value - please use nsFrame::IsSelectable()
+  Text,
   None,
-  Text,
+  All,
   Element,
   Elements,
-  All,
   Toggle,
   TriState,
-  Auto,     // internal value - please use nsFrame::IsSelectable()
   MozAll,   // force selection of all children, unless an ancestor has NONE set - bug 48096
   MozText,  // Like TEXT, except that it won't get overridden by ancestors having ALL.
 };
 
 // user-input
 enum class StyleUserInput : uint8_t {
+  Auto,
   None,
   Enabled,
   Disabled,
-  Auto,
 };
 
 // user-modify
 enum class StyleUserModify : uint8_t {
   ReadOnly,
   ReadWrite,
   WriteOnly,
 };
@@ -309,35 +309,35 @@ enum class StyleImageLayerRepeat : uint8
 #define NS_STYLE_MASK_MODE_MATCH_SOURCE         2
 
 // See nsStyleBackground
 #define NS_STYLE_BG_INLINE_POLICY_EACH_BOX      0
 #define NS_STYLE_BG_INLINE_POLICY_CONTINUOUS    1
 #define NS_STYLE_BG_INLINE_POLICY_BOUNDING_BOX  2
 
 // See nsStyleTable
-#define NS_STYLE_BORDER_COLLAPSE                0
-#define NS_STYLE_BORDER_SEPARATE                1
+#define NS_STYLE_BORDER_SEPARATE                0
+#define NS_STYLE_BORDER_COLLAPSE                1
 
 // Possible enumerated specified values of border-*-width, used by nsCSSMargin
 #define NS_STYLE_BORDER_WIDTH_THIN              0
 #define NS_STYLE_BORDER_WIDTH_MEDIUM            1
 #define NS_STYLE_BORDER_WIDTH_THICK             2
 // XXX chopping block #define NS_STYLE_BORDER_WIDTH_LENGTH_VALUE      3
 
 // See nsStyleBorder mBorderStyle
 #define NS_STYLE_BORDER_STYLE_NONE              0
-#define NS_STYLE_BORDER_STYLE_GROOVE            1
-#define NS_STYLE_BORDER_STYLE_RIDGE             2
-#define NS_STYLE_BORDER_STYLE_DOTTED            3
-#define NS_STYLE_BORDER_STYLE_DASHED            4
-#define NS_STYLE_BORDER_STYLE_SOLID             5
-#define NS_STYLE_BORDER_STYLE_DOUBLE            6
-#define NS_STYLE_BORDER_STYLE_INSET             7
-#define NS_STYLE_BORDER_STYLE_OUTSET            8
+#define NS_STYLE_BORDER_STYLE_INSET             1
+#define NS_STYLE_BORDER_STYLE_GROOVE            2
+#define NS_STYLE_BORDER_STYLE_OUTSET            3
+#define NS_STYLE_BORDER_STYLE_RIDGE             4
+#define NS_STYLE_BORDER_STYLE_DOTTED            5
+#define NS_STYLE_BORDER_STYLE_DASHED            6
+#define NS_STYLE_BORDER_STYLE_SOLID             7
+#define NS_STYLE_BORDER_STYLE_DOUBLE            8
 #define NS_STYLE_BORDER_STYLE_HIDDEN            9
 #define NS_STYLE_BORDER_STYLE_AUTO              10 // for outline-style only
 
 // See nsStyleBorder mBorderImage
 #define NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH    0
 #define NS_STYLE_BORDER_IMAGE_REPEAT_REPEAT     1
 #define NS_STYLE_BORDER_IMAGE_REPEAT_ROUND      2
 #define NS_STYLE_BORDER_IMAGE_REPEAT_SPACE      3
@@ -672,18 +672,18 @@ enum class StyleGridTrackBreadth : uint8
 // See nsStylePosition::mWidth, mMinWidth, mMaxWidth
 #define NS_STYLE_WIDTH_MAX_CONTENT              0
 #define NS_STYLE_WIDTH_MIN_CONTENT              1
 #define NS_STYLE_WIDTH_FIT_CONTENT              2
 #define NS_STYLE_WIDTH_AVAILABLE                3
 
 // See nsStyleDisplay.mPosition
 #define NS_STYLE_POSITION_STATIC                0
-#define NS_STYLE_POSITION_RELATIVE              1
-#define NS_STYLE_POSITION_ABSOLUTE              2
+#define NS_STYLE_POSITION_ABSOLUTE              1
+#define NS_STYLE_POSITION_RELATIVE              2
 #define NS_STYLE_POSITION_FIXED                 3
 #define NS_STYLE_POSITION_STICKY                4
 
 // See nsStyleEffects.mClip, mClipFlags
 #define NS_STYLE_CLIP_AUTO                      0x00
 #define NS_STYLE_CLIP_RECT                      0x01
 #define NS_STYLE_CLIP_TYPE_MASK                 0x0F
 #define NS_STYLE_CLIP_LEFT_AUTO                 0x10
@@ -739,33 +739,33 @@ enum class StyleGridTrackBreadth : uint8
 // These styles are handled as custom styles defined in counterstyles.css.
 // They are preserved here only for html attribute map.
 #define NS_STYLE_LIST_STYLE_LOWER_ROMAN           100
 #define NS_STYLE_LIST_STYLE_UPPER_ROMAN           101
 #define NS_STYLE_LIST_STYLE_LOWER_ALPHA           102
 #define NS_STYLE_LIST_STYLE_UPPER_ALPHA           103
 
 // See nsStyleList
-#define NS_STYLE_LIST_STYLE_POSITION_INSIDE     0
-#define NS_STYLE_LIST_STYLE_POSITION_OUTSIDE    1
+#define NS_STYLE_LIST_STYLE_POSITION_OUTSIDE    0
+#define NS_STYLE_LIST_STYLE_POSITION_INSIDE     1
 
 // See nsStyleMargin
 #define NS_STYLE_MARGIN_SIZE_AUTO               0
 
 // See nsStyleVisibility
-#define NS_STYLE_POINTER_EVENTS_NONE            0
-#define NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED  1
-#define NS_STYLE_POINTER_EVENTS_VISIBLEFILL     2
-#define NS_STYLE_POINTER_EVENTS_VISIBLESTROKE   3
-#define NS_STYLE_POINTER_EVENTS_VISIBLE         4
-#define NS_STYLE_POINTER_EVENTS_PAINTED         5
-#define NS_STYLE_POINTER_EVENTS_FILL            6
-#define NS_STYLE_POINTER_EVENTS_STROKE          7
-#define NS_STYLE_POINTER_EVENTS_ALL             8
-#define NS_STYLE_POINTER_EVENTS_AUTO            9
+#define NS_STYLE_POINTER_EVENTS_AUTO            0
+#define NS_STYLE_POINTER_EVENTS_NONE            1
+#define NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED  2
+#define NS_STYLE_POINTER_EVENTS_VISIBLEFILL     3
+#define NS_STYLE_POINTER_EVENTS_VISIBLESTROKE   4
+#define NS_STYLE_POINTER_EVENTS_VISIBLE         5
+#define NS_STYLE_POINTER_EVENTS_PAINTED         6
+#define NS_STYLE_POINTER_EVENTS_FILL            7
+#define NS_STYLE_POINTER_EVENTS_STROKE          8
+#define NS_STYLE_POINTER_EVENTS_ALL             9
 
 // See nsStyleVisibility.mImageOrientationType
 #define NS_STYLE_IMAGE_ORIENTATION_FLIP         0
 #define NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE   1
 
 // See nsStyleDisplay
 #define NS_STYLE_ISOLATION_AUTO                 0
 #define NS_STYLE_ISOLATION_ISOLATE              1
@@ -810,34 +810,34 @@ enum class StyleGridTrackBreadth : uint8
 #define NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH 0x04
 #define NS_STYLE_TEXT_DECORATION_LINE_BLINK        0x08
 // OVERRIDE_ALL does not occur in stylesheets; it only comes from HTML
 // attribute mapping (and thus appears in computed data)
 #define NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL 0x10
 #define NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK   (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE | NS_STYLE_TEXT_DECORATION_LINE_OVERLINE | NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH)
 
 // See nsStyleText
-#define NS_STYLE_TEXT_DECORATION_STYLE_NONE     0 // not in CSS spec, mapped to -moz-none
-#define NS_STYLE_TEXT_DECORATION_STYLE_DOTTED   1
-#define NS_STYLE_TEXT_DECORATION_STYLE_DASHED   2
-#define NS_STYLE_TEXT_DECORATION_STYLE_SOLID    3
-#define NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE   4
-#define NS_STYLE_TEXT_DECORATION_STYLE_WAVY     5
-#define NS_STYLE_TEXT_DECORATION_STYLE_MAX      NS_STYLE_TEXT_DECORATION_STYLE_WAVY
+#define NS_STYLE_TEXT_DECORATION_STYLE_SOLID    0
+#define NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE   1
+#define NS_STYLE_TEXT_DECORATION_STYLE_DOTTED   2
+#define NS_STYLE_TEXT_DECORATION_STYLE_DASHED   3
+#define NS_STYLE_TEXT_DECORATION_STYLE_WAVY     4
+#define NS_STYLE_TEXT_DECORATION_STYLE_NONE     5 // not in CSS spec, mapped to -moz-none
+#define NS_STYLE_TEXT_DECORATION_STYLE_MAX      NS_STYLE_TEXT_DECORATION_STYLE_NONE
 
 // See nsStyleTextOverflow
 #define NS_STYLE_TEXT_OVERFLOW_CLIP     0
 #define NS_STYLE_TEXT_OVERFLOW_ELLIPSIS 1
 #define NS_STYLE_TEXT_OVERFLOW_STRING   2
 
 // See nsStyleText
 #define NS_STYLE_TEXT_TRANSFORM_NONE            0
 #define NS_STYLE_TEXT_TRANSFORM_CAPITALIZE      1
-#define NS_STYLE_TEXT_TRANSFORM_LOWERCASE       2
-#define NS_STYLE_TEXT_TRANSFORM_UPPERCASE       3
+#define NS_STYLE_TEXT_TRANSFORM_UPPERCASE       2
+#define NS_STYLE_TEXT_TRANSFORM_LOWERCASE       3
 #define NS_STYLE_TEXT_TRANSFORM_FULL_WIDTH      4
 
 // See nsStyleDisplay
 #define NS_STYLE_TOUCH_ACTION_NONE            (1 << 0)
 #define NS_STYLE_TOUCH_ACTION_AUTO            (1 << 1)
 #define NS_STYLE_TOUCH_ACTION_PAN_X           (1 << 2)
 #define NS_STYLE_TOUCH_ACTION_PAN_Y           (1 << 3)
 #define NS_STYLE_TOUCH_ACTION_MANIPULATION    (1 << 4)
@@ -865,18 +865,18 @@ enum class StyleGridTrackBreadth : uint8
 #define NS_STYLE_VERTICAL_ALIGN_TOP                  17
 #define NS_STYLE_VERTICAL_ALIGN_TEXT_TOP             18
 #define NS_STYLE_VERTICAL_ALIGN_MIDDLE               19
 #define NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM          20
 #define NS_STYLE_VERTICAL_ALIGN_BOTTOM               21
 #define NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE 22
 
 // See nsStyleVisibility
-#define NS_STYLE_VISIBILITY_HIDDEN              0
-#define NS_STYLE_VISIBILITY_VISIBLE             1
+#define NS_STYLE_VISIBILITY_VISIBLE             0
+#define NS_STYLE_VISIBILITY_HIDDEN              1
 #define NS_STYLE_VISIBILITY_COLLAPSE            2
 
 // See nsStyleText
 #define NS_STYLE_TABSIZE_INITIAL                8
 
 // See nsStyleText
 enum class StyleWhiteSpace : uint8_t {
   Normal = 0,
@@ -892,29 +892,29 @@ enum class StyleWhiteSpace : uint8_t {
 #define NS_STYLE_WORDBREAK_BREAK_ALL            1
 #define NS_STYLE_WORDBREAK_KEEP_ALL             2
 
 // See nsStyleText
 #define NS_STYLE_OVERFLOWWRAP_NORMAL            0
 #define NS_STYLE_OVERFLOWWRAP_BREAK_WORD        1
 
 // ruby-align, see nsStyleText
-#define NS_STYLE_RUBY_ALIGN_START               0
-#define NS_STYLE_RUBY_ALIGN_CENTER              1
-#define NS_STYLE_RUBY_ALIGN_SPACE_BETWEEN       2
-#define NS_STYLE_RUBY_ALIGN_SPACE_AROUND        3
+#define NS_STYLE_RUBY_ALIGN_SPACE_AROUND        0
+#define NS_STYLE_RUBY_ALIGN_START               1
+#define NS_STYLE_RUBY_ALIGN_CENTER              2
+#define NS_STYLE_RUBY_ALIGN_SPACE_BETWEEN       3
 
 // ruby-position, see nsStyleText
 #define NS_STYLE_RUBY_POSITION_OVER             0
 #define NS_STYLE_RUBY_POSITION_UNDER            1
 #define NS_STYLE_RUBY_POSITION_INTER_CHARACTER  2 /* placeholder, not yet parsed */
 
 // See nsStyleText
-#define NS_STYLE_TEXT_SIZE_ADJUST_NONE          0
-#define NS_STYLE_TEXT_SIZE_ADJUST_AUTO          1
+#define NS_STYLE_TEXT_SIZE_ADJUST_AUTO          0
+#define NS_STYLE_TEXT_SIZE_ADJUST_NONE          1
 
 // See nsStyleText
 #define NS_STYLE_TEXT_ORIENTATION_MIXED          0
 #define NS_STYLE_TEXT_ORIENTATION_UPRIGHT        1
 #define NS_STYLE_TEXT_ORIENTATION_SIDEWAYS       2
 
 // See nsStyleText
 #define NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE        0
@@ -932,26 +932,26 @@ enum class StyleWhiteSpace : uint8_t {
 #define NS_STYLE_UNICODE_BIDI_ISOLATE           0x2
 #define NS_STYLE_UNICODE_BIDI_BIDI_OVERRIDE     0x4
 #define NS_STYLE_UNICODE_BIDI_ISOLATE_OVERRIDE  0x6
 #define NS_STYLE_UNICODE_BIDI_PLAINTEXT         0x8
 
 #define NS_STYLE_TABLE_LAYOUT_AUTO              0
 #define NS_STYLE_TABLE_LAYOUT_FIXED             1
 
-#define NS_STYLE_TABLE_EMPTY_CELLS_HIDE            0
-#define NS_STYLE_TABLE_EMPTY_CELLS_SHOW            1
+#define NS_STYLE_TABLE_EMPTY_CELLS_SHOW            0
+#define NS_STYLE_TABLE_EMPTY_CELLS_HIDE            1
 
 // Constants for the caption-side property. Note that despite having "physical"
 // names, these are actually interpreted according to the table's writing-mode:
 // TOP and BOTTOM are treated as block-start and -end respectively, and LEFT
 // and RIGHT are treated as line-left and -right.
 #define NS_STYLE_CAPTION_SIDE_TOP               0
-#define NS_STYLE_CAPTION_SIDE_RIGHT             1
-#define NS_STYLE_CAPTION_SIDE_BOTTOM            2
+#define NS_STYLE_CAPTION_SIDE_BOTTOM            1
+#define NS_STYLE_CAPTION_SIDE_RIGHT             2
 #define NS_STYLE_CAPTION_SIDE_LEFT              3
 #define NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE       4
 #define NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE    5
 
 // constants for cell "scope" attribute
 #define NS_STYLE_CELL_SCOPE_ROW                 0
 #define NS_STYLE_CELL_SCOPE_COL                 1
 #define NS_STYLE_CELL_SCOPE_ROWGROUP            2
@@ -973,18 +973,18 @@ enum class StyleWhiteSpace : uint8_t {
 #define NS_STYLE_PAGE_BREAK_AVOID               2
 #define NS_STYLE_PAGE_BREAK_LEFT                3
 #define NS_STYLE_PAGE_BREAK_RIGHT               4
 
 // See nsStyleColumn
 #define NS_STYLE_COLUMN_COUNT_AUTO              0
 #define NS_STYLE_COLUMN_COUNT_UNLIMITED         (-1)
 
-#define NS_STYLE_COLUMN_FILL_AUTO               0
-#define NS_STYLE_COLUMN_FILL_BALANCE            1
+#define NS_STYLE_COLUMN_FILL_BALANCE            0
+#define NS_STYLE_COLUMN_FILL_AUTO               1
 
 #define NS_STYLE_COLUMN_SPAN_NONE               0
 #define NS_STYLE_COLUMN_SPAN_ALL                1
 
 // See nsStyleUIReset
 #define NS_STYLE_IME_MODE_AUTO                  0
 #define NS_STYLE_IME_MODE_NORMAL                1
 #define NS_STYLE_IME_MODE_ACTIVE                2
@@ -1115,27 +1115,27 @@ enum class StyleWhiteSpace : uint8_t {
 #define NS_STYLE_TEXT_RENDERING_OPTIMIZELEGIBILITY 2
 #define NS_STYLE_TEXT_RENDERING_GEOMETRICPRECISION 3
 
 // adjust-color
 #define NS_STYLE_COLOR_ADJUST_ECONOMY               0
 #define NS_STYLE_COLOR_ADJUST_EXACT                 1
 
 // color-interpolation and color-interpolation-filters
-#define NS_STYLE_COLOR_INTERPOLATION_AUTO           0
-#define NS_STYLE_COLOR_INTERPOLATION_SRGB           1
+#define NS_STYLE_COLOR_INTERPOLATION_SRGB           0
+#define NS_STYLE_COLOR_INTERPOLATION_AUTO           1
 #define NS_STYLE_COLOR_INTERPOLATION_LINEARRGB      2
 
 // vector-effect
 #define NS_STYLE_VECTOR_EFFECT_NONE                 0
 #define NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE   1
 
 // 3d Transforms - Backface visibility
-#define NS_STYLE_BACKFACE_VISIBILITY_VISIBLE        1
-#define NS_STYLE_BACKFACE_VISIBILITY_HIDDEN         0
+#define NS_STYLE_BACKFACE_VISIBILITY_VISIBLE        0
+#define NS_STYLE_BACKFACE_VISIBILITY_HIDDEN         1
 
 #define NS_STYLE_TRANSFORM_STYLE_FLAT               0
 #define NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D        1
 
 // object {fill,stroke}-opacity inherited from context for SVG glyphs
 #define NS_STYLE_CONTEXT_FILL_OPACITY               0
 #define NS_STYLE_CONTEXT_STROKE_OPACITY             1
 
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -61,32 +61,34 @@ def parse_aliases(value):
 
 class Keyword(object):
     def __init__(self, name, values, gecko_constant_prefix=None,
                  gecko_enum_prefix=None, custom_consts=None,
                  extra_gecko_values=None, extra_servo_values=None,
                  aliases=None,
                  extra_gecko_aliases=None,
                  gecko_strip_moz_prefix=None,
-                 gecko_inexhaustive=None):
+                 gecko_inexhaustive=None,
+                 gecko_mismatched_keyword_values=False):
         self.name = name
         self.values = values.split()
         if gecko_constant_prefix and gecko_enum_prefix:
             raise TypeError("Only one of gecko_constant_prefix and gecko_enum_prefix can be specified")
         self.gecko_constant_prefix = gecko_constant_prefix or \
             "NS_STYLE_" + self.name.upper().replace("-", "_")
         self.gecko_enum_prefix = gecko_enum_prefix
         self.extra_gecko_values = (extra_gecko_values or "").split()
         self.extra_servo_values = (extra_servo_values or "").split()
         self.aliases = parse_aliases(aliases or "")
         self.extra_gecko_aliases = parse_aliases(extra_gecko_aliases or "")
         self.consts_map = {} if custom_consts is None else custom_consts
         self.gecko_strip_moz_prefix = True \
             if gecko_strip_moz_prefix is None else gecko_strip_moz_prefix
         self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None)
+        self.gecko_mismatched_keyword_values = gecko_mismatched_keyword_values
 
     def gecko_values(self):
         return self.values + self.extra_gecko_values
 
     def servo_values(self):
         return self.values + self.extra_servo_values
 
     def gecko_aliases(self):
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -392,41 +392,63 @@ def get_gecko_property(ffi_name, self_pa
 def set_gecko_property(ffi_name, expr):
     if "mBorderColor" in ffi_name:
         ffi_name = ffi_name.replace("mBorderColor",
                                     "*self.gecko.__bindgen_anon_1.mBorderColor.as_mut()")
         return "unsafe { %s = %s };" % (ffi_name, expr)
     return "self.gecko.%s = %s;" % (ffi_name, expr)
 %>
 
+<%def name="keyword_static_assertions(ident, keyword)">
+    unsafe {
+        % for value in keyword.values_for('gecko'):
+            let _ = transmute::<[u32; 1], [u32; (
+                Keyword::${to_rust_ident(value)} as usize ==
+                structs::${keyword.gecko_constant(value)} as usize
+            ) as usize]>; // ${ident}
+        % endfor
+    }
+</%def>
+
 <%def name="impl_keyword_setter(ident, gecko_ffi_name, keyword, cast_type='u8', on_set=None)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         use properties::longhands::${ident}::computed_value::T as Keyword;
-        // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
-        let result = match v {
-            % for value in keyword.values_for('gecko'):
-                Keyword::${to_rust_ident(value)} =>
-                    structs::${keyword.gecko_constant(value)} ${keyword.maybe_cast(cast_type)},
-            % endfor
-        };
+        % if keyword.gecko_mismatched_keyword_values:
+            // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
+            let result = match v {
+                % for value in keyword.values_for('gecko'):
+                    Keyword::${to_rust_ident(value)} =>
+                        structs::${keyword.gecko_constant(value)} ${keyword.maybe_cast(cast_type)},
+                % endfor
+            };
+        % else:
+            <%call expr="keyword_static_assertions(ident, keyword)"></%call>
+            % if keyword.gecko_enum_prefix is None:
+                let result = v ${keyword.maybe_cast(cast_type)};
+            % else:
+                let result = unsafe { transmute(v) };
+            % endif
+        % endif
         ${set_gecko_property(gecko_ffi_name, "result")}
         % if on_set:
         self.${on_set}();
         % endif
     }
 </%def>
 
 <%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')">
     // FIXME: We introduced non_upper_case_globals for -moz-appearance only
     //        since the prefix of Gecko value starts with ThemeWidgetType_NS_THEME.
     //        We should remove this after fix bug 1371809.
     #[allow(non_snake_case, non_upper_case_globals)]
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         use properties::longhands::${ident}::computed_value::T as Keyword;
+
+        % if keyword.gecko_mismatched_keyword_values:
         // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
 
         // Some constant macros in the gecko are defined as negative integer(e.g. font-stretch).
         // And they are convert to signed integer in Rust bindings. We need to cast then
         // as signed type when we have both signed/unsigned integer in order to use them
         // as match's arms.
         // Also, to use same implementation here we use casted constant if we have only singed values.
         % if keyword.gecko_enum_prefix is None:
@@ -448,16 +470,20 @@ def set_gecko_property(ffi_name, expr):
             % for value in keyword.values_for('gecko'):
             structs::${keyword.gecko_constant(value)} => Keyword::${to_rust_ident(value)},
             % endfor
             % if keyword.gecko_inexhaustive:
             x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x),
             % endif
         }
         % endif
+        % else:
+        <%call expr="keyword_static_assertions(ident, keyword)"></%call>
+        unsafe { transmute(${get_gecko_property(gecko_ffi_name)}) }
+        % endif
     }
 </%def>
 
 <%def name="impl_color_setter(ident, gecko_ffi_name)">
     #[allow(unreachable_code)]
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         ${set_gecko_property(gecko_ffi_name, "v.into()")}
@@ -1210,17 +1236,17 @@ fn static_assert() {
     // Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
     % for side in SIDES:
     { const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
     % endfor
 }
 
 
 <% border_style_keyword = Keyword("border-style",
-                                  "none solid double dotted dashed hidden groove ridge inset outset") %>
+                                  "none inset groove outset ridge dotted dashed solid double hidden") %>
 
 <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
                                      for x in SIDES
                                      for y in ["color", "style", "width"]] +
                                     ["border-{0}-radius".format(x.ident.replace("_", "-"))
                                      for x in CORNERS]) %>
 
 <% skip_moz_border_color_longhands = " ".join("-moz-border-{0}-colors".format(x.ident)
@@ -1942,25 +1968,22 @@ fn static_assert() {
 <% skip_outline_longhands = " ".join("outline-style outline-width".split() +
                                      ["-moz-outline-radius-{0}".format(x.ident.replace("_", ""))
                                       for x in CORNERS]) %>
 <%self:impl_trait style_struct_name="Outline"
                   skip_longhands="${skip_outline_longhands}">
 
     #[allow(non_snake_case)]
     pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) {
-        // FIXME(bholley): Align binary representations and ditch |match| for
-        // cast + static_asserts
+        use self::border_style::T as Keyword;
+        <%call expr="keyword_static_assertions('outline-style', border_style_keyword)"></%call>
         let result = match v {
-            % for value in border_style_keyword.values_for('gecko'):
-                Either::Second(border_style::T::${to_rust_ident(value)}) =>
-                    structs::${border_style_keyword.gecko_constant(value)} ${border_style_keyword.maybe_cast("u8")},
-            % endfor
-                Either::First(Auto) =>
-                    structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")},
+            Either::First(Auto) =>
+                structs::${border_style_keyword.gecko_constant('auto')} ${border_style_keyword.maybe_cast("u8")},
+            Either::Second(border_style) => unsafe { transmute(border_style) },
         };
         ${set_gecko_property("mOutlineStyle", "result")}
 
         // NB: This is needed to correctly handling the initial value of
         // outline-width when outline-style changes, see the
         // update_border_${side.ident} comment for more details.
         self.gecko.mActualOutlineWidth = self.gecko.mOutlineWidth;
     }
@@ -1972,25 +1995,19 @@ fn static_assert() {
 
     #[allow(non_snake_case)]
     pub fn reset_outline_style(&mut self, other: &Self) {
         self.copy_outline_style_from(other)
     }
 
     #[allow(non_snake_case)]
     pub fn clone_outline_style(&self) -> longhands::outline_style::computed_value::T {
-        // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
         match ${get_gecko_property("mOutlineStyle")} ${border_style_keyword.maybe_cast("u32")} {
-            % for value in border_style_keyword.values_for('gecko'):
-            structs::${border_style_keyword.gecko_constant(value)} => Either::Second(border_style::T::${value}),
-            % endfor
             structs::${border_style_keyword.gecko_constant('auto')} => Either::First(Auto),
-            % if border_style_keyword.gecko_inexhaustive:
-            x => panic!("Found unexpected value in style struct for outline_style property: {:?}", x),
-            % endif
+            border_style => Either::Second(unsafe { transmute(border_style as u8) }),
         }
     }
 
     <% impl_non_negative_length("outline_width", "mActualOutlineWidth",
                                 inherit_from="mOutlineWidth",
                                 round_to_pixels=True) %>
 
     % for corner in CORNERS:
@@ -2715,74 +2732,57 @@ fn static_assert() {
                                             "-webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid " +
                                             "-moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck " +
                                             "-moz-popup -moz-groupbox",
                                             gecko_enum_prefix="StyleDisplay",
                                             gecko_strip_moz_prefix=False) %>
 
     pub fn set_display(&mut self, v: longhands::display::computed_value::T) {
         use properties::longhands::display::computed_value::T as Keyword;
-        // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
-        let result = match v {
-            % for value in display_keyword.values_for('gecko'):
-                Keyword::${to_rust_ident(value)} =>
-                    structs::${display_keyword.gecko_constant(value)},
-            % endfor
-        };
+        <%call expr="keyword_static_assertions('display', display_keyword)"></%call>
+        let result = unsafe { transmute(v) };
         self.gecko.mDisplay = result;
         self.gecko.mOriginalDisplay = result;
     }
 
     /// Set the display value from the style adjustment code. This is pretty
     /// much like set_display, but without touching the mOriginalDisplay field,
     /// which we want to keep.
     pub fn set_adjusted_display(&mut self,
                                 v: longhands::display::computed_value::T,
                                 _is_item_or_root: bool) {
         use properties::longhands::display::computed_value::T as Keyword;
-        let result = match v {
-            % for value in display_keyword.values_for('gecko'):
-                Keyword::${to_rust_ident(value)} =>
-                    structs::${display_keyword.gecko_constant(value)},
-            % endfor
-        };
+        <%call expr="keyword_static_assertions('display', display_keyword)"></%call>
+        let result = unsafe { transmute(v) };
         self.gecko.mDisplay = result;
     }
 
     pub fn copy_display_from(&mut self, other: &Self) {
         self.gecko.mDisplay = other.gecko.mDisplay;
         self.gecko.mOriginalDisplay = other.gecko.mDisplay;
     }
 
     pub fn reset_display(&mut self, other: &Self) {
         self.copy_display_from(other)
     }
 
     <%call expr="impl_keyword_clone('display', 'mDisplay', display_keyword)"></%call>
 
     <% overflow_x = data.longhands_by_name["overflow-x"] %>
     pub fn set_overflow_y(&mut self, v: longhands::overflow_y::computed_value::T) {
-        use properties::longhands::overflow_x::computed_value::T as BaseType;
-        // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
-        self.gecko.mOverflowY = match v {
-            % for value in overflow_x.keyword.values_for('gecko'):
-                BaseType::${to_rust_ident(value)} => structs::${overflow_x.keyword.gecko_constant(value)} as u8,
-            % endfor
-        };
+        use properties::longhands::overflow_x::computed_value::T as Keyword;
+        <%call expr="keyword_static_assertions('overflow_y', overflow_x.keyword)"></%call>
+        let result = unsafe { transmute(v) };
+        self.gecko.mOverflowY = result;
     }
     ${impl_simple_copy('overflow_y', 'mOverflowY')}
     pub fn clone_overflow_y(&self) -> longhands::overflow_y::computed_value::T {
-        use properties::longhands::overflow_x::computed_value::T as BaseType;
-        // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts
-        match self.gecko.mOverflowY as u32 {
-            % for value in overflow_x.keyword.values_for('gecko'):
-            structs::${overflow_x.keyword.gecko_constant(value)} => BaseType::${to_rust_ident(value)},
-            % endfor
-            x => panic!("Found unexpected value in style struct for overflow_y property: {}", x),
-        }
+        use properties::longhands::overflow_y::computed_value::T as Keyword;
+        <%call expr="keyword_static_assertions('overflow_y', overflow_x.keyword)"></%call>
+        unsafe { transmute(self.gecko.mOverflowY) }
     }
 
     pub fn set_vertical_align(&mut self, v: longhands::vertical_align::computed_value::T) {
         use values::generics::box_::VerticalAlign;
         let value = match v {
             VerticalAlign::Baseline => structs::NS_STYLE_VERTICAL_ALIGN_BASELINE,
             VerticalAlign::Sub => structs::NS_STYLE_VERTICAL_ALIGN_SUB,
             VerticalAlign::Super => structs::NS_STYLE_VERTICAL_ALIGN_SUPER,
@@ -4605,17 +4605,18 @@ fn static_assert() {
 
 
 <%self:impl_trait style_struct_name="InheritedText"
                   skip_longhands="text-align text-emphasis-style text-shadow line-height letter-spacing word-spacing
                                   -webkit-text-stroke-width text-emphasis-position -moz-tab-size">
 
     <% text_align_keyword = Keyword("text-align",
                                     "start end left right center justify -moz-center -moz-left -moz-right char",
-                                    gecko_strip_moz_prefix=False) %>
+                                    gecko_strip_moz_prefix=False,
+                                    gecko_mismatched_keyword_values=True) %>
     ${impl_keyword('text_align', 'mTextAlign', text_align_keyword)}
 
     pub fn set_text_shadow<I>(&mut self, v: I)
         where I: IntoIterator<Item = SimpleShadow>,
               I::IntoIter: ExactSizeIterator
     {
         let v = v.into_iter();
         self.gecko.mTextShadow.replace_with_new(v.len() as u32);
@@ -4634,17 +4635,16 @@ fn static_assert() {
 
     pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
         let buf = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()).collect();
         longhands::text_shadow::computed_value::T(buf)
     }
 
     pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
         use values::generics::text::LineHeight;
-        // FIXME: Align binary representations and ditch |match| for cast + static_asserts
         let en = match v {
             LineHeight::Normal => CoordDataValue::Normal,
             LineHeight::Length(val) => CoordDataValue::Coord(val.0.to_i32_au()),
             LineHeight::Number(val) => CoordDataValue::Factor(val.0),
             LineHeight::MozBlockHeight =>
                     CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
         };
         self.gecko.mLineHeight.set_value(en);
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -421,16 +421,17 @@
 </%def>
 
 <%def name="single_keyword_system(name, values, **kwargs)">
     <%
         keyword_kwargs = {a: kwargs.pop(a, None) for a in [
             'gecko_constant_prefix', 'gecko_enum_prefix',
             'extra_gecko_values', 'extra_servo_values',
             'custom_consts', 'gecko_inexhaustive',
+            'gecko_mismatched_keyword_values',
         ]}
         keyword = keyword=Keyword(name, values, **keyword_kwargs)
     %>
     <%call expr="longhand(name, keyword=Keyword(name, values, **keyword_kwargs), **kwargs)">
         use properties::longhands::system_font::SystemFont;
 
         pub mod computed_value {
             use cssparser::Parser;
@@ -594,23 +595,25 @@
                 }
             % endfor
             bits
         }
     }
 </%def>
 
 <%def name="single_keyword_computed(name, values, vector=False,
-            extra_specified=None, needs_conversion=False, **kwargs)">
+            extra_specified=None, needs_conversion=False,
+            initial_value=None, **kwargs)">
     <%
         keyword_kwargs = {a: kwargs.pop(a, None) for a in [
             'gecko_constant_prefix', 'gecko_enum_prefix',
             'extra_gecko_values', 'extra_servo_values',
             'aliases', 'extra_gecko_aliases', 'custom_consts',
             'gecko_inexhaustive', 'gecko_strip_moz_prefix',
+            'gecko_mismatched_keyword_values',
         ]}
     %>
 
     <%def name="inner_body(keyword, extra_specified=None, needs_conversion=False)">
         % if extra_specified or keyword.aliases_for(product):
             define_css_keyword_enum! { SpecifiedValue:
                 values {
                     % for value in keyword.values_for(product) + (extra_specified or "").split():
@@ -630,21 +633,21 @@
             define_css_keyword_enum! { T:
                 % for value in data.longhands_by_name[name].keyword.values_for(product):
                     "${value}" => ${to_rust_ident(value)},
                 % endfor
             }
         }
         #[inline]
         pub fn get_initial_value() -> computed_value::T {
-            computed_value::T::${to_rust_ident(values.split()[0])}
+            computed_value::T::${to_rust_ident(initial_value or values.split()[0])}
         }
         #[inline]
         pub fn get_initial_specified_value() -> SpecifiedValue {
-            SpecifiedValue::${to_rust_ident(values.split()[0])}
+            SpecifiedValue::${to_rust_ident(initial_value or values.split()[0])}
         }
         #[inline]
         pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                              -> Result<SpecifiedValue, ParseError<'i>> {
             SpecifiedValue::parse(input)
         }
         impl Parse for SpecifiedValue {
             #[inline]
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -48,17 +48,17 @@
                               spec=maybe_logical_spec(side, "width"),
                               animation_value_type="NonNegativeLength",
                               logical=is_logical,
                               flags="APPLIES_TO_FIRST_LETTER",
                               allow_quirks=not is_logical)}
 % endfor
 
 ${helpers.gecko_keyword_conversion(Keyword('border-style',
-                                   "none solid double dotted dashed hidden groove ridge inset outset"),
+                                   "none inset groove outset ridge dotted dashed solid double hidden"),
                                    type="::values::specified::BorderStyle")}
 
 // FIXME(#4126): when gfx supports painting it, make this Size2D<LengthOrPercentage>
 % for corner in ["top-left", "top-right", "bottom-right", "bottom-left"]:
     ${helpers.predefined_type("border-" + corner + "-radius", "BorderCornerRadius",
                               "computed::BorderCornerRadius::zero()",
                               "parse", extra_prefixes="webkit",
                               spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner,
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -14,29 +14,37 @@
 // We allow "display" to apply to placeholders because we need to make the
 // placeholder pseudo-element an inline-block in the UA stylesheet in Gecko.
 <%helpers:longhand name="display"
                    animation_value_type="discrete"
                    custom_cascade="${product == 'servo'}"
                    flags="APPLIES_TO_PLACEHOLDER"
                    spec="https://drafts.csswg.org/css-display/#propdef-display">
     <%
-        values = """inline block inline-block
-            table inline-table table-row-group table-header-group table-footer-group
-            table-row table-column-group table-column table-cell table-caption
-            list-item none
-        """.split()
-        webkit_prefixed_values = "flex inline-flex".split()
-        values += webkit_prefixed_values
-        if product == "gecko":
-            values += """grid inline-grid ruby ruby-base ruby-base-container
-                ruby-text ruby-text-container contents flow-root -webkit-box
-                -webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid
-                -moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck
-                -moz-popup -moz-groupbox""".split()
+        if product == "servo":
+            values = """inline block inline-block
+                table inline-table table-row-group table-header-group table-footer-group
+                table-row table-column-group table-column table-cell table-caption
+                list-item none flex inline-flex""".split()
+        else:
+            # The order of these values must match those in Gecko's StyleDisplay
+            # enum. (This is statically asserted in gecko.mako.rs.)
+            values = """none block flow-root inline inline-block list-item table
+                inline-table table-row-group table-column table-column-group
+                table-header-group table-footer-group table-row table-cell
+                table-caption flex inline-flex grid inline-grid ruby ruby-base
+                ruby-base-container ruby-text ruby-text-container contents
+                -webkit-box -webkit-inline-box -moz-box -moz-inline-box
+                -moz-grid -moz-inline-grid -moz-grid-group -moz-grid-line
+                -moz-stack -moz-inline-stack -moz-deck -moz-groupbox
+                -moz-popup""".split()
+
+        webkit_aliased_values = "flex inline-flex".split()
+        for value in webkit_aliased_values:
+            assert(value in values)
     %>
     use style_traits::ToCss;
 
     pub mod computed_value {
         pub use super::SpecifiedValue as T;
 
         impl T {
             /// Returns whether this "display" value is the display of a flex or
@@ -180,29 +188,29 @@
                 % endfor
             }
         }
     }
 
     /// The initial display value.
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
-        computed_value::T::${to_rust_ident(values[0])}
+        computed_value::T::inline
     }
 
     /// Parse a display value.
     pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         try_match_ident_ignore_ascii_case! { input,
             % for value in values:
                 "${value}" => {
                     Ok(computed_value::T::${to_rust_ident(value)})
                 },
             % endfor
-            % for value in webkit_prefixed_values:
+            % for value in webkit_aliased_values:
                 "-webkit-${value}" => {
                     Ok(computed_value::T::${to_rust_ident(value)})
                 },
             % endfor
         }
     }
 
     % if product == "servo":
@@ -288,16 +296,17 @@
                                   values="none left right both"
                                   // https://drafts.csswg.org/css-logical-props/#float-clear
                                   extra_specified="inline-start inline-end"
                                   needs_conversion="True"
                                   gecko_inexhaustive="True"
                                   animation_value_type="discrete"
                                   gecko_enum_prefix="StyleClear"
                                   gecko_ffi_name="mBreakType"
+                                  gecko_mismatched_keyword_values="True"
                                   spec="https://www.w3.org/TR/CSS2/visuren.html#flow-control">
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
             let ltr = context.style().writing_mode.is_bidi_ltr();
             // https://drafts.csswg.org/css-logical-props/#float-clear
@@ -644,16 +653,17 @@
                          products="gecko",
                          spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before",
                          animation_value_type="discrete")}
 ${helpers.single_keyword("page-break-inside",
                          "auto avoid",
                          products="gecko",
                          gecko_ffi_name="mBreakInside",
                          gecko_constant_prefix="NS_STYLE_PAGE_BREAK",
+                         gecko_mismatched_keyword_values=True,
                          spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-inside",
                          animation_value_type="discrete")}
 
 // CSS Basic User Interface Module Level 3
 // http://dev.w3.org/csswg/css-ui
 // FIXME support logical values `block` and `inline` (https://drafts.csswg.org/css-logical-props/#resize)
 //
 // This is APPLIES_TO_PLACEHOLDER so we can override, in the UA sheet, the
@@ -689,16 +699,17 @@
                          "visible hidden",
                          spec="https://drafts.csswg.org/css-transforms/#backface-visibility-property",
                          extra_prefixes="moz webkit",
                          animation_value_type="discrete")}
 
 ${helpers.single_keyword("transform-box",
                          "border-box fill-box view-box",
                          gecko_enum_prefix="StyleGeometryBox",
+                         gecko_mismatched_keyword_values=True,
                          products="gecko",
                          spec="https://drafts.csswg.org/css-transforms/#transform-box",
                          gecko_inexhaustive="True",
                          animation_value_type="discrete")}
 
 // `auto` keyword is not supported in gecko yet.
 ${helpers.single_keyword("transform-style",
                          "auto flat preserve-3d" if product == "servo" else
@@ -835,16 +846,17 @@
                             -moz-win-communications-toolbox -moz-win-exclude-glass -moz-win-glass -moz-win-media-toolbox
                             -moz-window-button-box -moz-window-button-box-maximized -moz-window-button-close
                             -moz-window-button-maximize -moz-window-button-minimize -moz-window-button-restore
                             -moz-window-frame-bottom -moz-window-frame-left -moz-window-frame-right -moz-window-titlebar
                             -moz-window-titlebar-maximized
                          """,
                          gecko_ffi_name="mAppearance",
                          gecko_constant_prefix="ThemeWidgetType_NS_THEME",
+                         gecko_mismatched_keyword_values=True,
                          products="gecko",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-appearance)",
                          animation_value_type="discrete")}
 
 ${helpers.predefined_type("-moz-binding", "UrlOrNone", "Either::Second(None_)",
                           products="gecko",
                           boxed="True" if product == "gecko" else "False",
                           animation_value_type="none",
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -60,13 +60,13 @@
     spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color",
 )}
 
 ${helpers.single_keyword("column-span", "none all",
                          products="gecko", animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}
 
 ${helpers.single_keyword("column-rule-style",
-                         "none hidden dotted dashed solid double groove ridge inset outset",
+                         "none inset groove outset ridge dotted dashed solid double hidden",
                          products="gecko", extra_prefixes="moz",
                          gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -606,16 +606,17 @@ macro_rules! impl_gecko_keyword_conversi
                                       "all-petite-caps": "ALLPETITE",
                                       "titling-caps": "TITLING" } %>
 
 ${helpers.single_keyword_system("font-variant-caps",
                                 "normal small-caps",
                                 extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps",
                                 gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
                                 gecko_ffi_name="mFont.variantCaps",
+                                gecko_mismatched_keyword_values=True,
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
                                 custom_consts=font_variant_caps_custom_consts,
                                 flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                                 animation_value_type="discrete")}
 
 ${helpers.predefined_type("font-weight",
                           "FontWeight",
                           initial_value="computed::FontWeight::normal()",
@@ -651,26 +652,28 @@ macro_rules! impl_gecko_keyword_conversi
                           spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis")}
 
 ${helpers.single_keyword_system("font-stretch",
                                 "normal ultra-condensed extra-condensed condensed \
                                  semi-condensed semi-expanded expanded extra-expanded \
                                  ultra-expanded",
                                 gecko_ffi_name="mFont.stretch",
                                 gecko_constant_prefix="NS_FONT_STRETCH",
+                                gecko_mismatched_keyword_values=True,
                                 cast_type='i16',
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch",
                                 flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                                 animation_value_type="ComputedValue")}
 
 ${helpers.single_keyword_system("font-kerning",
                                 "auto none normal",
                                 products="gecko",
                                 gecko_ffi_name="mFont.kerning",
                                 gecko_constant_prefix="NS_FONT_KERNING",
+                                gecko_mismatched_keyword_values=True,
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning",
                                 flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                                 animation_value_type="discrete")}
 
 ${helpers.predefined_type("font-variant-alternates",
                           "FontVariantAlternates",
                           products="gecko",
                           initial_value="computed::FontVariantAlternates::get_initial_value()",
@@ -1146,16 +1149,17 @@ macro_rules! exclusive_value {
     impl_gecko_keyword_conversions!(VariantNumeric, u8);
 </%helpers:longhand>
 
 ${helpers.single_keyword_system("font-variant-position",
                                 "normal sub super",
                                 products="gecko",
                                 gecko_ffi_name="mFont.variantPosition",
                                 gecko_constant_prefix="NS_FONT_VARIANT_POSITION",
+                                gecko_mismatched_keyword_values=True,
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
                                 flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                                 animation_value_type="discrete")}
 
 <%helpers:longhand name="font-feature-settings" products="gecko" animation_value_type="discrete"
                    extra_prefixes="moz" boxed="True"
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings">
--- a/servo/components/style/properties/longhand/inherited_box.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_box.mako.rs
@@ -17,16 +17,17 @@
 // CSS Writing Modes Level 3
 // https://drafts.csswg.org/css-writing-modes-3
 ${helpers.single_keyword("writing-mode",
                          "horizontal-tb vertical-rl vertical-lr",
                          extra_gecko_values="sideways-rl sideways-lr",
                          extra_gecko_aliases="lr=horizontal-tb lr-tb=horizontal-tb \
                                               rl=horizontal-tb rl-tb=horizontal-tb \
                                               tb=vertical-rl   tb-rl=vertical-rl",
+                         gecko_mismatched_keyword_values=True,
                          experimental=True,
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-writing-modes/#propdef-writing-mode")}
 
 ${helpers.single_keyword("direction", "ltr rtl", animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction",
                          needs_conversion=True)}
 
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -24,16 +24,17 @@
                          products="gecko",
                          animation_value_type="discrete",
                          spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty")}
 
 ${helpers.single_keyword("color-interpolation-filters", "linearrgb auto srgb",
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
                          animation_value_type="discrete",
+                         gecko_mismatched_keyword_values=True,
                          spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")}
 
 ${helpers.predefined_type(
     "fill", "SVGPaint",
     "::values::computed::SVGPaint::black()",
     products="gecko",
     animation_value_type="IntermediateSVGPaint",
     boxed=True,
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -99,16 +99,17 @@
         }
     }
 </%helpers:single_keyword_computed>
 
 ${helpers.single_keyword("text-align-last",
                          "auto start end left right center justify",
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_TEXT_ALIGN",
+                         gecko_mismatched_keyword_values=True,
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-text/#propdef-text-align-last")}
 
 // TODO make this a shorthand and implement text-align-last/text-align-all
 <%helpers:longhand name="text-align" animation_value_type="discrete"
                    flags="APPLIES_TO_PLACEHOLDER"
                    spec="https://drafts.csswg.org/css-text/#propdef-text-align">
     pub mod computed_value {
@@ -155,17 +156,17 @@
             _moz_right("-moz-right") => 8,
             char("char") => 10,
             % endif
         }
 
         ${helpers.gecko_keyword_conversion(Keyword('text-align',
                                                    """left right center justify -moz-left -moz-right
                                                     -moz-center char end""",
-                                                    gecko_strip_moz_prefix=False), type="T")}
+                                                   gecko_strip_moz_prefix=False), type="T")}
     }
 
     #[inline] pub fn get_initial_value() -> computed_value::T {
         computed_value::T::start
     }
 
 
     % if product == "gecko":
--- a/servo/components/style/properties/longhand/text.mako.rs
+++ b/servo/components/style/properties/longhand/text.mako.rs
@@ -17,16 +17,17 @@
                           "computed::TextOverflow::get_initial_value()",
                           animation_value_type="discrete",
                           boxed=True,
                           flags="APPLIES_TO_PLACEHOLDER",
                           spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow")}
 
 ${helpers.single_keyword("unicode-bidi",
                          "normal embed isolate bidi-override isolate-override plaintext",
+                         gecko_mismatched_keyword_values=True,
                          animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi")}
 
 <%helpers:longhand name="text-decoration-line"
                    custom_cascade="${product == 'servo'}"
                    animation_value_type="discrete"
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                    spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line">
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -156,26 +156,26 @@ pub fn parse_number_with_clamping_mode<'
         value: result.min(f32::MAX).max(f32::MIN),
         calc_clamping_mode: Some(clamping_mode),
     })
 }
 
 // The integer values here correspond to the border conflict resolution rules in CSS 2.1 ยง
 // 17.6.2.1. Higher values override lower values.
 define_numbered_css_keyword_enum! { BorderStyle:
-    "none" => none = -1,
-    "solid" => solid = 6,
-    "double" => double = 7,
-    "dotted" => dotted = 4,
-    "dashed" => dashed = 5,
-    "hidden" => hidden = -2,
-    "groove" => groove = 1,
-    "ridge" => ridge = 3,
-    "inset" => inset = 0,
-    "outset" => outset = 2,
+    "none" => none = 0,
+    "inset" => inset = 1,
+    "groove" => groove = 2,
+    "outset" => outset = 3,
+    "ridge" => ridge = 4,
+    "dotted" => dotted = 5,
+    "dashed" => dashed = 6,
+    "solid" => solid = 7,
+    "double" => double = 8,
+    "hidden" => hidden = 9,
 }
 
 
 impl BorderStyle {
     /// Whether this border style is either none or hidden.
     pub fn none_or_hidden(&self) -> bool {
         matches!(*self, BorderStyle::none | BorderStyle::hidden)
     }