Bug 1364115 - Allow -moz-stack-sizing to work in a single direction only. r=dbaron,SimonSapin draft
authorNeil Deakin <neil@mozilla.com>
Mon, 15 May 2017 12:33:46 +0100
changeset 577791 c27a637080503999426fb9dbeee1cfc6010f6816
parent 576947 1ec1d88637208098802e57d13db9033902e5a229
child 628590 4c32428d8e15be8455f3cf389c0ca60d1170d837
push id58788
push userpaolo.mozmail@amadzone.org
push dateMon, 15 May 2017 11:36:46 +0000
reviewersdbaron, SimonSapin
bugs1364115
milestone55.0a1
Bug 1364115 - Allow -moz-stack-sizing to work in a single direction only. r=dbaron,SimonSapin MozReview-Commit-ID: Kl7YQpfolTC
devtools/shared/css/generated/properties-db.js
layout/reftests/bugs/346189-1-ref.xul
layout/reftests/bugs/346189-1.xul
layout/reftests/bugs/reftest.list
layout/reftests/xul/reftest.list
layout/reftests/xul/stack-sizing-1-ref.xul
layout/reftests/xul/stack-sizing-1.xul
layout/reftests/xul/stack-sizing-2-ref.xul
layout/reftests/xul/stack-sizing-2.xul
layout/style/nsCSSKeywordList.h
layout/style/nsCSSProps.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/xul/nsStackLayout.cpp
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/xul.mako.rs
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -1229,16 +1229,18 @@ exports.CSS_PROPERTIES = {
   "-moz-stack-sizing": {
     "isInherited": false,
     "subproperties": [
       "-moz-stack-sizing"
     ],
     "supports": [],
     "values": [
       "ignore",
+      "ignore-horizontal",
+      "ignore-vertical",
       "inherit",
       "initial",
       "stretch-to-fit",
       "unset"
     ]
   },
   "-moz-tab-size": {
     "isInherited": true,
@@ -3397,16 +3399,18 @@ exports.CSS_PROPERTIES = {
       "horizontal",
       "horizontal-tb",
       "hsl",
       "hsla",
       "hue",
       "icon",
       "ideographic",
       "ignore",
+      "ignore-horizontal",
+      "ignore-vertical",
       "inactive",
       "infinite",
       "inherit",
       "initial",
       "inline",
       "inline-axis",
       "inline-block",
       "inline-end",
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -455,17 +455,16 @@ fuzzy-if(skiaContent,2,3) == 339289-1.ht
 != 341043-1b.html 341043-1-ref.html
 == 343538-1.html 343538-1-ref.html
 == 343540-1.html 343540-1-ref.html
 == 345267-1a.html 345267-1-ref.html
 == 345267-1b.html 345267-1-ref.html
 == 345267-1c.html 345267-1-ref.html
 == 345267-1d.html 345267-1-ref.html
 != 345563-sub.xhtml 345563-sup.xhtml
-== 346189-1.xul 346189-1-ref.xul
 fuzzy-if(skiaContent,4,2) == 346774-1a.html 346774-1-ref.html
 fuzzy-if(skiaContent,4,2) == 346774-1b.html 346774-1-ref.html
 fuzzy-if(skiaContent,4,2) == 346774-1c.html 346774-1-ref.html
 == 347348-1.xhtml 347348-1-ref.xhtml
 == 347496-1.xhtml 347496-1-ref.xhtml
 == 347912-1.html 347912-1-ref.html
 fails-if(stylo) == 348049-1.xhtml 348049-1-ref.xhtml
 == 348516-1.html 348516-1-ref.html
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -56,16 +56,19 @@ fails-if(!stylo) == object-fit-fill-svg-
 == object-fit-scale-down-svg-002.xul object-fit-scale-down-svg-002-ref.html
 == object-fit-scale-down-svg-003.xul object-fit-scale-down-svg-003-ref.html
 == object-fit-scale-down-svg-004.xul object-fit-scale-down-svg-004-ref.html
 == object-fit-scale-down-svg-005.xul object-fit-scale-down-svg-005-ref.html
 == object-fit-scale-down-svg-006.xul object-fit-scale-down-svg-006-ref.html
 fuzzy-if(webrender,16,20) == object-position-png-001.xul object-position-png-001-ref.html
 == object-position-png-002.xul object-position-png-002-ref.html
 
+== stack-sizing-1.xul stack-sizing-1-ref.xul
+== stack-sizing-2.xul stack-sizing-2-ref.xul
+
 # Tests for rendering SVG images in a XUL <treecell>:
 # XXXdholbert: These are marked as "random" right now, since they might not
 # render the images they trying to test in time for the reftest snapshot, per
 # bug 1218954.
 skip == treecell-image-svg-1a.xul treecell-image-svg-1-ref.xul # bug 1218954
 skip == treecell-image-svg-1b.xul treecell-image-svg-1-ref.xul # bug 1218954
 
 == treechildren-padding-percent-1.xul treechildren-padding-percent-1-ref.xul
rename from layout/reftests/bugs/346189-1-ref.xul
rename to layout/reftests/xul/stack-sizing-1-ref.xul
rename from layout/reftests/bugs/346189-1.xul
rename to layout/reftests/xul/stack-sizing-1.xul
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/stack-sizing-2-ref.xul
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+  width="400"
+  height="600"
+  align="start">
+
+<box style="background: red; width: 20px; height: 20px;"/>
+
+<box style="background: green; width: 10px; height: 20px;"/>
+
+<box style="background: blue; width: 20px; height: 10px;"/>
+
+<box style="background: yellow; width: 10px; height: 10px;"/>
+
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/stack-sizing-2.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+  width="400"
+  height="600"
+  align="start">
+
+<!-- stretch-to-fit: both width and height are considered. -->
+<stack style="background: red;">
+  <box style="width: 10px; height: 10px;"/>
+  <box style="-moz-stack-sizing: stretch-to-fit; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore-horizontal: width is not considered, height is considered. -->
+<stack style="background: green;">
+  <box style="width: 10px; height: 10px;"/>
+  <box style="-moz-stack-sizing: ignore-horizontal; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore-vertical: width is considered, height is not considered. -->
+<stack style="background: blue;">
+  <box style="width: 10px; height: 10px;"/>
+  <box style="-moz-stack-sizing: ignore-vertical; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore: neither width or height are considered. -->
+<stack style="background: yellow;">
+  <box style="width: 10px; height: 10px;"/>
+  <box style="-moz-stack-sizing: ignore; width: 20px; height: 20px;"/>
+</stack>
+
+</window>
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -307,16 +307,18 @@ CSS_KEY(historical-forms, historical_for
 CSS_KEY(historical-ligatures, historical_ligatures)
 CSS_KEY(horizontal, horizontal)
 CSS_KEY(horizontal-tb, horizontal_tb)
 CSS_KEY(hue, hue)
 CSS_KEY(hue-rotate, hue_rotate)
 CSS_KEY(hz, hz)
 CSS_KEY(icon, icon)
 CSS_KEY(ignore, ignore)
+CSS_KEY(ignore-horizontal, ignore_horizontal)
+CSS_KEY(ignore-vertical, ignore_vertical)
 CSS_KEY(in, in)
 CSS_KEY(interlace, interlace)
 CSS_KEY(inactive, inactive)
 CSS_KEY(inactiveborder, inactiveborder)
 CSS_KEY(inactivecaption, inactivecaption)
 CSS_KEY(inactivecaptiontext, inactivecaptiontext)
 CSS_KEY(infinite, infinite)
 CSS_KEY(infobackground, infobackground)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1961,18 +1961,20 @@ const KTableEntry nsCSSProps::kScrollBeh
 const KTableEntry nsCSSProps::kScrollSnapTypeKTable[] = {
   { eCSSKeyword_none,      NS_STYLE_SCROLL_SNAP_TYPE_NONE },
   { eCSSKeyword_mandatory, NS_STYLE_SCROLL_SNAP_TYPE_MANDATORY },
   { eCSSKeyword_proximity, NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY },
   { eCSSKeyword_UNKNOWN,   -1 }
 };
 
 const KTableEntry nsCSSProps::kStackSizingKTable[] = {
-  { eCSSKeyword_ignore, NS_STYLE_STACK_SIZING_IGNORE },
-  { eCSSKeyword_stretch_to_fit, NS_STYLE_STACK_SIZING_STRETCH_TO_FIT },
+  { eCSSKeyword_ignore, StyleStackSizing::Ignore },
+  { eCSSKeyword_stretch_to_fit, StyleStackSizing::StretchToFit },
+  { eCSSKeyword_ignore_horizontal, StyleStackSizing::IgnoreHorizontal },
+  { eCSSKeyword_ignore_vertical, StyleStackSizing::IgnoreVertical },
   { eCSSKeyword_UNKNOWN, -1 }
 };
 
 const KTableEntry nsCSSProps::kTableLayoutKTable[] = {
   { eCSSKeyword_auto, NS_STYLE_TABLE_LAYOUT_AUTO },
   { eCSSKeyword_fixed, NS_STYLE_TABLE_LAYOUT_FIXED },
   { eCSSKeyword_UNKNOWN, -1 }
 };
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1078,18 +1078,18 @@ nsComputedDOMStyle::DoGetBottom()
 {
   return GetOffsetWidthFor(eSideBottom);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetStackSizing()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  val->SetIdent(StyleXUL()->mStretchStack ? eCSSKeyword_stretch_to_fit :
-                eCSSKeyword_ignore);
+  val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mStackSizing,
+                                               nsCSSProps::kStackSizingKTable));
   return val.forget();
 }
 
 void
 nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
                                    nscolor aColor)
 {
   nsROCSSPrimitiveValue *red   = new nsROCSSPrimitiveValue;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1496,16 +1496,17 @@ struct SetEnumValueHelper
   DEFINE_ENUM_CLASS_SETTER(StyleBoxOrient, Horizontal, Vertical)
   DEFINE_ENUM_CLASS_SETTER(StyleBoxPack, Start, Justify)
   DEFINE_ENUM_CLASS_SETTER(StyleBoxSizing, Content, Border)
   DEFINE_ENUM_CLASS_SETTER(StyleClear, None, Both)
   DEFINE_ENUM_CLASS_SETTER(StyleFillRule, Nonzero, Evenodd)
   DEFINE_ENUM_CLASS_SETTER(StyleFloat, None, InlineEnd)
   DEFINE_ENUM_CLASS_SETTER(StyleFloatEdge, ContentBox, MarginBox)
   DEFINE_ENUM_CLASS_SETTER(StyleHyphens, None, Auto)
+  DEFINE_ENUM_CLASS_SETTER(StyleStackSizing, Ignore, IgnoreVertical)
   DEFINE_ENUM_CLASS_SETTER(StyleTextJustify, None, InterCharacter)
   DEFINE_ENUM_CLASS_SETTER(StyleUserFocus, None, SelectMenu)
   DEFINE_ENUM_CLASS_SETTER(StyleUserSelect, None, MozText)
   DEFINE_ENUM_CLASS_SETTER(StyleUserInput, None, Auto)
   DEFINE_ENUM_CLASS_SETTER(StyleUserModify, ReadOnly, WriteOnly)
   DEFINE_ENUM_CLASS_SETTER(StyleWindowDragging, Default, NoDrag)
   DEFINE_ENUM_CLASS_SETTER(StyleOrient, Inline, Vertical)
   DEFINE_ENUM_CLASS_SETTER(StyleGeometryBox, BorderBox, ViewBox)
@@ -9078,27 +9079,21 @@ nsRuleNode::ComputeXULData(void* aStartS
            StyleBoxPack::Start);
 
   // box-ordinal-group: integer, inherit, initial
   SetValue(*aRuleData->ValueForBoxOrdinalGroup(),
            xul->mBoxOrdinal, conditions,
            SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
            parentXUL->mBoxOrdinal, 1);
 
-  const nsCSSValue* stackSizingValue = aRuleData->ValueForStackSizing();
-  if (eCSSUnit_Inherit == stackSizingValue->GetUnit()) {
-    conditions.SetUncacheable();
-    xul->mStretchStack = parentXUL->mStretchStack;
-  } else if (eCSSUnit_Initial == stackSizingValue->GetUnit() ||
-             eCSSUnit_Unset == stackSizingValue->GetUnit()) {
-    xul->mStretchStack = true;
-  } else if (eCSSUnit_Enumerated == stackSizingValue->GetUnit()) {
-    xul->mStretchStack = stackSizingValue->GetIntValue() ==
-      NS_STYLE_STACK_SIZING_STRETCH_TO_FIT;
-  }
+  SetValue(*aRuleData->ValueForStackSizing(),
+           xul->mStackSizing, conditions,
+           SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
+           parentXUL->mStackSizing,
+           StyleStackSizing::StretchToFit);
 
   COMPUTE_END_RESET(XUL, xul)
 }
 
 const void*
 nsRuleNode::ComputeColumnData(void* aStartStruct,
                               const nsRuleData* aRuleData,
                               nsStyleContext* aContext,
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -153,16 +153,24 @@ enum class StyleShapeRadius : uint8_t {
 // Shape source type
 enum class StyleShapeSourceType : uint8_t {
   None,
   URL,
   Shape,
   Box,
 };
 
+// -moz-stack-sizing
+enum class StyleStackSizing : uint8_t {
+  Ignore,
+  StretchToFit,
+  IgnoreHorizontal,
+  IgnoreVertical,
+};
+
 // text-justify
 enum class StyleTextJustify : uint8_t {
   None,
   Auto,
   InterWord,
   InterCharacter,
 };
 
@@ -217,20 +225,16 @@ enum class StyleWindowDragging : uint8_t
 // orient
 enum class StyleOrient : uint8_t {
   Inline,
   Block,
   Horizontal,
   Vertical,
 };
 
-// stack-sizing
-#define NS_STYLE_STACK_SIZING_IGNORE         0
-#define NS_STYLE_STACK_SIZING_STRETCH_TO_FIT 1
-
 // Azimuth - See nsStyleAural
 #define NS_STYLE_AZIMUTH_LEFT_SIDE        0x00
 #define NS_STYLE_AZIMUTH_FAR_LEFT         0x01
 #define NS_STYLE_AZIMUTH_LEFT             0x02
 #define NS_STYLE_AZIMUTH_CENTER_LEFT      0x03
 #define NS_STYLE_AZIMUTH_CENTER           0x04
 #define NS_STYLE_AZIMUTH_CENTER_RIGHT     0x05
 #define NS_STYLE_AZIMUTH_RIGHT            0x06
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -737,48 +737,48 @@ nsStyleList::sNoneQuotes;
 //
 nsStyleXUL::nsStyleXUL(const nsPresContext* aContext)
   : mBoxFlex(0.0f)
   , mBoxOrdinal(1)
   , mBoxAlign(StyleBoxAlign::Stretch)
   , mBoxDirection(StyleBoxDirection::Normal)
   , mBoxOrient(StyleBoxOrient::Horizontal)
   , mBoxPack(StyleBoxPack::Start)
-  , mStretchStack(true)
+  , mStackSizing(StyleStackSizing::StretchToFit)
 {
   MOZ_COUNT_CTOR(nsStyleXUL);
 }
 
 nsStyleXUL::~nsStyleXUL()
 {
   MOZ_COUNT_DTOR(nsStyleXUL);
 }
 
 nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
   : mBoxFlex(aSource.mBoxFlex)
   , mBoxOrdinal(aSource.mBoxOrdinal)
   , mBoxAlign(aSource.mBoxAlign)
   , mBoxDirection(aSource.mBoxDirection)
   , mBoxOrient(aSource.mBoxOrient)
   , mBoxPack(aSource.mBoxPack)
-  , mStretchStack(aSource.mStretchStack)
+  , mStackSizing(aSource.mStackSizing)
 {
   MOZ_COUNT_CTOR(nsStyleXUL);
 }
 
 nsChangeHint
 nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
 {
   if (mBoxAlign == aNewData.mBoxAlign &&
       mBoxDirection == aNewData.mBoxDirection &&
       mBoxFlex == aNewData.mBoxFlex &&
       mBoxOrient == aNewData.mBoxOrient &&
       mBoxPack == aNewData.mBoxPack &&
       mBoxOrdinal == aNewData.mBoxOrdinal &&
-      mStretchStack == aNewData.mStretchStack) {
+      mStackSizing == aNewData.mStackSizing) {
     return nsChangeHint(0);
   }
   if (mBoxOrdinal != aNewData.mBoxOrdinal) {
     return nsChangeHint_ReconstructFrame;
   }
   return NS_STYLE_HINT_REFLOW;
 }
 
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3319,17 +3319,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
 
   float         mBoxFlex;               // [reset] see nsStyleConsts.h
   uint32_t      mBoxOrdinal;            // [reset] see nsStyleConsts.h
   mozilla::StyleBoxAlign mBoxAlign;         // [reset]
   mozilla::StyleBoxDirection mBoxDirection; // [reset]
   mozilla::StyleBoxOrient mBoxOrient;       // [reset]
   mozilla::StyleBoxPack mBoxPack;           // [reset]
-  bool          mStretchStack;          // [reset] see nsStyleConsts.h
+  mozilla::StyleStackSizing mStackSizing;   // [reset] see nsStyleConsts.h
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
 {
   explicit nsStyleColumn(const nsPresContext* aContext);
   nsStyleColumn(const nsStyleColumn& aSource);
   ~nsStyleColumn();
   void FinishStyle(nsPresContext* aPresContext) {}
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1914,17 +1914,17 @@ var gCSSProperties = {
     other_values: [ "both", "horizontal", "vertical" ],
     invalid_values: []
   },
   "-moz-stack-sizing": {
     domProp: "MozStackSizing",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "stretch-to-fit" ],
-    other_values: [ "ignore" ],
+    other_values: [ "ignore", "ignore-horizontal", "ignore-vertical" ],
     invalid_values: []
   },
   "-moz-tab-size": {
     domProp: "MozTabSize",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "8" ],
     other_values: [ "0", "2.5", "3", "99", "12000", "0px", "1em", "calc(1px + 1em)", "calc(1px - 2px)", "calc(1 + 1)", "calc(-2.5)" ],
--- a/layout/xul/nsStackLayout.cpp
+++ b/layout/xul/nsStackLayout.cpp
@@ -60,25 +60,34 @@ nsStackLayout::nsStackLayout()
 
 nsSize
 nsStackLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
 {
   nsSize prefSize (0, 0);
 
   nsIFrame* child = nsBox::GetChildXULBox(aBox);
   while (child) {
-    if (child->StyleXUL()->mStretchStack) {
+    auto stackSizing = child->StyleXUL()->mStackSizing;
+    if (stackSizing != StyleStackSizing::Ignore) {
       nsSize pref = child->GetXULPrefSize(aState);
 
       AddMargin(child, pref);
       nsMargin offset;
       GetOffset(child, offset);
       pref.width += offset.LeftRight();
       pref.height += offset.TopBottom();
-      AddLargestSize(prefSize, pref);
+
+      if (pref.width > prefSize.width &&
+          stackSizing != StyleStackSizing::IgnoreHorizontal) {
+        prefSize.width = pref.width;
+      }
+      if (pref.height > prefSize.height &&
+          stackSizing != StyleStackSizing::IgnoreVertical) {
+        prefSize.height = pref.height;
+      }
     }
 
     child = nsBox::GetNextXULBox(child);
   }
 
   AddBorderAndPadding(aBox, prefSize);
 
   return prefSize;
@@ -86,25 +95,34 @@ nsStackLayout::GetXULPrefSize(nsIFrame* 
 
 nsSize
 nsStackLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
 {
   nsSize minSize (0, 0);
 
   nsIFrame* child = nsBox::GetChildXULBox(aBox);
   while (child) {
-    if (child->StyleXUL()->mStretchStack) {
+    auto stackSizing = child->StyleXUL()->mStackSizing;
+    if (stackSizing != StyleStackSizing::Ignore) {
       nsSize min = child->GetXULMinSize(aState);
 
       AddMargin(child, min);
       nsMargin offset;
       GetOffset(child, offset);
       min.width += offset.LeftRight();
       min.height += offset.TopBottom();
-      AddLargestSize(minSize, min);
+
+      if (min.width > minSize.width &&
+          stackSizing != StyleStackSizing::IgnoreHorizontal) {
+        minSize.width = min.width;
+      }
+      if (min.height > minSize.height &&
+          stackSizing != StyleStackSizing::IgnoreVertical) {
+        minSize.height = min.height;
+      }
     }
 
     child = nsBox::GetNextXULBox(child);
   }
 
   AddBorderAndPadding(aBox, minSize);
 
   return minSize;
@@ -112,28 +130,37 @@ nsStackLayout::GetXULMinSize(nsIFrame* a
 
 nsSize
 nsStackLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
 {
   nsSize maxSize (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
 
   nsIFrame* child = nsBox::GetChildXULBox(aBox);
   while (child) {
-    if (child->StyleXUL()->mStretchStack) {
+    auto stackSizing = child->StyleXUL()->mStackSizing;
+    if (stackSizing != StyleStackSizing::Ignore) {
       nsSize min = child->GetXULMinSize(aState);
       nsSize max = child->GetXULMaxSize(aState);
 
       max = nsBox::BoundsCheckMinMax(min, max);
 
       AddMargin(child, max);
       nsMargin offset;
       GetOffset(child, offset);
       max.width += offset.LeftRight();
       max.height += offset.TopBottom();
-      AddSmallestSize(maxSize, max);
+
+      if (max.width < maxSize.width &&
+          stackSizing != StyleStackSizing::IgnoreHorizontal) {
+        maxSize.width = max.width;
+      }
+      if (max.height < maxSize.height &&
+          stackSizing != StyleStackSizing::IgnoreVertical) {
+        maxSize.height = max.height;
+      }
     }
 
     child = nsBox::GetNextXULBox(child);
   }
 
   AddBorderAndPadding(aBox, maxSize);
 
   return maxSize;
@@ -340,34 +367,37 @@ nsStackLayout::XULLayout(nsIFrame* aBox,
 
           // Flow the child.
           child->XULLayout(aState);
 
           // Get the child's new rect.
           childRect = child->GetRect();
           childRect.Inflate(margin);
 
-          if (child->StyleXUL()->mStretchStack) {
+          auto stackSizing = child->StyleXUL()->mStackSizing;
+          if (stackSizing != StyleStackSizing::Ignore) {
             // Did the child push back on us and get bigger?
-            if (offset.LeftRight() + childRect.width > clientRect.width) {
+            if (offset.LeftRight() + childRect.width > clientRect.width &&
+                stackSizing != StyleStackSizing::IgnoreHorizontal) {
               clientRect.width = childRect.width + offset.LeftRight();
               grow = true;
             }
 
-            if (offset.TopBottom() + childRect.height > clientRect.height) {
+            if (offset.TopBottom() + childRect.height > clientRect.height &&
+                stackSizing != StyleStackSizing::IgnoreVertical) {
               clientRect.height = childRect.height + offset.TopBottom();
               grow = true;
             }
           }
        }
 
        child = nsBox::GetNextXULBox(child);
      }
    } while (grow);
-   
+
    // if some HTML inside us got bigger we need to force ourselves to
    // get bigger
    nsRect bounds(aBox->GetRect());
    nsMargin bp;
    aBox->GetXULBorderAndPadding(bp);
    clientRect.Inflate(bp);
 
    if (clientRect.width > bounds.width || clientRect.height > bounds.height)
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -4205,26 +4205,17 @@ clip-path
     pub fn set__moz_force_broken_image_icon(&mut self, v: longhands::_moz_force_broken_image_icon::computed_value::T) {
         self.gecko.mForceBrokenImageIcon = v.0 as u8;
     }
 
     ${impl_simple_copy("_moz_force_broken_image_icon", "mForceBrokenImageIcon")}
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="XUL"
-                  skip_longhands="-moz-stack-sizing -moz-box-ordinal-group">
-
-    #[allow(non_snake_case)]
-    pub fn set__moz_stack_sizing(&mut self, v: longhands::_moz_stack_sizing::computed_value::T) {
-        use properties::longhands::_moz_stack_sizing::computed_value::T;
-        self.gecko.mStretchStack = v == T::stretch_to_fit;
-    }
-
-    ${impl_simple_copy('_moz_stack_sizing', 'mStretchStack')}
-
+                  skip_longhands="-moz-box-ordinal-group">
     #[allow(non_snake_case)]
     pub fn set__moz_box_ordinal_group(&mut self, v: i32) {
         self.gecko.mBoxOrdinal = v as u32;
     }
 
     ${impl_simple_copy("_moz_box_ordinal_group", "mBoxOrdinal")}
 </%self:impl_trait>
 
--- a/servo/components/style/properties/longhand/xul.mako.rs
+++ b/servo/components/style/properties/longhand/xul.mako.rs
@@ -39,19 +39,19 @@
 
 ${helpers.single_keyword("-moz-box-pack", "start center end justify",
                          products="gecko", gecko_ffi_name="mBoxPack",
                          gecko_enum_prefix="StyleBoxPack",
                          animation_value_type="none",
                          alias="-webkit-box-pack",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-pack)")}
 
-${helpers.single_keyword("-moz-stack-sizing", "stretch-to-fit ignore",
-                         products="gecko", gecko_ffi_name="mStretchStack",
-                         gecko_constant_prefix="NS_STYLE_STACK_SIZING",
+${helpers.single_keyword("-moz-stack-sizing", "stretch-to-fit ignore ignore-horizontal ignore-vertical",
+                         products="gecko", gecko_ffi_name="mStackSizing",
+                         gecko_enum_prefix="StyleStackSizing",
                          animation_value_type="none",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-stack-sizing)")}
 
 ${helpers.predefined_type("-moz-box-ordinal-group", "Integer", "0",
                           parse_method="parse_non_negative",
                           products="gecko",
                           alias="-webkit-box-ordinal-group",
                           gecko_ffi_name="mBoxOrdinal",