Bug 696253, patch 6: implement parsing/computation for CSS properties 'flex-grow' and 'flex-shrink'. r=dbaron
authorDaniel Holbert <dholbert@cs.stanford.edu>
Fri, 06 Jul 2012 17:06:22 -0700
changeset 98588 10d1162cd4e1c2fbd9344dd42e874dd2886dcff6
parent 98587 08dc24b4a21cf7142fa980043a2899668b355a20
child 98589 57126745d4629a4be7049756fb649f59bd4de2d5
push id23064
push userryanvm@gmail.com
push dateSat, 07 Jul 2012 18:54:06 +0000
treeherdermozilla-central@9533b40ff28b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs696253
milestone16.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
Bug 696253, patch 6: implement parsing/computation for CSS properties 'flex-grow' and 'flex-shrink'. r=dbaron
dom/interfaces/css/nsIDOMCSS2Properties.idl
layout/style/nsCSSPropList.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/Makefile.in
layout/style/test/property_database.js
layout/style/test/test_flexbox_flex_grow_and_shrink.html
layout/style/test/test_transitions_per_property.html
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -766,15 +766,21 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozAlignSelf;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozFlexDirection;
                                         // raises(DOMException) on setting
 
+           attribute DOMString        MozFlexGrow;
+                                        // raises(DOMException) on setting
+
+           attribute DOMString        MozFlexShrink;
+                                        // raises(DOMException) on setting
+
            attribute DOMString        MozOrder;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozJustifyContent;
                                         // raises(DOMException) on setting
 */
 };
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1538,16 +1538,38 @@ CSS_PROP_POSITION(
     CSS_PROP_DOMPROP_PREFIXED(FlexDirection),
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HK,
     kFlexDirectionKTable,
     offsetof(nsStylePosition, mFlexDirection),
     eStyleAnimType_EnumU8)
 CSS_PROP_POSITION(
+    -moz-flex-grow,
+    flex_grow,
+    CSS_PROP_DOMPROP_PREFIXED(FlexGrow),
+    CSS_PROPERTY_PARSE_VALUE |
+      CSS_PROPERTY_VALUE_NONNEGATIVE,
+    "",
+    VARIANT_HN,
+    nsnull,
+    offsetof(nsStylePosition, mFlexGrow),
+    eStyleAnimType_float) // float, except animations to/from 0 shouldn't work
+CSS_PROP_POSITION(
+    -moz-flex-shrink,
+    flex_shrink,
+    CSS_PROP_DOMPROP_PREFIXED(FlexShrink),
+    CSS_PROPERTY_PARSE_VALUE |
+      CSS_PROPERTY_VALUE_NONNEGATIVE,
+    "",
+    VARIANT_HN,
+    nsnull,
+    offsetof(nsStylePosition, mFlexShrink),
+    eStyleAnimType_float) // float, except animations to/from 0 shouldn't work
+CSS_PROP_POSITION(
     -moz-order,
     order,
     CSS_PROP_DOMPROP_PREFIXED(Order),
     CSS_PROPERTY_PARSE_VALUE,
     "",
     VARIANT_HI,
     nsnull,
     offsetof(nsStylePosition, mOrder),
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2967,16 +2967,32 @@ nsComputedDOMStyle::DoGetFlexDirection()
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStylePosition()->mFlexDirection,
                                    nsCSSProps::kFlexDirectionKTable));
   return val;
 }
 
 nsIDOMCSSValue*
+nsComputedDOMStyle::DoGetFlexGrow()
+{
+  nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
+  val->SetNumber(GetStylePosition()->mFlexGrow);
+  return val;
+}
+
+nsIDOMCSSValue*
+nsComputedDOMStyle::DoGetFlexShrink()
+{
+  nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
+  val->SetNumber(GetStylePosition()->mFlexShrink);
+  return val;
+}
+
+nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetOrder()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   val->SetNumber(GetStylePosition()->mOrder);
   return val;
 }
 
 nsIDOMCSSValue*
