Bug 1176782 part 5 - [css-align] Implement additional syntax and values for the 'align-self' property in the style system. r=cam
authorMats Palmgren <mats@mozilla.com>
Tue, 03 Nov 2015 15:18:06 +0100
changeset 270940 ba69ab935f538911ff97764e9f284d7621d663d1
parent 270939 b191efb0028a523d18c0db431959be4ce197d8b8
child 270941 5ed5ee646acd814ac782873ee73194e843695870
push id67508
push usermpalmgren@mozilla.com
push dateTue, 03 Nov 2015 14:18:18 +0000
treeherdermozilla-inbound@56aebef6afdf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscam
bugs1176782
milestone45.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 1176782 part 5 - [css-align] Implement additional syntax and values for the 'align-self' property in the style system. r=cam
layout/generic/nsFlexContainerFrame.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -1560,25 +1560,34 @@ FlexItem::FlexItem(nsHTMLReflowState& aF
     mShareOfWeightSoFar(0.0f),
     mIsFrozen(false),
     mHadMinViolation(false),
     mHadMaxViolation(false),
     mHadMeasuringReflow(false),
     mIsStretched(false),
     mIsStrut(false),
     // mNeedsMinSizeAutoResolution is initialized in CheckForMinSizeAuto()
-    mWM(aFlexItemReflowState.GetWritingMode()),
-    mAlignSelf(aFlexItemReflowState.mStylePosition->mAlignSelf)
+    mWM(aFlexItemReflowState.GetWritingMode())
+    // mAlignSelf, see below
 {
   MOZ_ASSERT(mFrame, "expecting a non-null child frame");
   MOZ_ASSERT(mFrame->GetType() != nsGkAtoms::placeholderFrame,
              "placeholder frames should not be treated as flex items");
   MOZ_ASSERT(!(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
              "out-of-flow frames should not be treated as flex items");
 
+  mAlignSelf = aFlexItemReflowState.mStylePosition->ComputedAlignSelf(
+                 aFlexItemReflowState.mStyleDisplay,
+                 mFrame->StyleContext()->GetParent());
+  if (MOZ_UNLIKELY(mAlignSelf == NS_STYLE_ALIGN_AUTO)) {
+    // Happens in rare edge cases when 'position' was ignored by the frame
+    // constructor (and the style system computed 'auto' based on 'position').
+    mAlignSelf = NS_STYLE_ALIGN_STRETCH;
+  }
+
   SetFlexBaseSizeAndMainSize(aFlexBaseSize);
   CheckForMinSizeAuto(aFlexItemReflowState, aAxisTracker);
 
   // Assert that any "auto" margin components are set to 0.
   // (We'll resolve them later; until then, we want to treat them as 0-sized.)
 #ifdef DEBUG
   {
     const nsStyleSides& styleMargin =
@@ -1587,23 +1596,16 @@ FlexItem::FlexItem(nsHTMLReflowState& aF
       if (styleMargin.GetUnit(side) == eStyleUnit_Auto) {
         MOZ_ASSERT(GetMarginComponentForSide(side) == 0,
                    "Someone else tried to resolve our auto margin");
       }
     }
   }
 #endif // DEBUG
 
-  // Resolve "align-self: auto" to parent's "align-items" value.
-  if (mAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) {
-    auto parent = mFrame->StyleContext()->GetParent();
-    mAlignSelf =
-      parent->StylePosition()->ComputedAlignItems(parent->StyleDisplay());
-  }
-
   // If the flex item's inline axis is the same as the cross axis, then
   // 'align-self:baseline' is identical to 'flex-start'. If that's the case, we
   // just directly convert our align-self value here, so that we don't have to
   // handle this with special cases elsewhere.
   // Moreover: for the time being (until we support writing-modes),
   // all inline axes are horizontal -- so we can just check if the cross axis
   // is horizontal.
   // FIXME: Once we support writing-mode (vertical text), this
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -10629,16 +10629,18 @@ CSSParserImpl::ParsePropertyByFunction(n
     return ParseGridColumnRow(eCSSProperty_grid_row_start,
                               eCSSProperty_grid_row_end);
   case eCSSProperty_grid_area:
     return ParseGridArea();
   case eCSSProperty_image_region:
     return ParseRect(eCSSProperty_image_region);
   case eCSSProperty_align_items:
     return ParseAlignItemsSelfJustifySelf(aPropID);
+  case eCSSProperty_align_self:
+    return ParseAlignItemsSelfJustifySelf(aPropID);
   case eCSSProperty_justify_content:
     return ParseAlignJustifyContent(aPropID);
   case eCSSProperty_justify_items:
     return ParseJustifyItems();
   case eCSSProperty_justify_self:
     return ParseAlignItemsSelfJustifySelf(aPropID);
   case eCSSProperty_list_style:
     return ParseListStyle();
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1601,22 +1601,22 @@ CSS_PROP_POSITION(
     0,
     nullptr,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_POSITION(
     align-self,
     align_self,
     AlignSelf,
-    CSS_PROPERTY_PARSE_VALUE,
-    "",
-    VARIANT_HK,
-    kAlignSelfKTable,
-    offsetof(nsStylePosition, mAlignSelf),
-    eStyleAnimType_EnumU8)
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "",
+    0,
+    nullptr,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
 CSS_PROP_SHORTHAND(
     flex,
     flex,
     Flex,
     CSS_PROPERTY_PARSE_FUNCTION,
     "")
 CSS_PROP_POSITION(
     flex-basis,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1335,27 +1335,16 @@ const KTableValue nsCSSProps::kAlignCont
   eCSSKeyword_flex_end,      NS_STYLE_ALIGN_CONTENT_FLEX_END,
   eCSSKeyword_center,        NS_STYLE_ALIGN_CONTENT_CENTER,
   eCSSKeyword_space_between, NS_STYLE_ALIGN_CONTENT_SPACE_BETWEEN,
   eCSSKeyword_space_around,  NS_STYLE_ALIGN_CONTENT_SPACE_AROUND,
   eCSSKeyword_stretch,       NS_STYLE_ALIGN_CONTENT_STRETCH,
   eCSSKeyword_UNKNOWN,-1
 };
 
-// Note: 'align-self' takes the same keywords as 'align-items', plus 'auto'.
-const KTableValue nsCSSProps::kAlignSelfKTable[] = {
-  eCSSKeyword_flex_start, NS_STYLE_ALIGN_FLEX_START,
-  eCSSKeyword_flex_end,   NS_STYLE_ALIGN_FLEX_END,
-  eCSSKeyword_center,     NS_STYLE_ALIGN_CENTER,
-  eCSSKeyword_baseline,   NS_STYLE_ALIGN_BASELINE,
-  eCSSKeyword_stretch,    NS_STYLE_ALIGN_STRETCH,
-  eCSSKeyword_auto,       NS_STYLE_ALIGN_SELF_AUTO,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const KTableValue nsCSSProps::kFlexDirectionKTable[] = {
   eCSSKeyword_row,            NS_STYLE_FLEX_DIRECTION_ROW,
   eCSSKeyword_row_reverse,    NS_STYLE_FLEX_DIRECTION_ROW_REVERSE,
   eCSSKeyword_column,         NS_STYLE_FLEX_DIRECTION_COLUMN,
   eCSSKeyword_column_reverse, NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE,
   eCSSKeyword_UNKNOWN,-1
 };
 
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1331,16 +1331,17 @@ nsCSSValue::AppendToString(nsCSSProperty
                    != eCSSKeyword_UNKNOWN, "unknown fallback value");
         aResult.Append(' ');
         AppendAlignJustifyValueToString(fallback, aResult);
       }
       break;
     }
 
     case eCSSProperty_align_items:
+    case eCSSProperty_align_self:
     case eCSSProperty_justify_items:
     case eCSSProperty_justify_self:
       AppendAlignJustifyValueToString(intValue, aResult);
       break;
 
     default:
       const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue);
       AppendASCIItoUTF16(name, aResult);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -3866,42 +3866,16 @@ nsComputedDOMStyle::DoGetAlignContent()
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(StylePosition()->mAlignContent,
                                    nsCSSProps::kAlignContentKTable));
   return val;
 }
 
 CSSValue*
-nsComputedDOMStyle::DoGetAlignSelf()
-{
-  nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
-  uint8_t computedAlignSelf = StylePosition()->mAlignSelf;
-
-  if (computedAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) {
-    // "align-self: auto" needs to compute to parent's align-items value.
-    nsStyleContext* parentStyleContext = mStyleContext->GetParent();
-    if (parentStyleContext) {
-      computedAlignSelf = parentStyleContext->StylePosition()->
-        ComputedAlignItems(parentStyleContext->StyleDisplay());
-    } else {
-      // No parent --> use default.
-      computedAlignSelf = NS_STYLE_ALIGN_STRETCH; // XXX temporary, will be removed in later patch
-    }
-  }
-
-  MOZ_ASSERT(computedAlignSelf != NS_STYLE_ALIGN_SELF_AUTO,
-             "Should have swapped out 'auto' for something non-auto");
-  val->SetIdent(
-    nsCSSProps::ValueToKeywordEnum(computedAlignSelf,
-                                   nsCSSProps::kAlignSelfKTable));
-  return val;
-}
-
-CSSValue*
 nsComputedDOMStyle::DoGetFlexBasis()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
 
   // XXXdholbert We could make this more automagic and resolve percentages
   // if we wanted, by passing in a PercentageBaseGetter instead of nullptr
   // below.  Logic would go like this:
   //   if (i'm a flex item) {
@@ -3968,16 +3942,28 @@ nsComputedDOMStyle::DoGetAlignItems()
   nsAutoString str;
   auto align = StylePosition()->ComputedAlignItems(StyleDisplay());
   nsCSSValue::AppendAlignJustifyValueToString(align, str);
   val->SetString(str);
   return val;
 }
 
 CSSValue*
