Bug 1313254 part 1 - [css-align] Change "baseline|last-baseline" to "[ first | last ]? baseline". r=dholbert
authorMats Palmgren <mats@mozilla.com>
Sat, 05 Nov 2016 02:57:07 +0100
changeset 347954 28219b1ad2983b16d1dbbab260aae44bb2cdd0c2
parent 347953 728204430c0bf24aeb3d0f256f24827772f43430
child 347955 06769bb604a358d6f18e7843cc90123078051edd
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1313254
milestone52.0a1
Bug 1313254 part 1 - [css-align] Change "baseline|last-baseline" to "[ first | last ]? baseline". r=dholbert
layout/style/nsCSSKeywordList.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsCSSValue.cpp
layout/style/test/property_database.js
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -271,16 +271,17 @@ CSS_KEY(extra-expanded, extra_expanded)
 CSS_KEY(ew-resize, ew_resize)
 CSS_KEY(fallback, fallback)
 CSS_KEY(fantasy, fantasy)
 CSS_KEY(farthest-side, farthest_side)
 CSS_KEY(farthest-corner, farthest_corner)
 CSS_KEY(fill, fill)
 CSS_KEY(filled, filled)
 CSS_KEY(fill-box, fill_box)
+CSS_KEY(first, first)
 CSS_KEY(fit-content, fit_content)
 CSS_KEY(fixed, fixed)
 CSS_KEY(flat, flat)
 CSS_KEY(flex, flex)
 CSS_KEY(flex-end, flex_end)
 CSS_KEY(flex-start, flex_start)
 CSS_KEY(flip, flip)
 CSS_KEY(forwards, forwards)
@@ -349,18 +350,19 @@ CSS_KEY(justify, justify)
 CSS_KEY(keep-all, keep_all)
 CSS_KEY(khz, khz)
 CSS_KEY(korean-hangul-formal, korean_hangul_formal)
 CSS_KEY(korean-hanja-formal, korean_hanja_formal)
 CSS_KEY(korean-hanja-informal, korean_hanja_informal)
 CSS_KEY(landscape, landscape)
 CSS_KEY(large, large)
 CSS_KEY(larger, larger)
+CSS_KEY(last, last)
+CSS_KEY(last baseline, last_baseline) // only used for DevTools auto-completion
 CSS_KEY(layout, layout)
-CSS_KEY(last-baseline, last_baseline)
 CSS_KEY(left, left)
 CSS_KEY(legacy, legacy)
 CSS_KEY(lighten, lighten)
 CSS_KEY(lighter, lighter)
 CSS_KEY(line-through, line_through)
 CSS_KEY(linear, linear)
 CSS_KEY(lining-nums, lining_nums)
 CSS_KEY(list-item, list_item)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -1211,16 +1211,22 @@ protected:
   //   <hue> = <number> | <angle>
   // The unit of outparam 'aAngle' is degree. Assume the unit to be degree if an
   // unitless <number> is parsed.
   bool ParseHue(float& aAngle);
 
   bool ParseEnum(nsCSSValue& aValue,
                  const KTableEntry aKeywordTable[]);
 
+  // A special ParseEnum for the CSS Box Alignment properties that have
+  // 'baseline' values.  In addition to the keywords in aKeywordTable, it also
+  // parses 'first baseline' and 'last baseline' as a single value.
+  // (aKeywordTable must contain 'baseline')
+  bool ParseAlignEnum(nsCSSValue& aValue, const KTableEntry aKeywordTable[]);
+
   // Variant parsing methods
   CSSParseResult ParseVariant(nsCSSValue& aValue,
                               uint32_t aVariantMask,
                               const KTableEntry aKeywordTable[]);
   CSSParseResult ParseVariantWithRestrictions(nsCSSValue& aValue,
                                               int32_t aVariantMask,
                                               const KTableEntry aKeywordTable[],
                                               uint32_t aRestrictions);
@@ -7568,16 +7574,54 @@ CSSParserImpl::ParseEnum(nsCSSValue& aVa
     }
   }
 
   // Put the unknown identifier back and return
   UngetToken();
   return false;
 }
 