@@ -4705,16 +4721,18 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_gap,               ColumnGap),
     //// COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule,         ColumnRule),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_color,        ColumnRuleColor),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_style,        ColumnRuleStyle),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_width,        ColumnRuleWidth),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_width,             ColumnWidth),
 #ifdef MOZ_FLEXBOX
     COMPUTED_STYLE_MAP_ENTRY(flex_direction,                FlexDirection),
+    COMPUTED_STYLE_MAP_ENTRY(flex_grow,                     FlexGrow),
+    COMPUTED_STYLE_MAP_ENTRY(flex_shrink,                   FlexShrink),
 #endif // MOZ_FLEXBOX
     COMPUTED_STYLE_MAP_ENTRY(float_edge,                    FloatEdge),
     COMPUTED_STYLE_MAP_ENTRY(font_feature_settings,         FontFeatureSettings),
     COMPUTED_STYLE_MAP_ENTRY(font_language_override,        FontLanguageOverride),
     COMPUTED_STYLE_MAP_ENTRY(force_broken_image_icon,       ForceBrokenImageIcon),
     COMPUTED_STYLE_MAP_ENTRY(hyphens,                       Hyphens),
     COMPUTED_STYLE_MAP_ENTRY(image_region,                  ImageRegion),
 #ifdef MOZ_FLEXBOX
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -357,16 +357,18 @@ private:
   nsIDOMCSSValue* DoGetAnimationIterationCount();
   nsIDOMCSSValue* DoGetAnimationPlayState();
 
 #ifdef MOZ_FLEXBOX
   /* CSS Flexbox properties */
   nsIDOMCSSValue* DoGetAlignItems();
   nsIDOMCSSValue* DoGetAlignSelf();
   nsIDOMCSSValue* DoGetFlexDirection();
+  nsIDOMCSSValue* DoGetFlexGrow();
+  nsIDOMCSSValue* DoGetFlexShrink();
   nsIDOMCSSValue* DoGetOrder();
   nsIDOMCSSValue* DoGetJustifyContent();
 #endif // MOZ_FLEXBOX
 
   /* SVG properties */
   nsIDOMCSSValue* DoGetFill();
   nsIDOMCSSValue* DoGetStroke();
   nsIDOMCSSValue* DoGetMarkerEnd();
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -6486,16 +6486,26 @@ nsRuleNode::ComputePositionData(void* aS
   }
 
   // flex-direction: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForFlexDirection(),
               pos->mFlexDirection, canStoreInRuleTree,
               SETDSC_ENUMERATED, parentPos->mFlexDirection,
               NS_STYLE_FLEX_DIRECTION_ROW, 0, 0, 0, 0);
 