+nsComputedDOMStyle::DoGetAlignSelf()
+{
+  nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
+  auto align = StylePosition()->
+    ComputedAlignSelf(StyleDisplay(), mStyleContext->GetParent());
+  nsAutoString str;
+  nsCSSValue::AppendAlignJustifyValueToString(align, str);
+  val->SetString(str);
+  return val;
+}
+
+CSSValue*
 nsComputedDOMStyle::DoGetJustifyContent()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
   nsAutoString str;
   auto justify = StylePosition()->ComputedJustifyContent(StyleDisplay());
   nsCSSValue::AppendAlignJustifyValueToString(justify & NS_STYLE_JUSTIFY_ALL_BITS, str);
   auto fallback = justify >> NS_STYLE_JUSTIFY_ALL_SHIFT;
   if (fallback) {
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -7815,64 +7815,36 @@ nsRuleNode::ComputePositionData(void* aS
     SetDiscrete(alignItemsValue,
                 pos->mAlignItems, conditions,
                 SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
                 parentPos->mAlignItems, // unused, we handle 'inherit' above
                 NS_STYLE_ALIGN_AUTO, 0, 0, 0, 0);
   }
 
   // align-self: enum, inherit, initial
-  // NOTE: align-self's initial value is the special keyword "auto", which is
-  // supposed to compute to our parent's computed value of "align-items".  So
-  // technically, "auto" itself is never a valid computed value for align-self,
-  // since it always computes to something else.  Despite that, we do actually
-  // store "auto" in nsStylePosition::mAlignSelf, as NS_STYLE_ALIGN_SELF_AUTO
-  // (and then resolve it as-necessary).  We do this because "auto" is the
-  // initial value for this property, so if we were to actually resolve it in
-  // nsStylePosition, we'd never be able to share any nsStylePosition structs
-  // in the rule tree, since their mAlignSelf values would depend on the parent
-  // style, by default.
-  if (aRuleData->ValueForAlignSelf()->GetUnit() == eCSSUnit_Inherit) {
-    // Special handling for "align-self: inherit", in case we're inheriting
-    // "align-self: auto", in which case we need to resolve the parent's "auto"
-    // and inherit that resolved value.
-    uint8_t inheritedAlignSelf = parentPos->mAlignSelf;
-    if (inheritedAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) {
-      if (!parentContext) {
-        // We're the root node. Nothing to inherit from --> just use default
-        // value.
-        inheritedAlignSelf = NS_STYLE_ALIGN_AUTO; // XXX will be removed in next patch
-      } else {
-        // Our parent's "auto" value should resolve to our grandparent's value
-        // for "align-items".  So, that's what we're supposed to inherit.
-        nsStyleContext* grandparentContext = parentContext->GetParent();
-        if (!grandparentContext) {
-          // No grandparent --> our parent is the root node, so its
-          // "align-self: auto" computes to the default "align-items" value:
-          inheritedAlignSelf = NS_STYLE_ALIGN_AUTO; // XXX will be removed in next patch
-        } else {
-          // Normal case -- we have a grandparent.
-          // Its "align-items" value is what we should end up inheriting.
-          const nsStylePosition* grandparentPos =
-            grandparentContext->StylePosition();
-          inheritedAlignSelf = grandparentPos->ComputedAlignItems(grandparentContext->StyleDisplay());
-          aContext->AddStyleBit(NS_STYLE_USES_GRANDANCESTOR_STYLE);
-        }
-      }
-    }
-
-    pos->mAlignSelf = inheritedAlignSelf;
+  const auto& alignSelfValue = *aRuleData->ValueForAlignSelf();
+  if (MOZ_UNLIKELY(alignSelfValue.GetUnit() == eCSSUnit_Inherit)) {
+    if (MOZ_LIKELY(parentContext)) {
+      nsStyleContext* grandparentContext = parentContext->GetParent();
+      if (MOZ_LIKELY(grandparentContext)) {
+        aContext->AddStyleBit(NS_STYLE_USES_GRANDANCESTOR_STYLE);
+      }
+      pos->mAlignSelf =
+        parentPos->ComputedAlignSelf(parentContext->StyleDisplay(),
+                                     grandparentContext);
+    } else {
+      pos->mAlignSelf = NS_STYLE_ALIGN_START;
+    }
     conditions.SetUncacheable();
   } else {
-    SetDiscrete(*aRuleData->ValueForAlignSelf(),
+    SetDiscrete(alignSelfValue,
                 pos->mAlignSelf, conditions,
                 SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
-                parentPos->mAlignSelf, // (unused -- we handled inherit above)
-                NS_STYLE_ALIGN_SELF_AUTO, // initial == auto
-                0, 0, 0, 0);
+                parentPos->mAlignSelf, // unused, we handle 'inherit' above
+                NS_STYLE_ALIGN_AUTO, 0, 0, 0, 0);
   }
 
   // justify-content: enum, inherit, initial
   const auto& justifyContentValue = *aRuleData->ValueForJustifyContent();
   if (MOZ_UNLIKELY(justifyContentValue.GetUnit() == eCSSUnit_Inherit)) {
     if (MOZ_LIKELY(parentContext)) {
       pos->mJustifyContent =
         parentPos->ComputedJustifyContent(parentContext->StyleDisplay());
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1428,17 +1428,17 @@ nsStylePosition::nsStylePosition(void)
   mGridAutoColumnsMax.SetAutoValue();
   mGridAutoRowsMin.SetAutoValue();
   mGridAutoRowsMax.SetAutoValue();
 
   mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
   mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
   mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH;
   mAlignItems = NS_STYLE_ALIGN_AUTO;
-  mAlignSelf = NS_STYLE_ALIGN_SELF_AUTO;
+  mAlignSelf = NS_STYLE_ALIGN_AUTO;
   mJustifyContent = NS_STYLE_JUSTIFY_AUTO;
   mJustifyItems = NS_STYLE_JUSTIFY_AUTO;
   mJustifySelf = NS_STYLE_JUSTIFY_AUTO;
   mFlexDirection = NS_STYLE_FLEX_DIRECTION_ROW;
   mFlexWrap = NS_STYLE_FLEX_WRAP_NOWRAP;
   mObjectFit = NS_STYLE_OBJECT_FIT_FILL;
   mOrder = NS_STYLE_ORDER_INITIAL;
   mFlexGrow = 0.0f;
@@ -1701,16 +1701,36 @@ nsStylePosition::ComputedAlignItems(cons
 {
   if (mAlignItems != NS_STYLE_ALIGN_AUTO) {
     return MapLeftRightToStart(mAlignItems, eLogicalAxisBlock, aDisplay);
   }
   return aDisplay->IsFlexOrGridDisplayType() ? NS_STYLE_ALIGN_STRETCH
                                              : NS_STYLE_ALIGN_START;
 }
 
+uint8_t
+nsStylePosition::ComputedAlignSelf(const nsStyleDisplay* aDisplay,
+                                   nsStyleContext* aParent) const
+{
+  if (mAlignSelf != NS_STYLE_ALIGN_AUTO) {
+    return MapLeftRightToStart(mAlignSelf, eLogicalAxisBlock, aDisplay);
+  }
+  if (MOZ_UNLIKELY(aDisplay->IsAbsolutelyPositionedStyle())) {
+    return NS_STYLE_ALIGN_AUTO;
+  }
+  if (MOZ_LIKELY(aParent)) {
+    auto parentAlignItems = aParent->StylePosition()->
+      ComputedAlignItems(aParent->StyleDisplay());
+    MOZ_ASSERT(!(parentAlignItems & NS_STYLE_ALIGN_LEGACY),
+               "align-items can't have 'legacy'");
+    return MapLeftRightToStart(parentAlignItems, eLogicalAxisBlock, aDisplay);
+  }
+  return NS_STYLE_ALIGN_START;
+}
+
 uint16_t
 nsStylePosition::ComputedJustifyContent(const nsStyleDisplay* aDisplay) const
 {
   switch (aDisplay->mDisplay) {
     case NS_STYLE_DISPLAY_FLEX:
     case NS_STYLE_DISPLAY_INLINE_FLEX:
       // XXX maybe map 'auto' too? (ISSUE 8 in the spec)
       // https://drafts.csswg.org/css-align-3/#content-distribution
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1398,16 +1398,23 @@ struct nsStylePosition {
 
   /**
    * Return the computed value for 'align-items' given our 'display' value in
    * aDisplay.
    */
   uint8_t ComputedAlignItems(const nsStyleDisplay* aDisplay) const;
 
   /**
+   * Return the computed value for 'align-self' given our 'display' value in
+   * aDisplay and the parent StyleContext aParent (or null for the root).
+   */
+  uint8_t ComputedAlignSelf(const nsStyleDisplay* aDisplay,
+                            nsStyleContext* aParent) const;
+
+  /**
    * Return the computed value for 'justify-content' given our 'display' value
    * in aDisplay.
    */
   uint16_t ComputedJustifyContent(const nsStyleDisplay* aDisplay) const;
 
   /**
    * Return the computed value for 'justify-items' given our 'display' value in
    * aDisplay and the parent StyleContext aParent (or null for the root).
@@ -1433,24 +1440,24 @@ struct nsStylePosition {
   nsStyleCoord  mFlexBasis;             // [reset] coord, percent, enum, calc, auto
   nsStyleCoord  mGridAutoColumnsMin;    // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoColumnsMax;    // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoRowsMin;       // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoRowsMax;       // [reset] coord, percent, enum, calc, flex
   uint8_t       mGridAutoFlow;          // [reset] enumerated. See nsStyleConsts.h
   uint8_t       mBoxSizing;             // [reset] see nsStyleConsts.h
   uint8_t       mAlignContent;          // [reset] see nsStyleConsts.h
-  uint8_t       mAlignSelf;             // [reset] see nsStyleConsts.h
 private:
   friend class nsRuleNode;
   // Helper for the ComputedAlign/Justify* methods.
   uint8_t MapLeftRightToStart(uint8_t aAlign, mozilla::LogicalAxis aAxis,
                               const nsStyleDisplay* aDisplay) const;
 
   uint8_t       mAlignItems;            // [reset] see nsStyleConsts.h
+  uint8_t       mAlignSelf;             // [reset] see nsStyleConsts.h
   uint16_t      mJustifyContent;        // [reset] fallback value in the high byte
   uint8_t       mJustifyItems;          // [reset] see nsStyleConsts.h
   uint8_t       mJustifySelf;           // [reset] see nsStyleConsts.h
 public:
   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
   uint8_t       mObjectFit;             // [reset] see nsStyleConsts.h
   int32_t       mOrder;                 // [reset] integer
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -4066,20 +4066,22 @@ var gCSSProperties = {
     invalid_values: [ "space-between", "abc", "5%", "legacy", "legacy end",
                       "end legacy", "true", "true baseline", "auto true",
                       "safe left true", "safe stretch", "end end" ]
   },
   "align-self": {
     domProp: "alignSelf",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
-    // (Assuming defaults on the parent, 'auto' will compute to 'stretch'.)
-    initial_values: [ "auto", "stretch" ],
-    other_values: [ "flex-start", "flex-end", "center", "baseline" ],
-    invalid_values: [ "space-between", "abc", "30px" ]
+    // (Assuming defaults on the parent, 'auto' will compute to 'start'.)
+    initial_values: [ "auto", "start" ],
+    other_values: [ "flex-start", "flex-end", "center", "stretch",
+                    "baseline", "last-baseline", "right safe", "true center",
+                    "self-start", "self-end safe" ],
+    invalid_values: [ "space-between", "abc", "30px", "stretch safe", "safe" ]
   },
   "justify-content": {
     domProp: "justifyContent",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto" ],
     other_values: [ "start", "end", "flex-start", "flex-end", "center", "left",
                     "right", "space-between", "space-around", "space-evenly",