+bool
+CSSParserImpl::ParseAlignEnum(nsCSSValue& aValue,
+                              const KTableEntry aKeywordTable[])
+{
+  MOZ_ASSERT(nsCSSProps::ValueToKeywordEnum(NS_STYLE_ALIGN_BASELINE,
+                                            aKeywordTable) !=
+               eCSSKeyword_UNKNOWN,
+             "Please use ParseEnum instead");
+  nsSubstring* ident = NextIdent();
+  if (!ident) {
+    return false;
+  }
+  nsCSSKeyword baselinePrefix = eCSSKeyword_first;
+  nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(*ident);
+  if (keyword == eCSSKeyword_first || keyword == eCSSKeyword_last) {
+    baselinePrefix = keyword;
+    ident = NextIdent();
+    if (!ident) {
+      return false;
+    }
+    keyword = nsCSSKeywords::LookupKeyword(*ident);
+  }
+  if (eCSSKeyword_UNKNOWN < keyword) {
+    int32_t value;
+    if (nsCSSProps::FindKeyword(keyword, aKeywordTable, value)) {
+      if (baselinePrefix == eCSSKeyword_last &&
+          keyword == eCSSKeyword_baseline) {
+        value = NS_STYLE_ALIGN_LAST_BASELINE;
+      }
+      aValue.SetIntValue(value, eCSSUnit_Enumerated);
+      return true;
+    }
+  }
+
+  // Put the unknown identifier back and return
+  UngetToken();
+  return false;
+}
 
 struct UnitInfo {
   char name[6];  // needs to be long enough for the longest unit, with
                  // terminating null.
   uint32_t length;
   nsCSSUnit unit;
   int32_t type;
 };