+  // flex-grow: float, inherit, initial
+  SetFactor(*aRuleData->ValueForFlexGrow(),
+            pos->mFlexGrow, canStoreInRuleTree,
+            parentPos->mFlexGrow, 0.0f);
+
+  // flex-shrink: float, inherit, initial
+  SetFactor(*aRuleData->ValueForFlexShrink(),
+            pos->mFlexShrink, canStoreInRuleTree,
+            parentPos->mFlexShrink, 1.0f);
+
   // order: integer, inherit, initial
   SetDiscrete(*aRuleData->ValueForOrder(),
               pos->mOrder, canStoreInRuleTree,
               SETDSC_INTEGER, parentPos->mOrder,
               NS_STYLE_ORDER_INITIAL, 0, 0, 0, 0);
 
   // justify-content: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForJustifyContent(),
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -280,16 +280,28 @@ nsStyleAnimation::ComputeDistance(nsCSSP
     }
     case eUnit_Percent: {
       float startPct = aStartValue.GetPercentValue();
       float endPct = aEndValue.GetPercentValue();
       aDistance = fabs(double(endPct - startPct));
       return true;
     }
     case eUnit_Float: {
+#ifdef MOZ_FLEXBOX
+      // Special case for flex-grow and flex-shrink: animations are
+      // disallowed between 0 and other values.
+      if ((aProperty == eCSSProperty_flex_grow ||
+           aProperty == eCSSProperty_flex_shrink) &&
+          (aStartValue.GetFloatValue() == 0.0f ||
+           aEndValue.GetFloatValue() == 0.0f) &&
+          aStartValue.GetFloatValue() != aEndValue.GetFloatValue()) {
+        return false;
+      }
+#endif // MOZ_FLEXBOX
+
       float startFloat = aStartValue.GetFloatValue();
       float endFloat = aEndValue.GetFloatValue();
       aDistance = fabs(double(endFloat - startFloat));
       return true;
     }
     case eUnit_Color: {
       // http://www.w3.org/TR/smil-animation/#animateColorElement says
       // that we should use Euclidean RGB cube distance.  However, we
@@ -1615,16 +1627,28 @@ nsStyleAnimation::AddWeighted(nsCSSPrope
     }
     case eUnit_Percent: {
       aResultValue.SetPercentValue(RestrictValue(aProperty,
         aCoeff1 * aValue1.GetPercentValue() +
         aCoeff2 * aValue2.GetPercentValue()));
       return true;
     }
     case eUnit_Float: {
+#ifdef MOZ_FLEXBOX
+      // Special case for flex-grow and flex-shrink: animations are
+      // disallowed between 0 and other values.
+      if ((aProperty == eCSSProperty_flex_grow ||
+           aProperty == eCSSProperty_flex_shrink) &&
+          (aValue1.GetFloatValue() == 0.0f ||
+           aValue2.GetFloatValue() == 0.0f) &&
+          aValue1.GetFloatValue() != aValue2.GetFloatValue()) {
+        return false;
+      }
+#endif // MOZ_FLEXBOX
+
       aResultValue.SetFloatValue(RestrictValue(aProperty,
         aCoeff1 * aValue1.GetFloatValue() +
         aCoeff2 * aValue2.GetFloatValue()));
       return true;
     }
     case eUnit_Color: {
       nscolor color1 = aValue1.GetColorValue();
       nscolor color2 = aValue2.GetColorValue();
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1126,16 +1126,18 @@ nsStylePosition::nsStylePosition(void)
   mMaxHeight.SetNoneValue();
   mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
 #ifdef MOZ_FLEXBOX
   mAlignItems = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE;
   mAlignSelf = NS_STYLE_ALIGN_SELF_AUTO;
   mFlexDirection = NS_STYLE_FLEX_DIRECTION_ROW;
   mJustifyContent = NS_STYLE_JUSTIFY_CONTENT_FLEX_START;
   mOrder = NS_STYLE_ORDER_INITIAL;
+  mFlexGrow = 0.0f;
+  mFlexShrink = 1.0f;
 #endif // MOZ_FLEXBOX
   mZIndex.SetAutoValue();
 }
 
 nsStylePosition::~nsStylePosition(void) 
 { 
   MOZ_COUNT_DTOR(nsStylePosition);
 }
@@ -1157,16 +1159,18 @@ nsChangeHint nsStylePosition::CalcDiffer
   }
 
 #ifdef MOZ_FLEXBOX
   // Properties that apply to flex items:
   // NOTE: Changes to "order" on a flex item may trigger some repositioning.
   // If we're in a multi-line flex container, it also may affect our size
   // (and that of our container & siblings) by shuffling items between lines.
   if (mAlignSelf != aOther.mAlignSelf ||
+      mFlexGrow != aOther.mFlexGrow ||
+      mFlexShrink != aOther.mFlexShrink ||
       mOrder != aOther.mOrder) {
     return NS_CombineHint(hint, nsChangeHint_ReflowFrame);
   }
 
   // Properties that apply to flexbox containers:
 
   // flex-direction can swap a flexbox between vertical & horizontal.
   // align-items can change the sizing of a flexbox & the positioning
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1094,16 +1094,18 @@ struct nsStylePosition {
   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, calc, none
   PRUint8       mBoxSizing;             // [reset] see nsStyleConsts.h
 #ifdef MOZ_FLEXBOX
   PRUint8       mAlignItems;            // [reset] see nsStyleConsts.h
   PRUint8       mAlignSelf;             // [reset] see nsStyleConsts.h
   PRUint8       mFlexDirection;         // [reset] see nsStyleConsts.h
   PRUint8       mJustifyContent;        // [reset] see nsStyleConsts.h
   PRInt32       mOrder;                 // [reset] integer
+  float         mFlexGrow;              // [reset] float
+  float         mFlexShrink;            // [reset] float
 #endif // MOZ_FLEXBOX
   nsStyleCoord  mZIndex;                // [reset] integer, auto
 
   bool WidthDependsOnContainer() const
     { return WidthCoordDependsOnContainer(mWidth); }
   bool MinWidthDependsOnContainer() const
     { return WidthCoordDependsOnContainer(mMinWidth); }
   bool MaxWidthDependsOnContainer() const
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -200,16 +200,17 @@ GARBAGE += css_properties.js
 		visited_image_loading_frame_empty.html \
 		test_load_events_on_stylesheets.html \
 		test_bug721136.html \
 		$(NULL)
 
 ifdef MOZ_FLEXBOX
 _TEST_FILES +=	\
 		test_flexbox_align_self_auto.html \
+		test_flexbox_flex_grow_and_shrink.html \
 		$(NULL)
 endif
 
 _VISITED_REFTEST_FILES = \
 		$(shell find $(topsrcdir)/layout/reftests/css-visited/ -name '*.html' -o -name '*.xhtml') \
 		$(topsrcdir)/layout/reftests/svg/pseudo-classes-02.svg \
 		$(topsrcdir)/layout/reftests/svg/pseudo-classes-02-ref.svg \
 		$(topsrcdir)/layout/reftests/svg/as-image/lime100x100.svg \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -758,16 +758,32 @@ var gCSSProperties = {
 	"-moz-flex-direction": {
 		domProp: "MozFlexDirection",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "row" ],
 		other_values: [ "row-reverse", "column", "column-reverse" ],
 		invalid_values: [ "10px", "30%", "justify", "column wrap" ]
 	},
+	"-moz-flex-grow": {
+		domProp: "MozFlexGrow",
+		inherited: false,
+		type: CSS_TYPE_LONGHAND,
+		initial_values: [ "0" ],
+		other_values: [ "3", "1", "1.0", "2.5", "123" ],
+		invalid_values: [ "0px", "-5", "1%", "3em", "stretch", "auto" ]
+	},
+	"-moz-flex-shrink": {
+		domProp: "MozFlexShrink",
+		inherited: false,
+		type: CSS_TYPE_LONGHAND,
+		initial_values: [ "1" ],
+		other_values: [ "3", "0", "0.0", "2.5", "123" ],
+		invalid_values: [ "0px", "-5", "1%", "3em", "stretch", "auto" ]
+	},
 	"-moz-order": {
 		domProp: "MozOrder",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "0" ],
 		other_values: [ "1", "99999", "-1", "-50" ],
 		invalid_values: [ "0px", "1.0", "1.", "1%", "0.2", "3em", "stretch" ]
 	},
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_flexbox_flex_grow_and_shrink.html
@@ -0,0 +1,183 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=696253
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for flex-grow and flex-shrink animation (Bug 696253)</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="animation_utils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style type="text/css">
+
+  /* Set -moz-flex-grow and -moz-flex-shrink to nonzero values,
+     when no animations are applied. */
+
+  * { -moz-flex-grow: 10; -moz-flex-shrink: 20 }
+
+  /* These animations SHOULD affect computed style */
+  @-moz-keyframes flexGrowTwoToThree {
+     0%   { -moz-flex-grow: 2 }
+     100% { -moz-flex-grow: 3 }
+  }
+  @-moz-keyframes flexShrinkTwoToThree {
+     0%   { -moz-flex-shrink: 2 }
+     100% { -moz-flex-shrink: 3 }
+  }
+  @-moz-keyframes flexGrowZeroToZero {
+     0%   { -moz-flex-grow: 0 }
+     100% { -moz-flex-grow: 0 }
+  }
+  @-moz-keyframes flexShrinkZeroToZero {
+     0%   { -moz-flex-shrink: 0 }
+     100% { -moz-flex-shrink: 0 }
+  }
+
+  /* These animations SHOULD NOT affect computed style. (flex-grow and
+     flex-shrink are animatable "except between '0' and other values") */
+  @-moz-keyframes flexGrowZeroToOne {
+     0%   { -moz-flex-grow: 0 }
+     100% { -moz-flex-grow: 1 }
+  }
+  @-moz-keyframes flexShrinkZeroToOne {
+     0%   { -moz-flex-shrink: 0 }
+     100% { -moz-flex-shrink: 1 }
+  }
+  @-moz-keyframes flexGrowOneToZero {
+     0%   { -moz-flex-grow: 1 }
+     100% { -moz-flex-grow: 0 }
+  }
+  @-moz-keyframes flexShrinkOneToZero {
+     0%   { -moz-flex-shrink: 1 }
+     100% { -moz-flex-shrink: 0 }
+  }
+
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696253">Mozilla Bug 696253</a>
+<div id="display">
+  <div id="myDiv"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+"use strict";
+
+/** Test for flex-grow and flex-shrink animation (Bug 696253) **/
+
+function advance_clock(milliseconds) {
+  SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh(milliseconds);
+}
+
+var display = document.getElementById("display");
+var div = null;
+var cs = null;
+function new_div(style) {
+  return new_element("div", style);
+}
+function new_element(tagname, style) {
+  if (div != null || cs != null) {
+    ok(false, "test author forgot to call done_div");
+  }
+  if (typeof(style) != "string") {
+    ok(false, "test author forgot to pass argument");
+  }
+  div = document.createElement(tagname);
+  div.setAttribute("style", style);
+  display.appendChild(div);
+  cs = getComputedStyle(div, "");
+}
+
+function done_div() {
+  display.removeChild(div);
+  div = null;
+  cs = null;
+}
+// take over the refresh driver
+advance_clock(0);
+
+// ANIMATIONS THAT SHOULD AFFECT COMPUTED STYLE
+// --------------------------------------------
+
+// flexGrowTwoToThree: 2.0 at 0%, 2.5 at 50%, 10 after animation is over
+new_div("-moz-animation: flexGrowTwoToThree linear 1s");
+is_approx(cs.MozFlexGrow, 2, 0.01, "flexGrowTwoToThree at 0.0s");
+advance_clock(500);
+is_approx(cs.MozFlexGrow, 2.5, 0.01, "flexGrowTwoToThree at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexGrow, 10, "flexGrowTwoToThree at 1.5s");
+done_div();
+
+// flexShrinkTwoToThree: 2.0 at 0%, 2.5 at 50%, 20 after animation is over
+new_div("-moz-animation: flexShrinkTwoToThree linear 1s");
+is_approx(cs.MozFlexShrink, 2, 0.01,  "flexShrinkTwoToThree at 0.0s");
+advance_clock(500);
+is_approx(cs.MozFlexShrink, 2.5, 0.01, "flexShrinkTwoToThree at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexShrink, 20, "flexShrinkTwoToThree at 1.5s");
+done_div();
+
+// flexGrowZeroToZero: 0 at 0%, 0 at 50%, 10 after animation is over
+new_div("-moz-animation: flexGrowZeroToZero linear 1s");
+is(cs.MozFlexGrow, 0, "flexGrowZeroToZero at 0.0s");
+advance_clock(500);
+is(cs.MozFlexGrow, 0, "flexGrowZeroToZero at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexGrow, 10, "flexGrowZeroToZero at 1.5s");
+done_div();
+
+// flexShrinkZeroToZero: 0 at 0%, 0 at 50%, 20 after animation is over
+new_div("-moz-animation: flexShrinkZeroToZero linear 1s");
+is(cs.MozFlexShrink, 0, "flexShrinkZeroToZero at 0.0s");
+advance_clock(500);
+is(cs.MozFlexShrink, 0, "flexShrinkZeroToZero at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexShrink, 20, "flexShrinkZeroToZero at 1.5s");
+done_div();
+
+// ANIMATIONS THAT SHOULD NOT AFFECT COMPUTED STYLE
+// ------------------------------------------------
+
+// flexGrowZeroToOne: no effect on computed style. 10 all the way through.
+new_div("-moz-animation: flexGrowZeroToOne linear 1s");
+is(cs.MozFlexGrow, 10, "flexGrowZeroToOne at 0.0s");
+advance_clock(500);
+is(cs.MozFlexGrow, 10, "flexGrowZeroToOne at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexGrow, 10, "flexGrowZeroToOne at 1.5s");
+done_div();
+
+// flexShrinkZeroToOne: no effect on computed style. 20 all the way through.
+new_div("-moz-animation: flexShrinkZeroToOne linear 1s");
+is(cs.MozFlexShrink, 20,  "flexShrinkZeroToOne at 0.0s");
+advance_clock(500);
+is(cs.MozFlexShrink, 20, "flexShrinkZeroToOne at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexShrink, 20, "flexShrinkZeroToOne at 1.5s");
+done_div();
+
+// flexGrowOneToZero: no effect on computed style. 10 all the way through.
+new_div("-moz-animation: flexGrowOneToZero linear 1s");
+is(cs.MozFlexGrow, 10, "flexGrowOneToZero at 0.0s");
+advance_clock(500);
+is(cs.MozFlexGrow, 10, "flexGrowOneToZero at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexGrow, 10, "flexGrowOneToZero at 1.5s");
+done_div();
+
+// flexShrinkOneToZero: no effect on computed style. 20 all the way through.
+new_div("-moz-animation: flexShrinkOneToZero linear 1s");
+is(cs.MozFlexShrink, 20,  "flexShrinkOneToZero at 0.0s");
+advance_clock(500);
+is(cs.MozFlexShrink, 20, "flexShrinkOneToZero at 0.5s");
+advance_clock(1000);
+is(cs.MozFlexShrink, 20, "flexShrinkOneToZero at 1.5s");
+done_div();
+
+SpecialPowers.DOMWindowUtils.restoreNormalRefresh();
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/style/test/test_transitions_per_property.html
+++ b/layout/style/test/test_transitions_per_property.html
@@ -113,16 +113,20 @@ var supported_properties = {
     "fill": [ test_color_transition ],
     "fill-opacity" : [ test_float_zeroToOne_transition,
                        // opacity is clamped in computed style
                        // (not parsing/interpolation)
                        test_float_zeroToOne_clamped ],
 /* XXXdholbert In builds with MOZ_FLEXBOX enabled, this should be uncommented.
    (This would be #ifdef MOZ_FLEXBOX, if that worked in JS files.)
 
+    "-moz-flex-grow": [ test_float_zeroToOne_transition,
+                        test_float_aboveOne_transition ],
+    "-moz-flex-shrink": [ test_float_zeroToOne_transition,
+                          test_float_aboveOne_transition ],
     "-moz-order": [ test_integer_transition ],
 
 */
     "flood-color": [ test_color_transition ],
     "flood-opacity" : [ test_float_zeroToOne_transition,
                         // opacity is clamped in computed style
                         // (not parsing/interpolation)
                         test_float_zeroToOne_clamped ],