@@ -10054,17 +10098,17 @@ CSSParserImpl::ParseJustifyItems()
     if (MOZ_UNLIKELY(ParseEnum(value, nsCSSProps::kAlignLegacy))) {
       nsCSSValue legacy;
       if (!ParseEnum(legacy, nsCSSProps::kAlignLegacyPosition)) {
         return false; // leading 'legacy' not followed by 'left' etc is an error
       }
       value.SetIntValue(value.GetIntValue() | legacy.GetIntValue(),
                         eCSSUnit_Enumerated);
     } else {
-      if (!ParseEnum(value, nsCSSProps::kAlignAutoNormalStretchBaseline)) {
+      if (!ParseAlignEnum(value, nsCSSProps::kAlignAutoNormalStretchBaseline)) {
         if (!ParseAlignJustifyPosition(value, nsCSSProps::kAlignSelfPosition) ||
             value.GetUnit() == eCSSUnit_Null) {
           return false;
         }
         // check for a trailing 'legacy' after 'left' etc
         auto val = value.GetIntValue();
         if (val == NS_STYLE_JUSTIFY_CENTER ||
             val == NS_STYLE_JUSTIFY_LEFT   ||
@@ -10083,17 +10127,17 @@ CSSParserImpl::ParseJustifyItems()
 
 // normal | stretch | <baseline-position> |
 // [ <overflow-position>? && <self-position> ]
 bool
 CSSParserImpl::ParseAlignItems()
 {
   nsCSSValue value;
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
-    if (!ParseEnum(value, nsCSSProps::kAlignNormalStretchBaseline)) {
+    if (!ParseAlignEnum(value, nsCSSProps::kAlignNormalStretchBaseline)) {
       if (!ParseAlignJustifyPosition(value, nsCSSProps::kAlignSelfPosition) ||
           value.GetUnit() == eCSSUnit_Null) {
         return false;
       }
     }
   }
   AppendValue(eCSSProperty_align_items, value);
   return true;
@@ -10101,17 +10145,17 @@ CSSParserImpl::ParseAlignItems()
 
 // auto | normal | stretch | <baseline-position> |
 // [ <overflow-position>? && <self-position> ]
 bool
 CSSParserImpl::ParseAlignJustifySelf(nsCSSPropertyID aPropID)
 {
   nsCSSValue value;
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
-    if (!ParseEnum(value, nsCSSProps::kAlignAutoNormalStretchBaseline)) {
+    if (!ParseAlignEnum(value, nsCSSProps::kAlignAutoNormalStretchBaseline)) {
       if (!ParseAlignJustifyPosition(value, nsCSSProps::kAlignSelfPosition) ||
           value.GetUnit() == eCSSUnit_Null) {
         return false;
       }
     }
   }
   AppendValue(aPropID, value);
   return true;
@@ -10120,17 +10164,17 @@ CSSParserImpl::ParseAlignJustifySelf(nsC
 // normal | <baseline-position> | [ <content-distribution> ||
 //   [ <overflow-position>? && <content-position> ] ]
 // (the part after the || is called <*-position> below)
 bool
 CSSParserImpl::ParseAlignJustifyContent(nsCSSPropertyID aPropID)
 {
   nsCSSValue value;
   if (!ParseSingleTokenVariant(value, VARIANT_INHERIT, nullptr)) {
-    if (!ParseEnum(value, nsCSSProps::kAlignNormalBaseline)) {
+    if (!ParseAlignEnum(value, nsCSSProps::kAlignNormalBaseline)) {
       nsCSSValue fallbackValue;
       if (!ParseEnum(value, nsCSSProps::kAlignContentDistribution)) {
         if (!ParseAlignJustifyPosition(fallbackValue,
                                        nsCSSProps::kAlignContentPosition) ||
             fallbackValue.GetUnit() == eCSSUnit_Null) {
           return false;
         }
         // optional <content-distribution> after <*-position> ...
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1348,17 +1348,17 @@ const KTableEntry nsCSSProps::kAlignAllK
   { eCSSKeyword_start,         NS_STYLE_ALIGN_START },
   { eCSSKeyword_end,           NS_STYLE_ALIGN_END },
   { eCSSKeyword_flex_start,    NS_STYLE_ALIGN_FLEX_START },
   { eCSSKeyword_flex_end,      NS_STYLE_ALIGN_FLEX_END },
   { eCSSKeyword_center,        NS_STYLE_ALIGN_CENTER },
   { eCSSKeyword_left,          NS_STYLE_ALIGN_LEFT },
   { eCSSKeyword_right,         NS_STYLE_ALIGN_RIGHT },
   { eCSSKeyword_baseline,      NS_STYLE_ALIGN_BASELINE },
-  { eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
+  // Also "first/last baseline"; see nsCSSValue::AppendAlignJustifyValueToString
   { eCSSKeyword_stretch,       NS_STYLE_ALIGN_STRETCH },
   { eCSSKeyword_self_start,    NS_STYLE_ALIGN_SELF_START },
   { eCSSKeyword_self_end,      NS_STYLE_ALIGN_SELF_END },
   { eCSSKeyword_space_between, NS_STYLE_ALIGN_SPACE_BETWEEN },
   { eCSSKeyword_space_around,  NS_STYLE_ALIGN_SPACE_AROUND },
   { eCSSKeyword_space_evenly,  NS_STYLE_ALIGN_SPACE_EVENLY },
   { eCSSKeyword_legacy,        NS_STYLE_ALIGN_LEGACY },
   { eCSSKeyword_safe,          NS_STYLE_ALIGN_SAFE },
@@ -1397,32 +1397,32 @@ const KTableEntry nsCSSProps::kAlignLega
   { eCSSKeyword_UNKNOWN,       -1 }
 };
 
 const KTableEntry nsCSSProps::kAlignAutoNormalStretchBaseline[] = {
   { eCSSKeyword_auto,          NS_STYLE_ALIGN_AUTO },
   { eCSSKeyword_normal,        NS_STYLE_ALIGN_NORMAL },
   { eCSSKeyword_stretch,       NS_STYLE_ALIGN_STRETCH },
   { eCSSKeyword_baseline,      NS_STYLE_ALIGN_BASELINE },
-  { eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
+  // Also "first baseline" & "last baseline"; see CSSParserImpl::ParseAlignEnum
   { eCSSKeyword_UNKNOWN,       -1 }
 };
 
 const KTableEntry nsCSSProps::kAlignNormalStretchBaseline[] = {
   { eCSSKeyword_normal,        NS_STYLE_ALIGN_NORMAL },
   { eCSSKeyword_stretch,       NS_STYLE_ALIGN_STRETCH },
   { eCSSKeyword_baseline,      NS_STYLE_ALIGN_BASELINE },
-  { eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
+  // Also "first baseline" & "last baseline"; see CSSParserImpl::ParseAlignEnum
   { eCSSKeyword_UNKNOWN,       -1 }
 };
 
 const KTableEntry nsCSSProps::kAlignNormalBaseline[] = {
   { eCSSKeyword_normal,        NS_STYLE_ALIGN_NORMAL },
   { eCSSKeyword_baseline,      NS_STYLE_ALIGN_BASELINE },
-  { eCSSKeyword_last_baseline, NS_STYLE_ALIGN_LAST_BASELINE },
+  // Also "first baseline" & "last baseline"; see CSSParserImpl::ParseAlignEnum
   { eCSSKeyword_UNKNOWN,       -1 }
 };
 
 const KTableEntry nsCSSProps::kAlignContentDistribution[] = {
   { eCSSKeyword_stretch,       NS_STYLE_ALIGN_STRETCH },
   { eCSSKeyword_space_between, NS_STYLE_ALIGN_SPACE_BETWEEN },
   { eCSSKeyword_space_around,  NS_STYLE_ALIGN_SPACE_AROUND },
   { eCSSKeyword_space_evenly,  NS_STYLE_ALIGN_SPACE_EVENLY },
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -776,19 +776,19 @@ public:
   static const KTableEntry kElevationKTable[];
   static const KTableEntry kEmptyCellsKTable[];
   // -- tables for parsing the {align,justify}-{content,items,self} properties --
   static const KTableEntry kAlignAllKeywords[];
   static const KTableEntry kAlignOverflowPosition[]; // <overflow-position>
   static const KTableEntry kAlignSelfPosition[];     // <self-position>
   static const KTableEntry kAlignLegacy[];           // 'legacy'
   static const KTableEntry kAlignLegacyPosition[];   // 'left/right/center'
-  static const KTableEntry kAlignAutoNormalStretchBaseline[]; // 'auto/normal/stretch/baseline/last-baseline'
-  static const KTableEntry kAlignNormalStretchBaseline[]; // 'normal/stretch/baseline/last-baseline'
-  static const KTableEntry kAlignNormalBaseline[]; // 'normal/baseline/last-baseline'
+  static const KTableEntry kAlignAutoNormalStretchBaseline[]; // 'auto/normal/stretch/baseline'
+  static const KTableEntry kAlignNormalStretchBaseline[]; // 'normal/stretch/baseline'
+  static const KTableEntry kAlignNormalBaseline[]; // 'normal/baseline'
   static const KTableEntry kAlignContentDistribution[]; // <content-distribution>
   static const KTableEntry kAlignContentPosition[]; // <content-position>
   // -- tables for auto-completion of the {align,justify}-{content,items,self} properties --
   static const KTableEntry kAutoCompletionAlignJustifySelf[];
   static const KTableEntry kAutoCompletionAlignItems[];
   static const KTableEntry kAutoCompletionAlignJustifyContent[];
   // ------------------------------------------------------------------
   static const KTableEntry kFlexDirectionKTable[];
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1193,19 +1193,23 @@ nsCSSValue::AppendAlignJustifyValueToStr
   aValue &= ~overflowPos;
   MOZ_ASSERT(!(aValue & NS_STYLE_ALIGN_FLAG_BITS),
              "unknown bits in align/justify value");
   MOZ_ASSERT((aValue != NS_STYLE_ALIGN_AUTO &&
               aValue != NS_STYLE_ALIGN_NORMAL &&
               aValue != NS_STYLE_ALIGN_BASELINE &&
               aValue != NS_STYLE_ALIGN_LAST_BASELINE) ||
              (!legacy && !overflowPos),
-             "auto/normal/baseline/last-baseline never have any flags");
+             "auto/normal/baseline/'last baseline' never have any flags");
   MOZ_ASSERT(legacy == 0 || overflowPos == 0,
              "'legacy' together with <overflow-position>");
+  if (aValue == NS_STYLE_ALIGN_LAST_BASELINE) {
+    aResult.AppendLiteral("last ");
+    aValue = NS_STYLE_ALIGN_BASELINE;
+  }
   const auto& kwtable(nsCSSProps::kAlignAllKeywords);
   AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(aValue, kwtable), aResult);
   // Don't serialize the 'unsafe' keyword; it's the default.
   if (MOZ_UNLIKELY(overflowPos == NS_STYLE_ALIGN_SAFE)) {
     aResult.Append(' ');
     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(overflowPos, kwtable),
                        aResult);
   }
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -4481,88 +4481,89 @@ var gCSSProperties = {
   },
   "align-content": {
     domProp: "alignContent",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "normal" ],
     other_values: [ "start", "end", "flex-start", "flex-end", "center", "left",
                     "right", "space-between", "space-around", "space-evenly",
-                    "baseline", "last-baseline", "stretch", "start safe",
+                    "first baseline", "last baseline", "baseline", "stretch", "start safe",
                     "unsafe end", "unsafe end stretch", "end safe space-evenly" ],
     invalid_values: [ "none", "5", "self-end", "safe", "normal unsafe", "unsafe safe",
                       "safe baseline", "baseline unsafe", "baseline end", "end normal",
                       "safe end unsafe start", "safe end unsafe", "normal safe start",
                       "unsafe end start", "end start safe", "space-between unsafe",
-                      "stretch safe", "auto" ]
+                      "stretch safe", "auto", "first", "last" ]
   },
   "align-items": {
     domProp: "alignItems",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "normal" ],
     // Can't test 'left'/'right' here since that computes to 'start' for blocks.
     other_values: [ "end", "flex-start", "flex-end", "self-start", "self-end",
-                    "center", "stretch", "baseline", "unsafe left", "start",
-                    "center unsafe", "safe right", "center safe" ],
+                    "center", "stretch", "first baseline", "last baseline", "baseline",
+                    "unsafe left", "start", "center unsafe", "safe right", "center safe" ],
     invalid_values: [ "space-between", "abc", "5%", "legacy", "legacy end",
                       "end legacy", "unsafe", "unsafe baseline", "normal unsafe",
                       "safe left unsafe", "safe stretch", "end end", "auto" ]
   },
   "align-self": {
     domProp: "alignSelf",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto" ],
     other_values: [ "normal", "start", "flex-start", "flex-end", "center", "stretch",
-                    "baseline", "last-baseline", "right safe", "unsafe center",
-                    "self-start", "self-end safe" ],
+                    "first baseline", "last baseline", "baseline", "right safe",
+                    "unsafe 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: [ "normal" ],
     other_values: [ "start", "end", "flex-start", "flex-end", "center", "left",
                     "right", "space-between", "space-around", "space-evenly",
-                    "baseline", "last-baseline", "stretch", "start safe",
+                    "first baseline", "last baseline", "baseline", "stretch", "start safe",
                     "unsafe end", "unsafe end stretch", "end safe space-evenly" ],
     invalid_values: [ "30px", "5%", "self-end", "safe", "normal unsafe", "unsafe safe",
                       "safe baseline", "baseline unsafe", "baseline end", "normal end",
                       "safe end unsafe start", "safe end unsafe", "normal safe start",
                       "unsafe end start", "end start safe", "space-around unsafe",
-                      "safe stretch", "auto" ]
+                      "safe stretch", "auto", "first", "last" ]
   },
   "justify-items": {
     domProp: "justifyItems",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto", "normal" ],
     other_values: [ "end", "flex-start", "flex-end", "self-start", "self-end",
-                    "center", "left", "right", "baseline", "stretch", "start",
-                    "legacy left", "right legacy", "legacy center",
-                    "unsafe right", "left unsafe", "safe right", "center safe" ],
+                    "center", "left", "right", "first baseline", "last baseline",
+                    "baseline", "stretch", "start", "legacy left", "right legacy",
+                    "legacy center", "unsafe right", "left unsafe", "safe right",
+                    "center safe" ],
     invalid_values: [ "space-between", "abc", "30px", "legacy", "legacy start",
                       "end legacy", "legacy baseline", "legacy legacy", "unsafe",
                       "safe legacy left", "legacy left safe", "legacy safe left",
                       "safe left legacy", "legacy left legacy", "baseline unsafe",
-                      "safe unsafe", "safe left unsafe", "safe stretch" ]
+                      "safe unsafe", "safe left unsafe", "safe stretch", "last" ]
   },
   "justify-self": {
     domProp: "justifySelf",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto" ],
     other_values: [ "normal", "start", "end", "flex-start", "flex-end", "self-start",
-                    "self-end", "center", "left", "right", "baseline",
-                    "last-baseline", "stretch", "left unsafe", "unsafe right",
+                    "self-end", "center", "left", "right", "baseline", "first baseline",
+                    "last baseline", "stretch", "left unsafe", "unsafe right",
                     "safe right", "center safe" ],
-    invalid_values: [ "space-between", "abc", "30px", "none",
-                      "legacy left", "right legacy" ]
+    invalid_values: [ "space-between", "abc", "30px", "none", "first", "last",
+                      "legacy left", "right legacy", "baseline first", "baseline last" ]
   },
   "flex": {
     domProp: "flex",
     inherited: false,
     type: CSS_TYPE_TRUE_SHORTHAND,
     subproperties: [
       "flex-grow",
       "flex-shrink",