Add support for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill for width, min-width, and max-width. b=311415 r+sr=bzbarsky
authordbaron@dbaron.org
Thu, 03 May 2007 16:11:00 -0700
changeset 1068 d300d6434463bc88dcda787de75e4a22eb125f2a
parent 1067 81fe716892c91488e9a860c7b5d314970ff187bf
child 1069 34dcf8e94bdbe8a1162f376fd0bdc32773651b6b
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs311415
milestone1.9a5pre
Add support for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill for width, min-width, and max-width. b=311415 r+sr=bzbarsky
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/base/nsStyleConsts.h
layout/forms/nsGfxCheckboxControlFrame.cpp
layout/forms/nsGfxRadioControlFrame.cpp
layout/generic/nsAbsoluteContainingBlock.cpp
layout/generic/nsFrame.cpp
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsHTMLReflowState.cpp
layout/generic/nsHTMLReflowState.h
layout/generic/nsImageFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsSpacerFrame.cpp
layout/reftests/box-properties/box-sizing-1-ref.html
layout/reftests/box-properties/box-sizing-1.html
layout/reftests/box-properties/box-sizing-2-ref.html
layout/reftests/box-properties/box-sizing-2.html
layout/reftests/box-properties/box-sizing-3.html
layout/reftests/box-properties/box-sizing-4-ref.html
layout/reftests/box-properties/box-sizing-4.html
layout/reftests/box-properties/minmax-width-special-values-block-intrinsic-ref.html
layout/reftests/box-properties/minmax-width-special-values-block-intrinsic.html
layout/reftests/box-properties/reftest.list
layout/reftests/box-properties/width-special-values-block-intrinsic-ref.html
layout/reftests/box-properties/width-special-values-block-intrinsic.html
layout/reftests/box-properties/width-special-values-block-ref.html
layout/reftests/box-properties/width-special-values-block.html
layout/reftests/box-properties/width-special-values-cell-auto-ref.html
layout/reftests/box-properties/width-special-values-cell-auto.html
layout/reftests/box-properties/width-special-values-cell-fixed-ref.html
layout/reftests/box-properties/width-special-values-cell-fixed.html
layout/reftests/box-properties/width-special-values-float-intrinsic.html
layout/reftests/box-properties/width-special-values-float.html
layout/reftests/box-properties/width-special-values-image-block-ref.html
layout/reftests/box-properties/width-special-values-image-block.html
layout/reftests/box-properties/width-special-values-image-ref.html
layout/reftests/box-properties/width-special-values-image.html
layout/style/nsCSSKeywordList.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
layout/tables/BasicTableLayoutStrategy.cpp
layout/tables/FixedTableLayoutStrategy.cpp
layout/tables/nsTableFrame.cpp
layout/xul/base/src/grid/nsGridRowLeafFrame.cpp
layout/xul/base/src/nsBox.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1248,16 +1248,61 @@ static PRBool GetAbsoluteCoord(const nsS
     aRenderingContext->SetTextRunRTL(PR_FALSE);
     aRenderingContext->GetWidth('M', fontWidth);
     aResult = aStyle.GetIntValue() * fontWidth;
     return PR_TRUE;
   }
   return PR_FALSE;
 }
 
+// Handles only -moz-intrinsic and -moz-min-intrinsic, and
+// -moz-shrink-wrap for min-width and max-width, since the others
+// (-moz-shrink-wrap for width, and -moz-fill) have no effect on
+// intrinsic widths.
+enum eWidthProperty { PROP_WIDTH, PROP_MAX_WIDTH, PROP_MIN_WIDTH };
+static PRBool
+GetIntrinsicCoord(const nsStyleCoord& aStyle,
+                  nsIRenderingContext* aRenderingContext,
+                  nsIFrame* aFrame,
+                  eWidthProperty aProperty,
+                  nscoord& aResult)
+{
+  NS_PRECONDITION(aProperty == PROP_WIDTH || aProperty == PROP_MAX_WIDTH ||
+                  aProperty == PROP_MIN_WIDTH, "unexpected property");
+  if (aStyle.GetUnit() != eStyleUnit_Enumerated)
+    return PR_FALSE;
+  PRInt32 val = aStyle.GetIntValue();
+  NS_ASSERTION(val == NS_STYLE_WIDTH_INTRINSIC ||
+               val == NS_STYLE_WIDTH_MIN_INTRINSIC ||
+               val == NS_STYLE_WIDTH_SHRINK_WRAP ||
+               val == NS_STYLE_WIDTH_FILL,
+               "unexpected enumerated value for width property");
+  if (val == NS_STYLE_WIDTH_FILL)
+    return PR_FALSE;
+  if (val == NS_STYLE_WIDTH_SHRINK_WRAP) {
+    if (aProperty == PROP_WIDTH)
+      return PR_FALSE; // handle like 'width: auto'
+    if (aProperty == PROP_MAX_WIDTH)
+      // constrain large 'width' values down to -moz-intrinsic
+      val = NS_STYLE_WIDTH_INTRINSIC;
+    else
+      // constrain small 'width' or 'max-width' values up to -moz-min-intrinsic
+      val = NS_STYLE_WIDTH_MIN_INTRINSIC;
+  }
+
+  NS_ASSERTION(val == NS_STYLE_WIDTH_INTRINSIC ||
+               val == NS_STYLE_WIDTH_MIN_INTRINSIC,
+               "should have reduced everything remaining to one of these");
+  if (val == NS_STYLE_WIDTH_INTRINSIC)
+    aResult = aFrame->GetPrefWidth(aRenderingContext);
+  else
+    aResult = aFrame->GetMinWidth(aRenderingContext);
+  return PR_TRUE;
+}
+
 #undef  DEBUG_INTRINSIC_WIDTH
 
 #ifdef DEBUG_INTRINSIC_WIDTH
 static PRInt32 gNoiseIndent = 0;
 #endif
 
 /* static */ nscoord
 nsLayoutUtils::IntrinsicForContainer(nsIRenderingContext *aRenderingContext,
@@ -1273,17 +1318,17 @@ nsLayoutUtils::IntrinsicForContainer(nsI
   printf(" %s intrinsic width for container:\n",
          aType == MIN_WIDTH ? "min" : "pref");
 #endif
 
   nsIFrame::IntrinsicWidthOffsetData offsets =
     aFrame->IntrinsicWidthOffsets(aRenderingContext);
 
   const nsStylePosition *stylePos = aFrame->GetStylePosition();
-  const PRUint8 boxSizing = stylePos->mBoxSizing;
+  PRUint8 boxSizing = stylePos->mBoxSizing;
   const nsStyleCoord &styleWidth = stylePos->mWidth;
   const nsStyleCoord &styleMinWidth = stylePos->mMinWidth;
   const nsStyleCoord &styleMaxWidth = stylePos->mMaxWidth;
 
   // We build up two values starting with the content box, and then
   // adding padding, border and margin.  The result is normally
   // |result|.  Then, when we handle 'width', 'min-width', and
   // 'max-width', we use the results we've been building in |min| as a
@@ -1293,20 +1338,28 @@ nsLayoutUtils::IntrinsicForContainer(nsI
   //     a content width less than zero
   //   * that we prevent tables from becoming smaller than their
   //     intrinsic minimum width
   nscoord result = 0, min = 0;
 
   // If we have a specified width (or a specified 'min-width' greater
   // than the specified 'max-width', which works out to the same thing),
   // don't even bother getting the frame's intrinsic width.
-  if (styleWidth.GetUnit() != eStyleUnit_Coord &&
-      (styleMinWidth.GetUnit() != eStyleUnit_Coord ||
-       styleMaxWidth.GetUnit() != eStyleUnit_Coord ||
-       styleMaxWidth.GetCoordValue() > styleMinWidth.GetCoordValue())) {
+  if (styleWidth.GetUnit() == eStyleUnit_Enumerated &&
+      (styleWidth.GetIntValue() == NS_STYLE_WIDTH_INTRINSIC ||
+       styleWidth.GetIntValue() == NS_STYLE_WIDTH_MIN_INTRINSIC)) {
+    // -moz-shrink-wrap and -moz-fill enumerated widths compute intrinsic
+    // widths just like auto.
+    // For -moz-intrinsic and -moz-min-intrinsic, we handle them like
+    // specified widths, but ignore -moz-box-sizing.
+    boxSizing = NS_STYLE_BOX_SIZING_CONTENT;
+  } else if (styleWidth.GetUnit() != eStyleUnit_Coord &&
+             (styleMinWidth.GetUnit() != eStyleUnit_Coord ||
+              styleMaxWidth.GetUnit() != eStyleUnit_Coord ||
+              styleMaxWidth.GetCoordValue() > styleMinWidth.GetCoordValue())) {
 #ifdef DEBUG_INTRINSIC_WIDTH
     ++gNoiseIndent;
 #endif
     if (aType == MIN_WIDTH)
       result = aFrame->GetMinWidth(aRenderingContext);
     else
       result = aFrame->GetPrefWidth(aRenderingContext);
 #ifdef DEBUG_INTRINSIC_WIDTH
@@ -1359,37 +1412,43 @@ nsLayoutUtils::IntrinsicForContainer(nsI
   coordOutsideWidth += offsets.hMargin;
   pctOutsideWidth += offsets.hPctMargin;
 
   min += coordOutsideWidth;
   result += coordOutsideWidth;
   pctTotal += pctOutsideWidth;
 
   nscoord w;
-  if (GetAbsoluteCoord(styleWidth, aRenderingContext, aFrame, w)) {
+  if (GetAbsoluteCoord(styleWidth, aRenderingContext, aFrame, w) ||
+      GetIntrinsicCoord(styleWidth, aRenderingContext, aFrame,
+                        PROP_WIDTH, w)) {
     result = AddPercents(aType, w + coordOutsideWidth, pctOutsideWidth);
   }
   else if (aType == MIN_WIDTH && eStyleUnit_Percent == styleWidth.GetUnit() &&
            aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
     // A percentage width on replaced elements means they can shrink to 0.
     result = 0; // let |min| handle padding/border/margin
   }
   else {
     result = AddPercents(aType, result, pctTotal);
   }
 
   nscoord maxw;
-  if (GetAbsoluteCoord(styleMaxWidth, aRenderingContext, aFrame, maxw)) {
+  if (GetAbsoluteCoord(styleMaxWidth, aRenderingContext, aFrame, maxw) ||
+      GetIntrinsicCoord(styleMaxWidth, aRenderingContext, aFrame,
+                        PROP_MAX_WIDTH, maxw)) {
     maxw = AddPercents(aType, maxw + coordOutsideWidth, pctOutsideWidth);
     if (result > maxw)
       result = maxw;
   }
 
   nscoord minw;
-  if (GetAbsoluteCoord(styleMinWidth, aRenderingContext, aFrame, minw)) {
+  if (GetAbsoluteCoord(styleMinWidth, aRenderingContext, aFrame, minw) ||
+      GetIntrinsicCoord(styleMinWidth, aRenderingContext, aFrame,
+                        PROP_MIN_WIDTH, minw)) {
     minw = AddPercents(aType, minw + coordOutsideWidth, pctOutsideWidth);
     if (result < minw)
       result = minw;
   }
 
   min = AddPercents(aType, min, pctTotal);
   if (result < min)
     result = min;
@@ -1437,20 +1496,82 @@ nsLayoutUtils::ComputeWidthDependentValu
 
   nscoord result;
   if (GetAbsoluteCoord(aCoord, aRenderingContext, aFrame, result)) {
     return result;
   }
   if (eStyleUnit_Percent == aCoord.GetUnit()) {
     return NSToCoordFloor(aContainingBlockWidth * aCoord.GetPercentValue());
   }
+  NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_Null ||
+               aCoord.GetUnit() == eStyleUnit_Auto,
+               "unexpected width value");
   return 0;
 }
 
 /* static */ nscoord
+nsLayoutUtils::ComputeWidthValue(
+                 nsIRenderingContext* aRenderingContext,
+                 nsIFrame*            aFrame,
+                 nscoord              aContainingBlockWidth,
+                 nscoord              aContentEdgeToBoxSizing,
+                 nscoord              aBoxSizingToMarginEdge,
+                 const nsStyleCoord&  aCoord)
+{
+  NS_PRECONDITION(aFrame, "non-null frame expected");
+  NS_PRECONDITION(aRenderingContext, "non-null rendering context expected");
+  NS_PRECONDITION(aContainingBlockWidth != NS_UNCONSTRAINEDSIZE,
+                  "unconstrained widths no longer supported");
+  NS_PRECONDITION(aContainingBlockWidth >= 0,
+                  "width less than zero");
+
+  nscoord result;
+  if (GetAbsoluteCoord(aCoord, aRenderingContext, aFrame, result)) {
+    NS_ASSERTION(result >= 0, "width less than zero");
+    result -= aContentEdgeToBoxSizing;
+  } else if (eStyleUnit_Percent == aCoord.GetUnit()) {
+    NS_ASSERTION(aCoord.GetPercentValue() >= 0.0f, "width less than zero");
+    result = NSToCoordFloor(aContainingBlockWidth * aCoord.GetPercentValue()) -
+             aContentEdgeToBoxSizing;
+  } else if (eStyleUnit_Enumerated == aCoord.GetUnit()) {
+    PRInt32 val = aCoord.GetIntValue();
+    switch (val) {
+      case NS_STYLE_WIDTH_INTRINSIC:
+        result = aFrame->GetPrefWidth(aRenderingContext);
+        NS_ASSERTION(result >= 0, "width less than zero");
+        break;
+      case NS_STYLE_WIDTH_MIN_INTRINSIC:
+        result = aFrame->GetMinWidth(aRenderingContext);
+        NS_ASSERTION(result >= 0, "width less than zero");
+        break;
+      case NS_STYLE_WIDTH_SHRINK_WRAP:
+        {
+          nscoord pref = aFrame->GetPrefWidth(aRenderingContext),
+                   min = aFrame->GetMinWidth(aRenderingContext),
+                  fill = aContainingBlockWidth -
+                         (aBoxSizingToMarginEdge + aContentEdgeToBoxSizing);
+          result = PR_MAX(min, PR_MIN(pref, fill));
+          NS_ASSERTION(result >= 0, "width less than zero");
+        }
+        break;
+      case NS_STYLE_WIDTH_FILL:
+        result = aContainingBlockWidth -
+                 (aBoxSizingToMarginEdge + aContentEdgeToBoxSizing);
+    }
+  } else {
+    NS_NOTREACHED("unexpected width value");
+    result = 0;
+  }
+  if (result < 0)
+    result = 0;
+  return result;
+}
+
+
+/* static */ nscoord
 nsLayoutUtils::ComputeHeightDependentValue(
                  nsIRenderingContext* aRenderingContext,
                  nsIFrame*            aFrame,
                  nscoord              aContainingBlockHeight,
                  const nsStyleCoord&  aCoord)
 {
   NS_PRECONDITION(aFrame, "non-null frame expected");
   NS_PRECONDITION(aRenderingContext, "non-null rendering context expected");
@@ -1469,16 +1590,19 @@ nsLayoutUtils::ComputeHeightDependentVal
     // according to CSS2.1 they should be passing 'auto'.
     NS_PRECONDITION(NS_AUTOHEIGHT != aContainingBlockHeight,
                     "unexpected 'containing block height'");
 
     if (NS_AUTOHEIGHT != aContainingBlockHeight) {
       return NSToCoordFloor(aContainingBlockHeight * aCoord.GetPercentValue());
     }
   }
+  NS_ASSERTION(aCoord.GetUnit() == eStyleUnit_Null ||
+               aCoord.GetUnit() == eStyleUnit_Auto,
+               "unexpected height value");
   return 0;
 }
 
 inline PRBool
 IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
 {
   nsStyleUnit unit = aCoord.GetUnit();
   return unit == eStyleUnit_Auto ||  // only for 'height'
@@ -1488,64 +1612,63 @@ IsAutoHeight(const nsStyleCoord &aCoord,
 }
 
 #define MULDIV(a,b,c) (nscoord(PRInt64(a) * PRInt64(b) / PRInt64(c)))
 
 /* static */ nsSize
 nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
                    nsIRenderingContext* aRenderingContext,
                    nsIFrame* aFrame, nsSize aIntrinsicSize, nsSize aCBSize,
-                   nsSize aBorder, nsSize aPadding)
+                   nsSize aMargin, nsSize aBorder, nsSize aPadding)
 {
   const nsStylePosition *stylePos = aFrame->GetStylePosition();
   // Handle intrinsic sizes and their interaction with
   // {min-,max-,}{width,height} according to the rules in
   // http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
 
   // Note: throughout the following section of the function, I avoid
   // a * (b / c) because of its reduced accuracy relative to a * b / c
   // or (a * b) / c (which are equivalent).
 
-  PRBool isAutoWidth = stylePos->mWidth.GetUnit() == eStyleUnit_Auto;
-  PRBool isAutoHeight = IsAutoHeight(stylePos->mHeight, aCBSize.height);
+  const PRBool isAutoWidth = stylePos->mWidth.GetUnit() == eStyleUnit_Auto;
+  const PRBool isAutoHeight = IsAutoHeight(stylePos->mHeight, aCBSize.height);
 
   nsSize boxSizingAdjust(0,0);
   switch (stylePos->mBoxSizing) {
     case NS_STYLE_BOX_SIZING_BORDER:
       boxSizingAdjust += aBorder;
       // fall through
     case NS_STYLE_BOX_SIZING_PADDING:
       boxSizingAdjust += aPadding;
   }
+  nscoord boxSizingToMarginEdgeWidth =
+    aMargin.width + aBorder.width + aPadding.width - boxSizingAdjust.width;
 
   nscoord width, minWidth, maxWidth, height, minHeight, maxHeight;
 
   if (!isAutoWidth) {
-    width = nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext,
-              aFrame, aCBSize.width, stylePos->mWidth) -
-            boxSizingAdjust.width;
-    if (width < 0)
-      width = 0;
+    width = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
+              aFrame, aCBSize.width, boxSizingAdjust.width,
+              boxSizingToMarginEdgeWidth, stylePos->mWidth);
+    NS_ASSERTION(width >= 0, "negative result from ComputeWidthValue");
   }
 
   if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_Null) {
-    maxWidth = nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext,
-                 aFrame, aCBSize.width, stylePos->mMaxWidth) -
-               boxSizingAdjust.width;
-    if (maxWidth < 0)
-      maxWidth = 0;
+    maxWidth = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
+                 aFrame, aCBSize.width, boxSizingAdjust.width,
+                 boxSizingToMarginEdgeWidth, stylePos->mMaxWidth);
+    NS_ASSERTION(maxWidth >= 0, "negative result from ComputeWidthValue");
   } else {
     maxWidth = nscoord_MAX;
   }
 
-  minWidth = nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext,
-               aFrame, aCBSize.width, stylePos->mMinWidth) -
-             boxSizingAdjust.width;
-  if (minWidth < 0)
-    minWidth = 0;
+  minWidth = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
+               aFrame, aCBSize.width, boxSizingAdjust.width,
+               boxSizingToMarginEdgeWidth, stylePos->mMinWidth);
+  NS_ASSERTION(minWidth >= 0, "negative result from ComputeWidthValue");
 
   if (!isAutoHeight) {
     height = nsLayoutUtils::ComputeHeightDependentValue(aRenderingContext,
                aFrame, aCBSize.height, stylePos->mHeight) -
              boxSizingAdjust.height;
     if (height < 0)
       height = 0;
   }
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -522,32 +522,65 @@ public:
    * 'min-width', and 'max-width' properties, and its padding, border,
    * and margin.
    */
   enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH };
   static nscoord IntrinsicForContainer(nsIRenderingContext* aRenderingContext,
                                        nsIFrame* aFrame,
                                        IntrinsicWidthType aType);
 
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block width.
+   */
   static nscoord ComputeWidthDependentValue(
                    nsIRenderingContext* aRenderingContext,
                    nsIFrame*            aFrame,
                    nscoord              aContainingBlockWidth,
                    const nsStyleCoord&  aCoord);
 
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block width, and enumerated values are for width,
+   * min-width, or max-width.  Returns the content-box width value based
+   * on aContentEdgeToBoxSizing and aBoxSizingToMarginEdge (which are
+   * also used for the enumerated values for width.  This function does
+   * not handle 'auto'.  It ensures that the result is nonnegative.
+   *
+   * @param aRenderingContext Rendering context for font measurement/metrics.
+   * @param aFrame Frame whose (min-/max-/)width is being computed
+   * @param aContainingBlockWidth Width of aFrame's containing block.
+   * @param aContentEdgeToBoxSizing The sum of any left/right padding and
+   *          border that goes inside the rect chosen by -moz-box-sizing.
+   * @param aBoxSizingToMarginEdge The sum of any left/right padding, border,
+   *          and margin that goes outside the rect chosen by -moz-box-sizing.
+   * @param aCoord The width value to compute.
+   */
+  static nscoord ComputeWidthValue(
+                   nsIRenderingContext* aRenderingContext,
+                   nsIFrame*            aFrame,
+                   nscoord              aContainingBlockWidth,
+                   nscoord              aContentEdgeToBoxSizing,
+                   nscoord              aBoxSizingToMarginEdge,
+                   const nsStyleCoord&  aCoord);
+
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block height.
+   */
   static nscoord ComputeHeightDependentValue(
                    nsIRenderingContext* aRenderingContext,
                    nsIFrame*            aFrame,
                    nscoord              aContainingBlockHeight,
                    const nsStyleCoord&  aCoord);
 
   static nsSize ComputeSizeWithIntrinsicDimensions(
                     nsIRenderingContext* aRenderingContext,
                     nsIFrame* aFrame, nsSize aIntrinsicSize, nsSize aCBSize,
-                    nsSize aBorder, nsSize aPadding);
+                    nsSize aMargin, nsSize aBorder, nsSize aPadding);
 
   // Implement nsIFrame::GetPrefWidth in terms of nsIFrame::AddInlinePrefWidth
   static nscoord PrefWidthFromInline(nsIFrame* aFrame,
                                      nsIRenderingContext* aRenderingContext);
 
   // Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth
   static nscoord MinWidthFromInline(nsIFrame* aFrame,
                                     nsIRenderingContext* aRenderingContext);
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -423,16 +423,22 @@
 #define NS_STYLE_FONT_DESKTOP										10
 #define NS_STYLE_FONT_INFO											11
 #define NS_STYLE_FONT_DIALOG										12
 #define NS_STYLE_FONT_BUTTON										13
 #define NS_STYLE_FONT_PULL_DOWN_MENU						14
 #define NS_STYLE_FONT_LIST											15
 #define NS_STYLE_FONT_FIELD											16
 
+// See nsStylePosition::mWidth, mMinWidth, mMaxWidth
+#define NS_STYLE_WIDTH_INTRINSIC                0
+#define NS_STYLE_WIDTH_MIN_INTRINSIC            1
+#define NS_STYLE_WIDTH_SHRINK_WRAP              2
+#define NS_STYLE_WIDTH_FILL                     3
+
 // See nsStylePosition.mPosition
 #define NS_STYLE_POSITION_STATIC                0
 #define NS_STYLE_POSITION_RELATIVE              1
 #define NS_STYLE_POSITION_ABSOLUTE              2
 #define NS_STYLE_POSITION_FIXED                 3
 
 // See nsStylePosition.mClip
 #define NS_STYLE_CLIP_AUTO                      0x00
--- a/layout/forms/nsGfxCheckboxControlFrame.cpp
+++ b/layout/forms/nsGfxCheckboxControlFrame.cpp
@@ -252,16 +252,19 @@ nsGfxCheckboxControlFrame::BuildDisplayL
 void
 nsGfxCheckboxControlFrame::PaintCheckBoxFromStyle(
     nsIRenderingContext& aRenderingContext, nsPoint aPt, const nsRect& aDirtyRect) {
   const nsStylePadding* myPadding = mCheckButtonFaceStyle->GetStylePadding();
   const nsStylePosition* myPosition = mCheckButtonFaceStyle->GetStylePosition();
   const nsStyleBorder* myBorder = mCheckButtonFaceStyle->GetStyleBorder();
   const nsStyleBackground* myBackground = mCheckButtonFaceStyle->GetStyleBackground();
 
+  NS_ASSERTION(myPosition->mWidth.GetUnit() == eStyleUnit_Coord &&
+               myPosition->mHeight.GetUnit() == eStyleUnit_Coord,
+               "styles for :-moz-checkbox are incorrect or author-accessible");
   nscoord width = myPosition->mWidth.GetCoordValue();
   nscoord height = myPosition->mHeight.GetCoordValue();
   // Position the button centered within the control's rectangle.
   nscoord x = (mRect.width - width) / 2;
   nscoord y = (mRect.height - height) / 2;
   nsRect rect(aPt.x + x, aPt.y + y, width, height);
 
   nsCSSRendering::PaintBackgroundWithSC(PresContext(), aRenderingContext,
--- a/layout/forms/nsGfxRadioControlFrame.cpp
+++ b/layout/forms/nsGfxRadioControlFrame.cpp
@@ -130,16 +130,19 @@ nsGfxRadioControlFrame::PaintRadioButton
 {
   const nsStyleBorder* myBorder = mRadioButtonFaceStyle->GetStyleBorder();
   // Paint the button for the radio button using CSS background rendering code
   const nsStyleBackground* myColor = mRadioButtonFaceStyle->GetStyleBackground();
   const nsStyleColor* color = mRadioButtonFaceStyle->GetStyleColor();
   const nsStylePadding* myPadding = mRadioButtonFaceStyle->GetStylePadding();
   const nsStylePosition* myPosition = mRadioButtonFaceStyle->GetStylePosition();
 
+  NS_ASSERTION(myPosition->mWidth.GetUnit() == eStyleUnit_Coord &&
+               myPosition->mHeight.GetUnit() == eStyleUnit_Coord,
+               "styles for :-moz-radio are incorrect or author-accessible");
   nscoord width = myPosition->mWidth.GetCoordValue();
   nscoord height = myPosition->mHeight.GetCoordValue();
   // Position the button centered within the radio control's rectangle.
   nscoord x = (mRect.width - width) / 2;
   nscoord y = (mRect.height - height) / 2;
   nsRect rect = nsRect(x, y, width, height) + aPt;
 
   // So we will use PaintBackgroundWithSC to paint the dot, 
--- a/layout/generic/nsAbsoluteContainingBlock.cpp
+++ b/layout/generic/nsAbsoluteContainingBlock.cpp
@@ -179,24 +179,38 @@ nsAbsoluteContainingBlock::Reflow(nsIFra
                           aContainingBlockHeight, kidFrame, kidStatus);
 
     }
     AddFrameToChildBounds(kidFrame, aChildBounds);
   }
   return NS_OK;
 }
 
-static PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
+static inline PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
+  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
+}
+static inline PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
   return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
 }
-static PRBool IsFixedMarginSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
+static inline PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
+  return aUnit == eStyleUnit_Null || aUnit == eStyleUnit_Coord;
 }
-static PRBool IsFixedMaxSize(nsStyleUnit aUnit) {
-  return aUnit == eStyleUnit_Null || aUnit == eStyleUnit_Coord;
+
+static inline PRBool IsFixedWidth(const nsStyleCoord& aCoord)
+{
+  return aCoord.GetUnit() == eStyleUnit_Coord ||
+         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
+          aCoord.GetIntValue() == NS_STYLE_WIDTH_INTRINSIC ||
+          aCoord.GetIntValue() == NS_STYLE_WIDTH_MIN_INTRINSIC);
+}
+
+static inline PRBool IsFixedMaxWidth(const nsStyleCoord& aCoord)
+{
+  return aCoord.GetUnit() == eStyleUnit_Null ||
+         IsFixedWidth(aCoord);
 }
 
 PRBool
 nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
                                                    PRBool aCBWidthChanged,
                                                    PRBool aCBHeightChanged)
 {
   const nsStylePosition* pos = f->GetStylePosition();
@@ -224,19 +238,20 @@ nsAbsoluteContainingBlock::FrameDependsO
   const nsStylePadding* padding = f->GetStylePadding();
   const nsStyleMargin* margin = f->GetStyleMargin();
   if (aCBWidthChanged) {
     // See if f's width might have changed.
     // If border-left, border-right, padding-left, padding-right,
     // width, min-width, and max-width are all lengths, 'none', or enumerated,
     // then our frame width does not depend on the parent width.
     // Note that borders never depend on the parent width
-    if (pos->mWidth.GetUnit() != eStyleUnit_Coord ||
-        pos->mMinWidth.GetUnit() != eStyleUnit_Coord ||
-        !IsFixedMaxSize(pos->mMaxWidth.GetUnit()) ||
+    // XXX All of the enumerated values except -moz-fill are ok too.
+    if (!IsFixedWidth(pos->mWidth) ||
+        !IsFixedWidth(pos->mMinWidth) ||
+        !IsFixedMaxWidth(pos->mMaxWidth) ||
         !IsFixedPaddingSize(padding->mPadding.GetLeftUnit()) ||
         !IsFixedPaddingSize(padding->mPadding.GetRightUnit())) {
       return PR_TRUE;
     }
 
     // See if f's position might have changed. If we're RTL then the
     // rules are slightly different. We'll assume percentage or auto
     // margins will always induce a dependency on the size
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3138,39 +3138,41 @@ nsFrame::ComputeSize(nsIRenderingContext
 
   switch (stylePos->mBoxSizing) {
     case NS_STYLE_BOX_SIZING_BORDER:
       boxSizingAdjust += aBorder;
       // fall through
     case NS_STYLE_BOX_SIZING_PADDING:
       boxSizingAdjust += aPadding;
   }
+  nscoord boxSizingToMarginEdgeWidth =
+    aMargin.width + aBorder.width + aPadding.width - boxSizingAdjust.width;
 
   // Compute width
 
   if (stylePos->mWidth.GetUnit() != eStyleUnit_Auto) {
     result.width =
-      nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext, this,
-        aCBSize.width, stylePos->mWidth) -
-      boxSizingAdjust.width;
+      nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
+        aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
+        stylePos->mWidth);
   }
 
   if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_Null) {
     nscoord maxWidth =
-      nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext, this,
-        aCBSize.width, stylePos->mMaxWidth) -
-      boxSizingAdjust.width;
+      nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
+        aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
+        stylePos->mMaxWidth);
     if (maxWidth < result.width)
       result.width = maxWidth;
   }
 
   nscoord minWidth =
-    nsLayoutUtils::ComputeWidthDependentValue(aRenderingContext, this,
-      aCBSize.width, stylePos->mMinWidth) -
-    boxSizingAdjust.width;
+    nsLayoutUtils::ComputeWidthValue(aRenderingContext, this,
+      aCBSize.width, boxSizingAdjust.width, boxSizingToMarginEdgeWidth,
+      stylePos->mMinWidth);
   if (minWidth > result.width)
     result.width = minWidth;
 
   // Compute height
 
   if (!IsAutoHeight(stylePos->mHeight, aCBSize.height)) {
     result.height =
       nsLayoutUtils::ComputeHeightDependentValue(aRenderingContext, this,
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -106,17 +106,17 @@ nsHTMLCanvasFrame::ComputeSize(nsIRender
                                PRBool aShrinkWrap)
 {
   nsSize size = GetCanvasSize();
   nsSize canvasSize(nsPresContext::CSSPixelsToAppUnits(size.width),
                     nsPresContext::CSSPixelsToAppUnits(size.height));
 
   return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
                             aRenderingContext, this, canvasSize,
-                            aCBSize, aBorder, aPadding);
+                            aCBSize, aMargin, aBorder, aPadding);
 }
 
 NS_IMETHODIMP
 nsHTMLCanvasFrame::Reflow(nsPresContext*           aPresContext,
                           nsHTMLReflowMetrics&     aMetrics,
                           const nsHTMLReflowState& aReflowState,
                           nsReflowStatus&          aStatus)
 {
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -185,16 +185,50 @@ nsCSSOffsetState::ComputeWidthDependentV
                                              const nsStyleCoord& aCoord,
                                              nscoord& aResult)
 {
   aResult = nsLayoutUtils::ComputeWidthDependentValue(rendContext, frame,
                                                       aContainingBlockWidth,
                                                       aCoord);
 }
 
+inline nscoord
+nsCSSOffsetState::ComputeWidthValue(nscoord aContainingBlockWidth,
+                                    nscoord aContentEdgeToBoxSizing,
+                                    nscoord aBoxSizingToMarginEdge,
+                                    const nsStyleCoord& aCoord)
+{
+  return nsLayoutUtils::ComputeWidthValue(rendContext, frame,
+                                          aContainingBlockWidth,
+                                          aContentEdgeToBoxSizing,
+                                          aBoxSizingToMarginEdge,
+                                          aCoord);
+}
+
+nscoord
+nsCSSOffsetState::ComputeWidthValue(nscoord aContainingBlockWidth,
+                                    PRUint8 aBoxSizing,
+                                    const nsStyleCoord& aCoord)
+{
+  nscoord inside = 0, outside = mComputedBorderPadding.LeftRight() +
+                                mComputedMargin.LeftRight();
+  switch (aBoxSizing) {
+    case NS_STYLE_BOX_SIZING_BORDER:
+      inside = mComputedBorderPadding.LeftRight();
+      break;
+    case NS_STYLE_BOX_SIZING_PADDING:
+      inside = mComputedPadding.LeftRight();
+      break;
+  }
+  outside -= inside;
+
+  return ComputeWidthValue(aContainingBlockWidth, inside,
+                           outside, aCoord);
+}
+
 inline void
 nsCSSOffsetState::ComputeHeightDependentValue(nscoord aContainingBlockHeight,
                                               const nsStyleCoord& aCoord,
                                               nscoord& aResult)
 {
   aResult = nsLayoutUtils::ComputeHeightDependentValue(rendContext, frame,
                                                        aContainingBlockHeight,
                                                        aCoord);
@@ -628,18 +662,26 @@ GetIntrinsicSizeFor(nsIFrame* aFrame, ns
     nsImageFrame* imageFrame = (nsImageFrame*)aFrame;
 
     imageFrame->GetIntrinsicImageSize(aIntrinsicSize);
     result = (aIntrinsicSize != nsSize(0, 0));
   }
   return result;
 }
 
-nscoord
-nsHTMLReflowState::CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth)
+/**
+ * aInsideBoxSizing returns the part of the horizontal padding, border,
+ * and margin that goes inside the edge given by -moz-box-sizing;
+ * aOutsideBoxSizing returns the rest.
+ */
+void
+nsHTMLReflowState::CalculateHorizBorderPaddingMargin(
+                       nscoord aContainingBlockWidth,
+                       nscoord* aInsideBoxSizing,
+                       nscoord* aOutsideBoxSizing)
 {
   const nsMargin& border = mStyleBorder->GetBorder();
   nsMargin padding, margin;
 
   // See if the style system can provide us the padding directly
   if (!mStylePadding->GetPadding(padding)) {
     nsStyleCoord left, right;
 
@@ -670,18 +712,30 @@ nsHTMLReflowState::CalculateHorizBorderP
       margin.right = 0;  // just ignore
     } else {
       ComputeWidthDependentValue(aContainingBlockWidth,
                                  mStyleMargin->mMargin.GetRight(right),
                                  margin.right);
     }
   }
 
-  return padding.left + padding.right + border.left + border.right +
-         margin.left + margin.right;
+  nscoord outside =
+    padding.LeftRight() + border.LeftRight() + margin.LeftRight();
+  nscoord inside = 0;
+  switch (mStylePosition->mBoxSizing) {
+    case NS_STYLE_BOX_SIZING_BORDER:
+      inside += border.LeftRight();
+      // fall through
+    case NS_STYLE_BOX_SIZING_PADDING:
+      inside += padding.LeftRight();
+  }
+  outside -= inside;
+  *aInsideBoxSizing = inside;
+  *aOutsideBoxSizing = outside;
+  return;
 }
 
 /**
  * Returns PR_TRUE iff a pre-order traversal of the normal child
  * frames rooted at aFrame finds no non-empty frame before aDescendant.
  */
 static PRBool AreAllEarlierInFlowFramesEmpty(nsIFrame* aFrame,
   nsIFrame* aDescendant, PRBool* aFound) {
@@ -716,62 +770,64 @@ nsHTMLReflowState::CalculateHypothetical
                                             nsHypotheticalBox& aHypotheticalBox)
 {
   NS_ASSERTION(mStyleDisplay->mOriginalDisplay != NS_STYLE_DISPLAY_NONE,
                "mOriginalDisplay has not been properly initialized");
   
   // If it's a replaced element and it has a 'auto' value for 'width', see if we
   // can get the intrinsic size. This will allow us to exactly determine both the
   // left and right edges
-  nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit();
+  PRBool isAutoWidth = mStylePosition->mWidth.GetUnit() == eStyleUnit_Auto;
   nsSize      intrinsicSize;
   PRBool      knowIntrinsicSize = PR_FALSE;
-  if (NS_FRAME_IS_REPLACED(mFrameType) && (eStyleUnit_Auto == widthUnit)) {
+  if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoWidth) {
     // See if we can get the intrinsic size of the element
     knowIntrinsicSize = GetIntrinsicSizeFor(frame, intrinsicSize);
   }
 
   // See if we can calculate what the box width would have been if the
   // element had been in the flow
   nscoord boxWidth;
   PRBool  knowBoxWidth = PR_FALSE;
   if ((NS_STYLE_DISPLAY_INLINE == mStyleDisplay->mOriginalDisplay) &&
       !NS_FRAME_IS_REPLACED(mFrameType)) {
     // For non-replaced inline-level elements the 'width' property doesn't apply,
     // so we don't know what the width would have been without reflowing it
 
   } else {
     // It's either a replaced inline-level element or a block-level element
-    nscoord horizBorderPaddingMargin;
 
     // Determine the total amount of horizontal border/padding/margin that
     // the element would have had if it had been in the flow. Note that we
     // ignore any 'auto' and 'inherit' values
-    horizBorderPaddingMargin = CalculateHorizBorderPaddingMargin(aBlockContentWidth);
+    nscoord insideBoxSizing, outsideBoxSizing;
+    CalculateHorizBorderPaddingMargin(aBlockContentWidth,
+                                      &insideBoxSizing, &outsideBoxSizing);
 
-    if (NS_FRAME_IS_REPLACED(mFrameType) && (eStyleUnit_Auto == widthUnit)) {
+    if (NS_FRAME_IS_REPLACED(mFrameType) && isAutoWidth) {
       // It's a replaced element with an 'auto' width so the box width is
       // its intrinsic size plus any border/padding/margin
       if (knowIntrinsicSize) {
-        boxWidth = intrinsicSize.width + horizBorderPaddingMargin;
+        boxWidth = intrinsicSize.width + outsideBoxSizing + insideBoxSizing;
         knowBoxWidth = PR_TRUE;
       }
 
-    } else if (eStyleUnit_Auto == widthUnit) {
+    } else if (isAutoWidth) {
       // The box width is the containing block width
       boxWidth = aBlockContentWidth;
       knowBoxWidth = PR_TRUE;
     
     } else {
       // We need to compute it. It's important we do this, because if it's
       // percentage based this computed value may be different from the comnputed
       // value calculated using the absolute containing block width
-      ComputeWidthDependentValue(aBlockContentWidth, mStylePosition->mWidth,
-                                 boxWidth);
-      boxWidth += horizBorderPaddingMargin;
+      boxWidth = ComputeWidthValue(aBlockContentWidth,
+                                   insideBoxSizing, outsideBoxSizing,
+                                   mStylePosition->mWidth) + 
+                 insideBoxSizing + outsideBoxSizing;
       knowBoxWidth = PR_TRUE;
     }
   }
   
   // Get the 'direction' of the block
   const nsStyleVisibility* blockVis = aContainingBlock->GetStyleVisibility();
 
   // Get the placeholder x-offset and y-offset in the coordinate
@@ -1606,18 +1662,19 @@ nsHTMLReflowState::InitConstraints(nsPre
           // cells have border and padding
           mComputedWidth -= mComputedBorderPadding.left +
             mComputedBorderPadding.right;
         }
       
       } else {
         NS_ASSERTION(widthUnit == mStylePosition->mWidth.GetUnit(),
                      "unexpected width unit change");
-        ComputeWidthDependentValue(aContainingBlockWidth,
-                                   mStylePosition->mWidth, mComputedWidth);
+        mComputedWidth = ComputeWidthValue(aContainingBlockWidth,
+                                           mStylePosition->mBoxSizing,
+                                           mStylePosition->mWidth);
       }
 
       // Calculate the computed height
       if ((NS_STYLE_DISPLAY_TABLE_COLUMN == mStyleDisplay->mDisplay) ||
           (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == mStyleDisplay->mDisplay)) {
         // 'height' property doesn't apply to table columns and column groups
         heightUnit = eStyleUnit_Auto;
       }
@@ -2053,25 +2110,27 @@ nsHTMLReflowState::ApplyMinMaxConstraint
   }
 }
 
 void
 nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth,
                                        nscoord aContainingBlockHeight,
                                        const nsHTMLReflowState* aContainingBlockRS)
 {
-  ComputeWidthDependentValue(aContainingBlockWidth, mStylePosition->mMinWidth,
-                             mComputedMinWidth);
+  mComputedMinWidth = ComputeWidthValue(aContainingBlockWidth,
+                                        mStylePosition->mBoxSizing,
+                                        mStylePosition->mMinWidth);
 
   if (eStyleUnit_Null == mStylePosition->mMaxWidth.GetUnit()) {
     // Specified value of 'none'
     mComputedMaxWidth = NS_UNCONSTRAINEDSIZE;  // no limit
   } else {
-    ComputeWidthDependentValue(aContainingBlockWidth, mStylePosition->mMaxWidth,
-                               mComputedMaxWidth);
+    mComputedMaxWidth = ComputeWidthValue(aContainingBlockWidth,
+                                          mStylePosition->mBoxSizing,
+                                          mStylePosition->mMaxWidth);
   }
 
   // If the computed value of 'min-width' is greater than the value of
   // 'max-width', 'max-width' is set to the value of 'min-width'
   if (mComputedMinWidth > mComputedMaxWidth) {
     mComputedMaxWidth = mComputedMinWidth;
   }
 
--- a/layout/generic/nsHTMLReflowState.h
+++ b/layout/generic/nsHTMLReflowState.h
@@ -183,19 +183,46 @@ private:
   // fills in the mComputedMargin member
   void ComputeMargin(nscoord aContainingBlockWidth);
   
   // Computes padding values from the specified padding style information, and
   // fills in the mComputedPadding member
   void ComputePadding(nscoord aContainingBlockWidth);
 
 protected:
+
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block width.
+   */
+  // XXX Make aResult a return value
   inline void ComputeWidthDependentValue(nscoord aContainingBlockWidth,
                                          const nsStyleCoord& aCoord,
                                          nscoord& aResult);
+
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block width, and enumerated values are for width,
+   * min-width, or max-width.  Does not handle auto widths.
+   */
+  inline nscoord ComputeWidthValue(nscoord aContainingBlockWidth,
+                                   nscoord aContentEdgeToBoxSizing,
+                                   nscoord aBoxSizingToMarginEdge,
+                                   const nsStyleCoord& aCoord);
+  // same as previous, but using mComputedBorderPadding, mComputedPadding,
+  // and mComputedMargin
+  nscoord ComputeWidthValue(nscoord aContainingBlockWidth,
+                            PRUint8 aBoxSizing,
+                            const nsStyleCoord& aCoord);
+
+  /*
+   * Convert nsStyleCoord to nscoord when percentages depend on the
+   * containing block height.
+   */
+  // XXX Make aResult a return value
   inline void ComputeHeightDependentValue(nscoord aContainingBlockHeight,
                                           const nsStyleCoord& aCoord,
                                           nscoord& aResult);
 };
 
 /**
  * State passed to a frame during reflow or intrinsic size calculation.
  *
@@ -457,14 +484,16 @@ protected:
 
   // Calculates the computed values for the 'min-Width', 'max-Width',
   // 'min-Height', and 'max-Height' properties, and stores them in the assorted
   // data members
   void ComputeMinMaxValues(nscoord                  aContainingBlockWidth,
                            nscoord                  aContainingBlockHeight,
                            const nsHTMLReflowState* aContainingBlockRS);
 
-  nscoord CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth);
+  void CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth,
+                                         nscoord* aInsideBoxSizing,
+                                         nscoord* aOutsideBoxSizing);
 
 };
 
 #endif /* nsHTMLReflowState_h___ */
 
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -720,17 +720,17 @@ nsImageFrame::ComputeSize(nsIRenderingCo
                           PRBool aShrinkWrap)
 {
   nsPresContext *presContext = PresContext();
   EnsureIntrinsicSize(presContext);
 
   return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
                             aRenderingContext, this,
                             mIntrinsicSize,
-                            aCBSize, aBorder, aPadding);
+                            aCBSize, aMargin, aBorder, aPadding);
 }
 
 nsRect 
 nsImageFrame::GetInnerArea() const
 {
   return GetContentRect() - GetPosition();
 }
 
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -696,16 +696,26 @@ HasPercentageUnitSide(const nsStyleSides
 {
   NS_FOR_CSS_SIDES(side) {
     if (eStyleUnit_Percent == aSides.GetUnit(side))
       return PR_TRUE;
   }
   return PR_FALSE;
 }
 
+inline PRBool
+WidthDependsOnContainer(const nsStyleCoord& aCoord)
+{
+  return aCoord.GetUnit() == eStyleUnit_Percent ||
+         (aCoord.GetUnit() == eStyleUnit_Enumerated &&
+          (aCoord.GetIntValue() == NS_STYLE_WIDTH_FILL ||
+          (aCoord.GetIntValue() == NS_STYLE_WIDTH_SHRINK_WRAP)));
+
+}
+
 static PRBool
 IsPercentageAware(const nsIFrame* aFrame)
 {
   NS_ASSERTION(aFrame, "null frame is not allowed");
 
   nsIAtom *fType = aFrame->GetType();
   if (fType == nsGkAtoms::textFrame) {
     // None of these things can ever be true for text frames.
@@ -727,19 +737,19 @@ IsPercentageAware(const nsIFrame* aFrame
   if (HasPercentageUnitSide(padding->mPadding)) {
     return PR_TRUE;
   }
 
   // Note that borders can't be aware of percentages
 
   const nsStylePosition* pos = aFrame->GetStylePosition();
 
-  if (eStyleUnit_Percent == pos->mWidth.GetUnit() ||
-      eStyleUnit_Percent == pos->mMaxWidth.GetUnit() ||
-      eStyleUnit_Percent == pos->mMinWidth.GetUnit() ||
+  if (WidthDependsOnContainer(pos->mWidth) ||
+      WidthDependsOnContainer(pos->mMaxWidth) ||
+      WidthDependsOnContainer(pos->mMinWidth) ||
       eStyleUnit_Percent == pos->mOffset.GetRightUnit() ||
       eStyleUnit_Percent == pos->mOffset.GetLeftUnit()) {
     return PR_TRUE;
   }
 
   if (eStyleUnit_Auto == pos->mWidth.GetUnit()) {
     // We need to check for frames that shrink-wrap when they're auto
     // width.
--- a/layout/generic/nsSpacerFrame.cpp
+++ b/layout/generic/nsSpacerFrame.cpp
@@ -104,16 +104,17 @@ SpacerFrame::Reflow(nsPresContext*      
                     nsHTMLReflowMetrics&     aMetrics,
                     const nsHTMLReflowState& aReflowState,
                     nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("SpacerFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
   aStatus = NS_FRAME_COMPLETE;
 
+  // XXX Bug 379654 Should use containing block size!
   nsSize percentBase(aReflowState.availableWidth, aReflowState.availableHeight);
   if (percentBase.width == NS_UNCONSTRAINEDSIZE)
     percentBase.width = 0;
   if (percentBase.height == NS_UNCONSTRAINEDSIZE)
     percentBase.height = 0;
 
   if (GetType() == TYPE_LINE)
     aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_COMPLETE);
@@ -126,16 +127,22 @@ SpacerFrame::Reflow(nsPresContext*      
 
 void
 SpacerFrame::GetDesiredSize(nsHTMLReflowMetrics& aMetrics, nsSize aPercentBase)
 {
   // By default, we have no area
   aMetrics.width = 0;
   aMetrics.height = 0;
 
+  // XXX Bug 379654 This code doesn't handle some value types for width
+  // and height, doesn't handle min/max-width/height, doesn't handle
+  // border and padding, doesn't handle 'ch' units, doesn't handle the
+  // enumerated values on width, etc.  But it probably doesn't much
+  // matter.
+
   const nsStylePosition* position = GetStylePosition();
 
   PRUint8 type = GetType();
   switch (type) {
   case TYPE_WORD:
     break;
 
   case TYPE_LINE:
@@ -159,17 +166,17 @@ SpacerFrame::GetDesiredSize(nsHTMLReflow
     // height
     unit = position->mHeight.GetUnit();
     if (eStyleUnit_Coord == unit) {
       aMetrics.height = position->mHeight.GetCoordValue();
     }
     else if (eStyleUnit_Percent == unit) 
     {
       float factor = position->mHeight.GetPercentValue();
-      aMetrics.width = NSToCoordRound(factor * aPercentBase.height);
+      aMetrics.height = NSToCoordRound(factor * aPercentBase.height);
     }
     break;
   }
 
   if (aMetrics.width || aMetrics.height) {
     // Make sure that the other dimension is non-zero
     if (!aMetrics.width) aMetrics.width = 1;
     if (!aMetrics.height) aMetrics.height = 1;
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-1-ref.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td > div { width: 100px; }
+
+    td > div > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 1px;
+
+      float: left;
+      clear: left;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent"><div>
+
+<!-- -moz-box-sizing: content-box -->
+<div style="width: 37px">A B</div>
+<div style="width: auto">A B</div>
+<div style="width: auto">A<br>B</div>
+<div style="width: auto">A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60px">A B</div>
+
+</div></td>
+
+<td id="bspadding"><div>
+<!-- -moz-box-sizing: padding-box -->
+<div style="width: 37px">A B</div>
+<div style="width: auto">A B</div>
+<div style="width: auto">A<br>B</div>
+<div style="width: auto">A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 38px">A B</div>
+<div style="width: 48px">A B</div>
+
+</div></td>
+
+<td id="bsborder"><div>
+<!-- -moz-box-sizing: border-box -->
+<div style="width: 37px">A B</div>
+<div style="width: auto">A B</div>
+<div style="width: auto">A<br>B</div>
+<div style="width: auto">A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 20px">A B</div>
+<div style="width: 30px">A B</div>
+
+</div></td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-1.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td > div { width: 100px; }
+
+    td#bscontent > div > div { -moz-box-sizing: content-box; }
+    td#bspadding > div > div { -moz-box-sizing: padding-box; }
+    td#bsborder > div > div { -moz-box-sizing: border-box; }
+
+    td > div > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 1px;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent"><div>
+
+<!-- -moz-box-sizing: content-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bspadding"><div>
+<!-- -moz-box-sizing: padding-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bsborder"><div>
+<!-- -moz-box-sizing: border-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-2-ref.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td td > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent">
+
+<!-- -moz-box-sizing: content-box -->
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A<br>B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div style="width: 150px">A B</div></td></tr></table>
+
+</td>
+
+<td id="bspadding">
+<!-- -moz-box-sizing: padding-box -->
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A<br>B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div style="width: 138px">A B</div></td></tr></table>
+
+</td>
+
+<td id="bsborder">
+<!-- -moz-box-sizing: border-box -->
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A<br>B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div>A B</div></td></tr></table>
+<table><tr><td><div style="width: 120px">A B</div></td></tr></table>
+
+</td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-2.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td#bscontent td > div { -moz-box-sizing: content-box; }
+    td#bspadding td > div { -moz-box-sizing: padding-box; }
+    td#bsborder td > div { -moz-box-sizing: border-box; }
+
+    td td > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent">
+
+<!-- -moz-box-sizing: content-box -->
+<table><tr><td><div style="width: auto">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-min-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-shrink-wrap">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-fill">A B</div></td></tr></table>
+<table><tr><td><div style="width: 150px">A B</div></td></tr></table>
+
+</td>
+
+<td id="bspadding">
+<!-- -moz-box-sizing: padding-box -->
+<table><tr><td><div style="width: auto">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-min-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-shrink-wrap">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-fill">A B</div></td></tr></table>
+<table><tr><td><div style="width: 150px">A B</div></td></tr></table>
+
+</td>
+
+<td id="bsborder">
+<!-- -moz-box-sizing: border-box -->
+<table><tr><td><div style="width: auto">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-min-intrinsic">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-shrink-wrap">A B</div></td></tr></table>
+<table><tr><td><div style="width: -moz-fill">A B</div></td></tr></table>
+<table><tr><td><div style="width: 150px">A B</div></td></tr></table>
+
+</td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-3.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td > div { width: 100px; }
+
+    td#bscontent > div > div { -moz-box-sizing: content-box; }
+    td#bspadding > div > div { -moz-box-sizing: padding-box; }
+    td#bsborder > div > div { -moz-box-sizing: border-box; }
+
+    td > div > div {
+      margin-left: 1%;
+      border-left: 2px solid;
+      padding-left: 4%;
+      padding-right: 8%;
+      border-right: 16px solid;
+      margin-right: 32%;
+
+      background: yellow;
+      margin-bottom: 1px;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent"><div>
+
+<!-- -moz-box-sizing: content-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bspadding"><div>
+<!-- -moz-box-sizing: padding-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bsborder"><div>
+<!-- -moz-box-sizing: border-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-4-ref.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0 100px; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td > div { width: 100px; }
+
+    td > div > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 10px;
+      float: right;
+      clear: right;
+      text-align: right;
+      height: 40px;
+      right: 0;
+    }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent"><div>
+
+<!-- -moz-box-sizing: content-box -->
+<div>A B</div>
+<div>A B</div>
+<div>A<br>B</div>
+<div>A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60px">A B</div>
+
+</div></td>
+
+<td id="bspadding"><div>
+<!-- -moz-box-sizing: padding-box -->
+<div>A B</div>
+<div>A B</div>
+<div>A<br>B</div>
+<div>A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 38px">A B</div>
+<div style="width: 48px">A B</div>
+
+</div></td>
+
+<td id="bsborder"><div>
+<!-- -moz-box-sizing: border-box -->
+<div>A B</div>
+<div>A B</div>
+<div>A<br>B</div>
+<div>A B</div>
+<div style="width: 37px">A B</div>
+<div style="width: 20px">A B</div>
+<div style="width: 30px">A B</div>
+
+</div></td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/box-sizing-4.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>test of -moz-box-sizing</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+    table { border-spacing: 0; margin: 0 100px; }
+    td { border: 1px solid; padding: 1px solid; }
+
+    td > div { width: 100px; height: 350px;
+               direction: rtl; position: relative; }
+
+    td#bscontent > div > div { -moz-box-sizing: content-box; }
+    td#bspadding > div > div { -moz-box-sizing: padding-box; }
+    td#bsborder > div > div { -moz-box-sizing: border-box; }
+
+    td > div > div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 10px;
+      position: absolute;
+      height: 40px;
+      right: 0;
+    }
+
+    td > div > div { top: 0px; }
+    td > div > div + div { top: 50px; }
+    td > div > div + div + div { top: 100px; }
+    td > div > div + div + div + div { top: 150px; }
+    td > div > div + div + div  + div + div { top: 200px; }
+    td > div > div + div + div + div  + div + div { top: 250px; }
+    td > div > div + div + div  + div + div  + div + div { top: 300px; }
+
+  </style>
+</head>
+<body>
+
+<table><tr>
+
+<td id="bscontent"><div>
+
+<!-- -moz-box-sizing: content-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bspadding"><div>
+<!-- -moz-box-sizing: padding-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+<td id="bsborder"><div>
+<!-- -moz-box-sizing: border-box -->
+<div style="width: auto">A B</div>
+<div style="width: -moz-intrinsic">A B</div>
+<div style="width: -moz-min-intrinsic">A B</div>
+<div style="width: -moz-shrink-wrap">A B</div>
+<div style="width: -moz-fill">A B</div>
+<div style="width: 50px">A B</div>
+<div style="width: 60%">A B</div>
+
+</div></td>
+
+</tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/minmax-width-special-values-block-intrinsic-ref.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>intrinsic min-widths and max-widths for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+</head>
+<body>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 1px;">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 1px;">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 500px">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 500px">AA B</div>
+</td></tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/minmax-width-special-values-block-intrinsic.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>intrinsic min-widths and max-widths for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+</head>
+<body>
+
+<table border><tr><td>
+  <div style="width: 1px; min-width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 1px; min-width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 1px; min-width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 1px; min-width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 1px; min-width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 1px; min-width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 1px; min-width: -moz-fill">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 1px; min-width: -moz-fill">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 500px; max-width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 500px; max-width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 500px; max-width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 500px; max-width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 500px; max-width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 500px; max-width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: 500px; max-width: -moz-fill">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: 500px; max-width: -moz-fill">AA B</div>
+</td></tr></table>
+
+</body>
+</html>
--- a/layout/reftests/box-properties/reftest.list
+++ b/layout/reftests/box-properties/reftest.list
@@ -1,7 +1,20 @@
 == column-gap-percent-1.html column-gap-percent-1-ref.html
 != column-gap-percent-2.html column-gap-percent-2-ref.html
 == outline-radius-percent-1.html outline-radius-percent-1-ref.html
 == min-width-1.html min-width-1-ref.html
 == min-height-1.html min-height-1-ref.html
 == max-width-1.html max-width-1-ref.html
 == max-height-1.html max-height-1-ref.html
+== width-special-values-block.html width-special-values-block-ref.html
+== width-special-values-float.html width-special-values-block-ref.html
+== width-special-values-image-block.html width-special-values-image-block-ref.html
+== width-special-values-image.html width-special-values-image-ref.html
+== width-special-values-block-intrinsic.html width-special-values-block-intrinsic-ref.html
+== width-special-values-float-intrinsic.html width-special-values-block-intrinsic-ref.html
+== minmax-width-special-values-block-intrinsic.html minmax-width-special-values-block-intrinsic-ref.html
+== width-special-values-cell-auto.html width-special-values-cell-auto-ref.html
+== width-special-values-cell-fixed.html width-special-values-cell-fixed-ref.html
+== box-sizing-1.html box-sizing-1-ref.html
+== box-sizing-2.html box-sizing-2-ref.html
+== box-sizing-3.html box-sizing-1-ref.html
+== box-sizing-4.html box-sizing-4-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-block-intrinsic-ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>intrinsic widths for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+</head>
+<body>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div>AA B</div>
+</td></tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-block-intrinsic.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>intrinsic widths for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+</head>
+<body>
+
+<table border><tr><td>
+  <div style="width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-fill">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-fill">AA B</div>
+</td></tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-block-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 1px;
+      float: left;
+      clear: left;
+    }
+
+    div.fill { width: 37px; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<div class="">A B</div>
+<div class="">A B</div>
+<div class="">A B</div>
+<div class="">A <br>B</div>
+<div class="">A <br>B</div>
+<div class="">A <br>B</div>
+<div class="">A B</div>
+<div class="">A B</div>
+<div class="">A B</div>
+<div class="fill">A B C D E F G H I J</div>
+<div class="fill">A B C D E F G H I J</div>
+<div class="fill">A B C D E F G H I J</div>
+<div class="">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <br>B</div>
+<div class="">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <br>B</div>
+<div class="">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA <br>B</div>
+<div class="fill">A B</div>
+<div class="fill">A B</div>
+<div class="fill">A B</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-block.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      margin-bottom: 1px;
+    }
+
+    div.v1 { width: -moz-intrinsic; }
+    div.v2 { width: -moz-min-intrinsic; }
+    div.v3 { width: -moz-shrink-wrap; }
+    div.v4 { width: -moz-fill; }
+
+    div.s1 { -moz-box-sizing: content; }
+    div.s2 { -moz-box-sizing: padding; }
+    div.s3 { -moz-box-sizing: border; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<div class="v1 s1">A B</div>
+<div class="v1 s2">A B</div>
+<div class="v1 s3">A B</div>
+<div class="v2 s1">A B</div>
+<div class="v2 s2">A B</div>
+<div class="v2 s3">A B</div>
+<div class="v3 s1">A B</div>
+<div class="v3 s2">A B</div>
+<div class="v3 s3">A B</div>
+<div class="v3 s1">A B C D E F G H I J</div>
+<div class="v3 s2">A B C D E F G H I J</div>
+<div class="v3 s3">A B C D E F G H I J</div>
+<div class="v3 s1">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v3 s2">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v3 s3">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v4 s1">A B</div>
+<div class="v4 s2">A B</div>
+<div class="v4 s3">A B</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-cell-auto-ref.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on table cells with table-layout: auto</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    td td {
+      border-left: 1px solid;
+      padding-left: 2px;
+      padding-right: 4px;
+      border-right: 8px solid;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table border><tr>
+<td>
+<!-- width -->
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+
+</td>
+<td>
+<!-- min-width -->
+
+<table border><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+
+<table border><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+
+</td>
+<td>
+<!-- max-width -->
+
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td>A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+<table border><tr><td style="width: 150px">A B</td></tr></table>
+<table border width="1"><tr><td>A B</td></tr></table>
+
+
+</td>
+</tr></table>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-cell-auto.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on table cells with table-layout: auto</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    td td {
+      border-left: 1px solid;
+      padding-left: 2px;
+      padding-right: 4px;
+      border-right: 8px solid;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table border><tr>
+<td>
+<!-- width -->
+<table border><tr><td style="width: -moz-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: -moz-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: -moz-min-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: -moz-min-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: -moz-shrink-wrap">A B</td></tr></table>
+<table border width="1"><tr><td style="width: -moz-shrink-wrap">A B</td></tr></table>
+<table border><tr><td style="width: -moz-fill">A B</td></tr></table>
+<table border width="1"><tr><td style="width: -moz-fill">A B</td></tr></table>
+
+</td>
+<td>
+<!-- min-width -->
+
+<table border><tr><td style="min-width: -moz-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="min-width: -moz-intrinsic">A B</td></tr></table>
+<table border><tr><td style="min-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="min-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border><tr><td style="min-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border width="1"><tr><td style="min-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border><tr><td style="min-width: -moz-fill">A B</td></tr></table>
+<table border width="1"><tr><td style="min-width: -moz-fill">A B</td></tr></table>
+
+<table border><tr><td style="width: 1px; min-width: -moz-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 1px; min-width: -moz-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 1px; min-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 1px; min-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-fill">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 1px; min-width: -moz-fill">A B</td></tr></table>
+
+</td>
+<td>
+<!-- max-width -->
+
+<table border><tr><td style="max-width: -moz-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="max-width: -moz-intrinsic">A B</td></tr></table>
+<table border><tr><td style="max-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="max-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border><tr><td style="max-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border width="1"><tr><td style="max-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border><tr><td style="max-width: -moz-fill">A B</td></tr></table>
+<table border width="1"><tr><td style="max-width: -moz-fill">A B</td></tr></table>
+
+<table border><tr><td style="width: 150px; max-width: -moz-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 150px; max-width: -moz-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 150px; max-width: -moz-min-intrinsic">A B</td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 150px; max-width: -moz-shrink-wrap">A B</td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-fill">A B</td></tr></table>
+<table border width="1"><tr><td style="width: 150px; max-width: -moz-fill">A B</td></tr></table>
+
+
+</td>
+</tr></table>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-cell-fixed-ref.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on table cells with table-layout: fixed</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    td table { width: 200px; }
+    td td:first-child {
+      border-left: 1px solid;
+      padding-left: 2px;
+      padding-right: 4px;
+      border-right: 8px solid;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table border><tr>
+<td>
+<!-- width -->
+<table border><tr><td width="1">A&nbsp;B</td><td></td></tr></table>
+<table border><tr><td width="1">A B</td><td></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+
+</td>
+<td>
+<!-- min-width -->
+
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+
+<table border><tr><td width="1">A&nbsp;B</td><td></td></tr></table>
+<table border><tr><td width="1">A B</td><td></td></tr></table>
+<table border><tr><td width="1">A B</td><td></td></tr></table>
+<table border><tr><td width="1"><div style="width: 1px">A B</div></td><td></td></tr></table>
+
+</td>
+<td>
+<!-- max-width -->
+
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+<table border><tr><td width="50%">A B</td><td width="50%"></td></tr></table>
+
+<table border><tr><td width="1">A&nbsp;B</td><td></td></tr></table>
+<table border><tr><td width="1">A B</td><td></td></tr></table>
+<table border><tr><td width="1">A&nbsp;B</td><td></td></tr></table>
+<table border><tr><td width="150">A B</td><td></td></tr></table>
+
+</td>
+</tr></table>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-cell-fixed.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on table cells with table-layout: fixed</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    td table { table-layout: fixed; width: 200px; }
+    td td:first-child {
+      border-left: 1px solid;
+      padding-left: 2px;
+      padding-right: 4px;
+      border-right: 8px solid;
+
+      background: yellow;
+    }
+
+  </style>
+</head>
+<body>
+
+<table border><tr>
+<td>
+<!-- width -->
+<table border><tr><td style="width: -moz-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: -moz-min-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: -moz-shrink-wrap">A B</td><td></td></tr></table>
+<table border><tr><td style="width: -moz-fill">A B</td><td></td></tr></table>
+
+</td>
+<td>
+<!-- min-width -->
+
+<table border><tr><td style="min-width: -moz-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="min-width: -moz-min-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="min-width: -moz-shrink-wrap">A B</td><td></td></tr></table>
+<table border><tr><td style="min-width: -moz-fill">A B</td><td></td></tr></table>
+
+<table border><tr><td style="width: 1px; min-width: -moz-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-min-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-shrink-wrap">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 1px; min-width: -moz-fill">A B</td><td></td></tr></table>
+
+</td>
+<td>
+<!-- max-width -->
+
+<table border><tr><td style="max-width: -moz-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="max-width: -moz-min-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="max-width: -moz-shrink-wrap">A B</td><td></td></tr></table>
+<table border><tr><td style="max-width: -moz-fill">A B</td><td></td></tr></table>
+
+<table border><tr><td style="width: 150px; max-width: -moz-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-min-intrinsic">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-shrink-wrap">A B</td><td></td></tr></table>
+<table border><tr><td style="width: 150px; max-width: -moz-fill">A B</td><td></td></tr></table>
+
+
+</td>
+</tr></table>
+
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-float-intrinsic.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>intrinsic widths for -moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+  div { float: left; clear: left; }
+
+  </style>
+</head>
+<body>
+
+<table border><tr><td>
+  <div style="width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-min-intrinsic">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-shrink-wrap">AA B</div>
+</td></tr></table>
+
+<table border><tr><td>
+  <div style="width: -moz-fill">AA B</div>
+</td></tr></table>
+
+<table border width="1"><tr><td>
+  <div style="width: -moz-fill">AA B</div>
+</td></tr></table>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-float.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on blocks</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    body { font-size: 10px; line-height: 1; }
+
+    div {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+
+      background: yellow;
+      float: left;
+      clear: left;
+      margin-bottom: 1px;
+    }
+
+    div.v1 { width: -moz-intrinsic; }
+    div.v2 { width: -moz-min-intrinsic; }
+    div.v3 { width: -moz-shrink-wrap; }
+    div.v4 { width: -moz-fill; }
+
+    div.s1 { -moz-box-sizing: content; }
+    div.s2 { -moz-box-sizing: padding; }
+    div.s3 { -moz-box-sizing: border; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<div class="v1 s1">A B</div>
+<div class="v1 s2">A B</div>
+<div class="v1 s3">A B</div>
+<div class="v2 s1">A B</div>
+<div class="v2 s2">A B</div>
+<div class="v2 s3">A B</div>
+<div class="v3 s1">A B</div>
+<div class="v3 s2">A B</div>
+<div class="v3 s3">A B</div>
+<div class="v3 s1">A B C D E F G H I J</div>
+<div class="v3 s2">A B C D E F G H I J</div>
+<div class="v3 s3">A B C D E F G H I J</div>
+<div class="v3 s1">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v3 s2">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v3 s3">AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA B</div>
+<div class="v4 s1">A B</div>
+<div class="v4 s2">A B</div>
+<div class="v4 s3">A B</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-image-block-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on block images</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    img {
+      display: block;
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+      -moz-box-sizing: content;
+      margin-bottom: 1px;
+    }
+
+    img.v1 {  }
+    img.v2 {  }
+    img.v3 {  }
+    img.v4 { width: 37px; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s3">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-image-block.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on block images</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    img {
+      display: block;
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+      margin-bottom: 1px;
+    }
+
+    img.v1 { width: -moz-intrinsic; }
+    img.v2 { width: -moz-min-intrinsic; }
+    img.v3 { width: -moz-shrink-wrap; }
+    img.v4 { width: -moz-fill; }
+
+    img.s1 { -moz-box-sizing: content; }
+    img.s2 { -moz-box-sizing: padding; }
+    img.s3 { -moz-box-sizing: border; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s3">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-image-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on inline images</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    img {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+      -moz-box-sizing: content;
+      margin-bottom: 1px;
+    }
+
+    img.v1 {  }
+    img.v2 {  }
+    img.v3 {  }
+    img.v4 { width: 37px; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s3">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/box-properties/width-special-values-image.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+  <title>-moz-intrinsic, -moz-min-intrinsic, -moz-shrink-wrap, and -moz-fill values of CSS width property, on inline images</title>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <style type="text/css">
+
+    img {
+      margin-left: 1px;
+      border-left: 2px solid;
+      padding-left: 4px;
+      padding-right: 8px;
+      border-right: 16px solid;
+      margin-right: 32px;
+      margin-bottom: 1px;
+    }
+
+    img.v1 { width: -moz-intrinsic; }
+    img.v2 { width: -moz-min-intrinsic; }
+    img.v3 { width: -moz-shrink-wrap; }
+    img.v4 { width: -moz-fill; }
+
+    img.s1 { -moz-box-sizing: content; }
+    img.s2 { -moz-box-sizing: padding; }
+    img.s3 { -moz-box-sizing: border; }
+
+  </style>
+</head>
+<body style="width: 100px">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v1 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v2 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v3 s3">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s1">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s2">
+<img src="../pixel-rounding/green-25x25.png" alt="[]" class="v4 s3">
+</body>
+</html>
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -97,16 +97,17 @@ CSS_KEY(-moz-document, _moz_document)
 CSS_KEY(-moz-dragtargetzone, _moz_dragtargetzone)
 CSS_KEY(-moz-ethiopic-halehame, _moz_ethiopic_halehame)
 CSS_KEY(-moz-ethiopic-numeric, _moz_ethiopic_numeric)
 CSS_KEY(-moz-ethiopic-halehame-am, _moz_ethiopic_halehame_am)
 CSS_KEY(-moz-ethiopic-halehame-ti-er, _moz_ethiopic_halehame_ti_er)
 CSS_KEY(-moz-ethiopic-halehame-ti-et, _moz_ethiopic_halehame_ti_et)
 CSS_KEY(-moz-field, _moz_field)
 CSS_KEY(-moz-fieldtext, _moz_fieldtext)
+CSS_KEY(-moz-fill, _moz_fill)
 CSS_KEY(-moz-grabbing, _moz_grabbing)
 CSS_KEY(-moz-grab, _moz_grab)
 CSS_KEY(-moz-grid-group, _moz_grid_group)
 CSS_KEY(-moz-grid-line, _moz_grid_line)
 CSS_KEY(-moz-grid, _moz_grid)
 CSS_KEY(-moz-groupbox, _moz_groupbox)
 CSS_KEY(-moz-gujarati, _moz_gujarati)
 CSS_KEY(-moz-gurmukhi, _moz_gurmukhi)
@@ -114,16 +115,17 @@ CSS_KEY(-moz-hangul-consonant, _moz_hang
 CSS_KEY(-moz-hidden-unscrollable, _moz_hidden_unscrollable)
 CSS_KEY(-moz-hangul, _moz_hangul)
 CSS_KEY(-moz-hyperlinktext, _moz_hyperlinktext)
 CSS_KEY(-moz-info, _moz_info)
 CSS_KEY(-moz-initial, _moz_initial)
 CSS_KEY(-moz-inline-box, _moz_inline_box)
 CSS_KEY(-moz-inline-grid, _moz_inline_grid)
 CSS_KEY(-moz-inline-stack, _moz_inline_stack)
+CSS_KEY(-moz-intrinsic, _moz_intrinsic)
 CSS_KEY(-moz-japanese-formal, _moz_japanese_formal)
 CSS_KEY(-moz-japanese-informal, _moz_japanese_informal)
 CSS_KEY(-moz-kannada, _moz_kannada)
 CSS_KEY(-moz-khmer, _moz_khmer)
 CSS_KEY(-moz-lao, _moz_lao)
 CSS_KEY(-moz-left, _moz_left)
 CSS_KEY(-moz-list, _moz_list)
 CSS_KEY(-moz-mac-accentdarkestshadow, _moz_mac_accentdarkestshadow)
@@ -141,29 +143,31 @@ CSS_KEY(-moz-mac-menutextdisable, _moz_m
 CSS_KEY(-moz-mac-menutextselect, _moz_mac_menutextselect)
 CSS_KEY(-moz-mac-secondaryhighlight, _moz_mac_secondaryhighlight)
 CSS_KEY(-moz-malayalam, _moz_malayalam)
 CSS_KEY(-moz-marker, _moz_marker) // Disabled because not supported correctly.
 CSS_KEY(-moz-menuhover, _moz_menuhover)
 CSS_KEY(-moz-menuhovertext, _moz_menuhovertext)
 CSS_KEY(-moz-menubarhovertext, _moz_menubarhovertext)
 CSS_KEY(-moz-middle-with-baseline, _moz_middle_with_baseline)
+CSS_KEY(-moz-min-intrinsic, _moz_min_intrinsic)
 CSS_KEY(-moz-myanmar, _moz_myanmar)
 CSS_KEY(-moz-none, _moz_none)
 CSS_KEY(-moz-oriya, _moz_oriya)
 CSS_KEY(-moz-persian, _moz_persian)
 CSS_KEY(-moz-popup, _moz_popup)
 CSS_KEY(-moz-pre-wrap, _moz_pre_wrap)
 CSS_KEY(-moz-pull-down-menu, _moz_pull_down_menu)
 CSS_KEY(-moz-right, _moz_right)
 CSS_KEY(-moz-run-in, _moz_run_in) // Disabled because not supported.
 CSS_KEY(-moz-scrollbars-horizontal, _moz_scrollbars_horizontal)
 CSS_KEY(-moz-scrollbars-none, _moz_scrollbars_none)
 CSS_KEY(-moz-scrollbars-vertical, _moz_scrollbars_vertical)
 CSS_KEY(-moz-show-background, _moz_show_background)
+CSS_KEY(-moz-shrink-wrap, _moz_shrink_wrap)
 CSS_KEY(-moz-simp-chinese-formal, _moz_simp_chinese_formal)
 CSS_KEY(-moz-simp-chinese-informal, _moz_simp_chinese_informal)
 CSS_KEY(-moz-spinning, _moz_spinning)
 CSS_KEY(-moz-stack, _moz_stack)
 CSS_KEY(-moz-tamil, _moz_tamil)
 CSS_KEY(-moz-telugu, _moz_telugu)
 CSS_KEY(-moz-thai, _moz_thai)
 CSS_KEY(-moz-trad-chinese-formal, _moz_trad_chinese_formal)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -3551,24 +3551,26 @@ CSSParserImpl::DoTransferTempData(nsCSSD
 
 // Common combinations of variants
 #define VARIANT_AL   (VARIANT_AUTO | VARIANT_LENGTH)
 #define VARIANT_LP   (VARIANT_LENGTH | VARIANT_PERCENT)
 #define VARIANT_AH   (VARIANT_AUTO | VARIANT_INHERIT)
 #define VARIANT_AHLP (VARIANT_AH | VARIANT_LP)
 #define VARIANT_AHI  (VARIANT_AH | VARIANT_INTEGER)
 #define VARIANT_AHK  (VARIANT_AH | VARIANT_KEYWORD)
+#define VARIANT_AHKLP (VARIANT_AHLP | VARIANT_KEYWORD)
 #define VARIANT_AUK  (VARIANT_AUTO | VARIANT_URL | VARIANT_KEYWORD)
 #define VARIANT_AHUK (VARIANT_AH | VARIANT_URL | VARIANT_KEYWORD)
 #define VARIANT_AHL  (VARIANT_AH | VARIANT_LENGTH)
 #define VARIANT_AHKL (VARIANT_AHK | VARIANT_LENGTH)
 #define VARIANT_HK   (VARIANT_INHERIT | VARIANT_KEYWORD)
 #define VARIANT_HKF  (VARIANT_HK | VARIANT_FREQUENCY)
 #define VARIANT_HKL  (VARIANT_HK | VARIANT_LENGTH)
 #define VARIANT_HKLP (VARIANT_HK | VARIANT_LP)
+#define VARIANT_HKLPO (VARIANT_HKLP | VARIANT_NONE)
 #define VARIANT_HL   (VARIANT_INHERIT | VARIANT_LENGTH)
 #define VARIANT_HI   (VARIANT_INHERIT | VARIANT_INTEGER)
 #define VARIANT_HLP  (VARIANT_HL | VARIANT_PERCENT)
 #define VARIANT_HLPN (VARIANT_HLP | VARIANT_NUMBER)
 #define VARIANT_HLPO (VARIANT_HLP | VARIANT_NONE)
 #define VARIANT_HTP  (VARIANT_INHERIT | VARIANT_TIME | VARIANT_PERCENT)
 #define VARIANT_HMK  (VARIANT_HK | VARIANT_NORMAL)
 #define VARIANT_HMKI (VARIANT_HMK | VARIANT_INTEGER)
@@ -4623,18 +4625,20 @@ PRBool CSSParserImpl::ParseSingleValuePr
   case eCSSProperty_text_rendering:
     return ParseVariant(aErrorCode, aValue, VARIANT_AHK,
                         nsCSSProps::kTextRenderingKTable);
 #endif
   case eCSSProperty_box_sizing:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK,
                         nsCSSProps::kBoxSizingKTable);
   case eCSSProperty_height:
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);
   case eCSSProperty_width:
-    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHKLP,
+                                nsCSSProps::kWidthKTable);
   case eCSSProperty_force_broken_image_icon:
     return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HI, nsnull);
   case eCSSProperty_caption_side:
     return ParseVariant(aErrorCode, aValue, VARIANT_HK, 
                         nsCSSProps::kCaptionSideKTable);
   case eCSSProperty_clear:
     return ParseVariant(aErrorCode, aValue, VARIANT_HOK,
                         nsCSSProps::kClearKTable);
@@ -4708,21 +4712,25 @@ PRBool CSSParserImpl::ParseSingleValuePr
   case eCSSProperty_margin_start_value: // for internal use
   case eCSSProperty_margin_top:
     return ParseVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull);
   case eCSSProperty_marker_offset:
     return ParseVariant(aErrorCode, aValue, VARIANT_AHL, nsnull);
   case eCSSProperty_marks:
     return ParseMarks(aErrorCode, aValue);
   case eCSSProperty_max_height:
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLPO, nsnull);
   case eCSSProperty_max_width:
-    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLPO, nsnull);
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HKLPO,
+                                nsCSSProps::kWidthKTable);
   case eCSSProperty_min_height:
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);
   case eCSSProperty_min_width:
-    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HLP, nsnull);
+    return ParsePositiveVariant(aErrorCode, aValue, VARIANT_HKLP,
+                                nsCSSProps::kWidthKTable);
   case eCSSProperty_opacity:
     return ParseVariant(aErrorCode, aValue, VARIANT_HN, nsnull);
   case eCSSProperty_orphans:
   case eCSSProperty_widows:
     return ParseVariant(aErrorCode, aValue, VARIANT_HI, nsnull);
   case eCSSProperty_outline_color:
     return ParseVariant(aErrorCode, aValue, VARIANT_HCK, 
                         nsCSSProps::kOutlineColorKTable);
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -367,19 +367,19 @@ CSS_PROP_MARGIN(margin-right-rtl-source,
 CSS_PROP_SHORTHAND(-moz-margin-start, margin_start, MozMarginStart)
 #ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL
 CSS_PROP_MARGIN(margin-start-value, margin_start_value, X, Margin, mMarginStart, eCSSType_Value, nsnull)
 #endif
 CSS_PROP_MARGIN(margin-top, margin_top, MarginTop, Margin, mMargin.mTop, eCSSType_Value, nsnull)
 CSS_PROP_CONTENT(marker-offset, marker_offset, MarkerOffset, Content, mMarkerOffset, eCSSType_Value, nsnull)
 CSS_PROP_BACKENDONLY(marks, marks, Marks, Page, mMarks, eCSSType_Value, kPageMarksKTable)
 CSS_PROP_POSITION(max-height, max_height, MaxHeight, Position, mMaxHeight, eCSSType_Value, nsnull)
-CSS_PROP_POSITION(max-width, max_width, MaxWidth, Position, mMaxWidth, eCSSType_Value, nsnull)
+CSS_PROP_POSITION(max-width, max_width, MaxWidth, Position, mMaxWidth, eCSSType_Value, kWidthKTable)
 CSS_PROP_POSITION(min-height, min_height, MinHeight, Position, mMinHeight, eCSSType_Value, nsnull)
-CSS_PROP_POSITION(min-width, min_width, MinWidth, Position, mMinWidth, eCSSType_Value, nsnull)
+CSS_PROP_POSITION(min-width, min_width, MinWidth, Position, mMinWidth, eCSSType_Value, kWidthKTable)
 CSS_PROP_DISPLAY(opacity, opacity, Opacity, Display, mOpacity, eCSSType_Value, nsnull) // XXX bug 3935
 CSS_PROP_BACKENDONLY(orphans, orphans, Orphans, Breaks, mOrphans, eCSSType_Value, nsnull)
 CSS_PROP_SHORTHAND(outline, outline, Outline)
 CSS_PROP_OUTLINE(outline-color, outline_color, OutlineColor, Margin, mOutlineColor, eCSSType_Value, kOutlineColorKTable)
 CSS_PROP_OUTLINE(outline-style, outline_style, OutlineStyle, Margin, mOutlineStyle, eCSSType_Value, kBorderStyleKTable)
 CSS_PROP_OUTLINE(outline-width, outline_width, OutlineWidth, Margin, mOutlineWidth, eCSSType_Value, kBorderWidthKTable)
 CSS_PROP_OUTLINE(outline-offset, outline_offset, OutlineOffset, Margin, mOutlineOffset, eCSSType_Value, nsnull)
 CSS_PROP_SHORTHAND(overflow, overflow, Overflow)
@@ -441,17 +441,17 @@ CSS_PROP_USERINTERFACE(-moz-user-input, 
 CSS_PROP_USERINTERFACE(-moz-user-modify, user_modify, MozUserModify, UserInterface, mUserModify, eCSSType_Value, kUserModifyKTable) // XXX bug 3935
 CSS_PROP_UIRESET(-moz-user-select, user_select, MozUserSelect, UserInterface, mUserSelect, eCSSType_Value, kUserSelectKTable) // XXX bug 3935
 CSS_PROP_TEXTRESET(vertical-align, vertical_align, VerticalAlign, Text, mVerticalAlign, eCSSType_Value, kVerticalAlignKTable)
 CSS_PROP_VISIBILITY(visibility, visibility, Visibility, Display, mVisibility, eCSSType_Value, kVisibilityKTable)  // reflow for collapse
 CSS_PROP_BACKENDONLY(voice-family, voice_family, VoiceFamily, Aural, mVoiceFamily, eCSSType_Value, nsnull)
 CSS_PROP_BACKENDONLY(volume, volume, Volume, Aural, mVolume, eCSSType_Value, kVolumeKTable)
 CSS_PROP_TEXT(white-space, white_space, WhiteSpace, Text, mWhiteSpace, eCSSType_Value, kWhitespaceKTable)
 CSS_PROP_BACKENDONLY(widows, widows, Widows, Breaks, mWidows, eCSSType_Value, nsnull)
-CSS_PROP_POSITION(width, width, Width, Position, mWidth, eCSSType_Value, nsnull)
+CSS_PROP_POSITION(width, width, Width, Position, mWidth, eCSSType_Value, kWidthKTable)
 CSS_PROP_TEXT(word-spacing, word_spacing, WordSpacing, Text, mWordSpacing, eCSSType_Value, nsnull)
 CSS_PROP_POSITION(z-index, z_index, ZIndex, Position, mZIndex, eCSSType_Value, nsnull)
 
 CSS_PROP_XUL(-moz-box-align, box_align, MozBoxAlign, XUL, mBoxAlign, eCSSType_Value, kBoxAlignKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-direction, box_direction, MozBoxDirection, XUL, mBoxDirection, eCSSType_Value, kBoxDirectionKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-flex, box_flex, MozBoxFlex, XUL, mBoxFlex, eCSSType_Value, nsnull) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-orient, box_orient, MozBoxOrient, XUL, mBoxOrient, eCSSType_Value, kBoxOrientKTable) // XXX bug 3935
 CSS_PROP_XUL(-moz-box-pack, box_pack, MozBoxPack, XUL, mBoxPack, eCSSType_Value, kBoxPackKTable) // XXX bug 3935
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -936,16 +936,24 @@ const PRInt32 nsCSSProps::kVolumeKTable[
 
 const PRInt32 nsCSSProps::kWhitespaceKTable[] = {
   eCSSKeyword_pre, NS_STYLE_WHITESPACE_PRE,
   eCSSKeyword_nowrap, NS_STYLE_WHITESPACE_NOWRAP,
   eCSSKeyword__moz_pre_wrap, NS_STYLE_WHITESPACE_MOZ_PRE_WRAP,
   eCSSKeyword_UNKNOWN,-1
 };
 
+const PRInt32 nsCSSProps::kWidthKTable[] = {
+  eCSSKeyword__moz_intrinsic, NS_STYLE_WIDTH_INTRINSIC,
+  eCSSKeyword__moz_min_intrinsic, NS_STYLE_WIDTH_MIN_INTRINSIC,
+  eCSSKeyword__moz_shrink_wrap, NS_STYLE_WIDTH_SHRINK_WRAP,
+  eCSSKeyword__moz_fill, NS_STYLE_WIDTH_FILL,
+  eCSSKeyword_UNKNOWN,-1
+};
+
 // Specific keyword tables for XUL.properties
 const PRInt32 nsCSSProps::kBoxAlignKTable[] = {
   eCSSKeyword_stretch,  NS_STYLE_BOX_ALIGN_STRETCH,
   eCSSKeyword_start,   NS_STYLE_BOX_ALIGN_START,
   eCSSKeyword_center, NS_STYLE_BOX_ALIGN_CENTER,
   eCSSKeyword_baseline, NS_STYLE_BOX_ALIGN_BASELINE, 
   eCSSKeyword_end, NS_STYLE_BOX_ALIGN_END, 
   eCSSKeyword_UNKNOWN,-1
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -184,11 +184,12 @@ public:
   static const PRInt32 kUserFocusKTable[];
   static const PRInt32 kUserInputKTable[];
   static const PRInt32 kUserModifyKTable[];
   static const PRInt32 kUserSelectKTable[];
   static const PRInt32 kVerticalAlignKTable[];
   static const PRInt32 kVisibilityKTable[];
   static const PRInt32 kVolumeKTable[];
   static const PRInt32 kWhitespaceKTable[];
+  static const PRInt32 kWidthKTable[]; // also min-width, max-width
 };
 
 #endif /* nsCSSProps_h___ */
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2224,18 +2224,18 @@ nsComputedDOMStyle::GetWidth(nsIDOMCSSVa
       StyleCoordToNSCoord(positionData->mMinWidth,
                           &nsComputedDOMStyle::GetCBContentWidth, 0);
 
     nscoord maxWidth =
       StyleCoordToNSCoord(positionData->mMaxWidth,
                           &nsComputedDOMStyle::GetCBContentWidth,
                           nscoord_MAX);
     
-    SetValueToCoord(val, positionData->mWidth, nsnull, nsnull,
-                    minWidth, maxWidth);
+    SetValueToCoord(val, positionData->mWidth, nsnull,
+                    nsCSSProps::kWidthKTable, minWidth, maxWidth);
   }
 
   return CallQueryInterface(val, aValue);
 }
 
 nsresult
 nsComputedDOMStyle::GetMaxHeight(nsIDOMCSSValue** aValue)
 {
@@ -2250,17 +2250,18 @@ nsComputedDOMStyle::GetMaxHeight(nsIDOMC
 
 nsresult
 nsComputedDOMStyle::GetMaxWidth(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   SetValueToCoord(val, GetStylePosition()->mMaxWidth,
-                  &nsComputedDOMStyle::GetCBContentWidth);
+                  &nsComputedDOMStyle::GetCBContentWidth,
+                  nsCSSProps::kWidthKTable);
 
   return CallQueryInterface(val, aValue);
 }
 
 nsresult
 nsComputedDOMStyle::GetMinHeight(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
@@ -2274,17 +2275,18 @@ nsComputedDOMStyle::GetMinHeight(nsIDOMC
 
 nsresult
 nsComputedDOMStyle::GetMinWidth(nsIDOMCSSValue** aValue)
 {
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
 
   SetValueToCoord(val, GetStylePosition()->mMinWidth,
-                  &nsComputedDOMStyle::GetCBContentWidth);
+                  &nsComputedDOMStyle::GetCBContentWidth,
+                  nsCSSProps::kWidthKTable);
 
   return CallQueryInterface(val, aValue);
 }
 
 nsresult
 nsComputedDOMStyle::GetLeft(nsIDOMCSSValue** aValue)
 {
   return GetOffsetWidthFor(NS_SIDE_LEFT, aValue);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -245,16 +245,17 @@ nscoord CalcLength(const nsCSSValue& aVa
 
 #define SETCOORD_LP     (SETCOORD_LENGTH | SETCOORD_PERCENT)
 #define SETCOORD_LH     (SETCOORD_LENGTH | SETCOORD_INHERIT)
 #define SETCOORD_AH     (SETCOORD_AUTO | SETCOORD_INHERIT)
 #define SETCOORD_LAH    (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
 #define SETCOORD_LPH    (SETCOORD_LP | SETCOORD_INHERIT)
 #define SETCOORD_LPAH   (SETCOORD_LP | SETCOORD_AH)
 #define SETCOORD_LPEH   (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
+#define SETCOORD_LPAEH  (SETCOORD_LPAH | SETCOORD_ENUMERATED)
 #define SETCOORD_LE     (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
 #define SETCOORD_LEH    (SETCOORD_LE | SETCOORD_INHERIT)
 #define SETCOORD_IA     (SETCOORD_INTEGER | SETCOORD_AUTO)
 #define SETCOORD_LAE    (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
 
 // changes aCoord iff it returns PR_TRUE
 static PRBool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord, 
                        const nsStyleCoord& aParentCoord,
@@ -3582,21 +3583,21 @@ nsRuleNode::ComputePositionData(nsStyleS
       pos->mOffset.Set(side, coord);
     }
   }
 
   if (posData.mWidth.GetUnit() == eCSSUnit_Proportional)
     pos->mWidth.SetIntValue((PRInt32)(posData.mWidth.GetFloatValue()), eStyleUnit_Proportional);
   else 
     SetCoord(posData.mWidth, pos->mWidth, parentPos->mWidth,
-             SETCOORD_LPAH, aContext, mPresContext, inherited);
+             SETCOORD_LPAEH, aContext, mPresContext, inherited);
   SetCoord(posData.mMinWidth, pos->mMinWidth, parentPos->mMinWidth,
-           SETCOORD_LPH, aContext, mPresContext, inherited);
+           SETCOORD_LPEH, aContext, mPresContext, inherited);
   if (! SetCoord(posData.mMaxWidth, pos->mMaxWidth, parentPos->mMaxWidth,
-                 SETCOORD_LPH, aContext, mPresContext, inherited)) {
+                 SETCOORD_LPEH, aContext, mPresContext, inherited)) {
     if (eCSSUnit_None == posData.mMaxWidth.GetUnit()) {
       pos->mMaxWidth.Reset();
     }
   }
 
   SetCoord(posData.mHeight, pos->mHeight, parentPos->mHeight,
            SETCOORD_LPAH, aContext, mPresContext, inherited);
   SetCoord(posData.mMinHeight, pos->mMinHeight, parentPos->mMinHeight,
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -631,19 +631,19 @@ struct nsStylePosition : public nsStyleS
   }
 
   nsChangeHint CalcDifference(const nsStylePosition& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   
   nsStyleSides  mOffset;                // [reset]
-  nsStyleCoord  mWidth;                 // [reset] coord, percent, auto
-  nsStyleCoord  mMinWidth;              // [reset] coord, percent
-  nsStyleCoord  mMaxWidth;              // [reset] coord, percent, null
+  nsStyleCoord  mWidth;                 // [reset] coord, percent, auto, enum
+  nsStyleCoord  mMinWidth;              // [reset] coord, percent, enum
+  nsStyleCoord  mMaxWidth;              // [reset] coord, percent, null, enum
   nsStyleCoord  mHeight;                // [reset] coord, percent, auto
   nsStyleCoord  mMinHeight;             // [reset] coord, percent
   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, null
   PRUint8       mBoxSizing;             // [reset] see nsStyleConsts.h
   nsStyleCoord  mZIndex;                // [reset] 
 };
 
 struct nsStyleTextReset : public nsStyleStruct {
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -41,16 +41,30 @@ const CSS_TYPE_LONGHAND = 0;
 
 // True shorthand properties.
 const CSS_TYPE_TRUE_SHORTHAND = 1;
 
 // Properties that we handle as shorthands but were longhands either in
 // the current spec or earlier versions of the spec.
 const CSS_TYPE_SHORTHAND_AND_LONGHAND = 2;
 
+// Each property has the following fields:
+//   domProp: The name of the relevant member of nsIDOM[NS]CSS2Properties
+//   inherited: Whether the property is inherited by default (stated as 
+//     yes or no in the property header in all CSS specs)
+//   type: see above
+//   initial_values: Values whose computed value should be the same as the
+//     computed value for the property's initial value.
+//   other_values: Values whose computed value should be different from the
+//     computed value for the property's initial value.
+//   XXX Should have a third field for values whose computed value may or
+//     may not be the same as for the property's initial value.
+//   invalid_values: Things that are not values for the property and
+//     should be rejected.
+
 var gCSSProperties = {
 	"-moz-appearance": {
 		domProp: "MozAppearance",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
 		other_values: [ "radio", "menulist" ],
 		invalid_values: []
@@ -850,17 +864,17 @@ var gCSSProperties = {
 	},
 	"height": {
 		domProp: "height",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ " auto" ],
 		/* XXX these have prerequisites */
 		other_values: [ "15px", "3em", "15%" ],
-		invalid_values: []
+		invalid_values: [ "none", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ]
 	},
 	"left": {
 		domProp: "left",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		/* XXX requires position to be set */
 		/* XXX 0 may or may not be equal to auto */
 		initial_values: [ "auto" ],
@@ -982,40 +996,40 @@ var gCSSProperties = {
 		invalid_values: [ "none none", "crop none", "none crop", "cross none", "none cross" ]
 	},
 	"max-height": {
 		domProp: "maxHeight",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
 		other_values: [ "30px", "50%", "0" ],
-		invalid_values: [ "auto" ]
+		invalid_values: [ "auto", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ]
 	},
 	"max-width": {
 		domProp: "maxWidth",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
-		other_values: [ "30px", "50%", "0" ],
+		other_values: [ "30px", "50%", "0", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ],
 		invalid_values: [ "auto" ]
 	},
 	"min-height": {
 		domProp: "minHeight",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "0" ],
 		other_values: [ "30px", "50%" ],
-		invalid_values: [ "auto", "none" ]
+		invalid_values: [ "auto", "none", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ]
 	},
 	"min-width": {
 		domProp: "minWidth",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "0" ],
-		other_values: [ "30px", "50%" ],
+		other_values: [ "30px", "50%", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ],
 		invalid_values: [ "auto", "none" ]
 	},
 	"opacity": {
 		domProp: "opacity",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "1", "17", "397.376" ],
 		other_values: [ "0", "0.4", "0.0000", "-3" ],
@@ -1463,18 +1477,18 @@ var gCSSProperties = {
 		]
 	},
 	"width": {
 		domProp: "width",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ " auto" ],
 		/* XXX these have prerequisites */
-		other_values: [ "15px", "3em", "15%" ],
-		invalid_values: []
+		other_values: [ "15px", "3em", "15%", "-moz-intrinsic", "-moz-min-intrinsic", "-moz-shrink-wrap", "-moz-fill" ],
+		invalid_values: [ "none" ]
 	},
 	"word-spacing": {
 		domProp: "wordSpacing",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "normal", "0", "0px", "-0em" ],
 		other_values: [ "1em", "2px", "-3px" ],
 		invalid_values: []
--- a/layout/tables/BasicTableLayoutStrategy.cpp
+++ b/layout/tables/BasicTableLayoutStrategy.cpp
@@ -98,121 +98,150 @@ struct CellWidthInfo {
     nscoord prefCoord;
     float prefPercent;
 };
 
 // Used for both column and cell calculations.  The parts needed only
 // for cells are skipped when aCellFrame is null.
 static CellWidthInfo
 GetWidthInfo(nsIRenderingContext *aRenderingContext,
-             nsTableCellFrame *aCellFrame,
+             nsIFrame *aFrame,
+             PRBool aIsCell,
              const nsStylePosition *aStylePos)
 {
     nscoord minCoord, prefCoord;
-    if (aCellFrame) {
-        minCoord = aCellFrame->GetMinWidth(aRenderingContext);
-        prefCoord = aCellFrame->GetPrefWidth(aRenderingContext);
+    if (aIsCell) {
+        minCoord = aFrame->GetMinWidth(aRenderingContext);
+        prefCoord = aFrame->GetPrefWidth(aRenderingContext);
     } else {
         minCoord = 0;
         prefCoord = 0;
     }
     float prefPercent = 0.0f;
     PRBool hasSpecifiedWidth = PR_FALSE;
 
-    switch (aStylePos->mWidth.GetUnit()) {
-        case eStyleUnit_Coord: {
-                hasSpecifiedWidth = PR_TRUE;
-                nscoord w = aStylePos->mWidth.GetCoordValue();
-                // Quirk: A cell with "nowrap" set and a coord value for the
-                // width which is bigger than the intrinsic minimum width uses
-                // that coord value as the minimum width.
-                if (aCellFrame && w > minCoord &&
-                    aCellFrame->PresContext()->CompatibilityMode() ==
-                      eCompatibility_NavQuirks &&
-                    aCellFrame->GetContent()->HasAttr(kNameSpaceID_None,
-                                                      nsGkAtoms::nowrap)) {
-                    minCoord = w;
-                }
-                prefCoord = PR_MAX(w, minCoord);
-            }
-            break;
-        case eStyleUnit_Percent: {
-                prefPercent = aStylePos->mWidth.GetPercentValue();
-            }
-            break;
-        default:
-            break;
+    // XXXldb Should we consider -moz-box-sizing?
+
+    nsStyleUnit unit = aStylePos->mWidth.GetUnit();
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars) {
+        hasSpecifiedWidth = PR_TRUE;
+        nscoord w = nsLayoutUtils::ComputeWidthValue(aRenderingContext,
+                      aFrame, 0, 0, 0, aStylePos->mWidth);
+        // Quirk: A cell with "nowrap" set and a coord value for the
+        // width which is bigger than the intrinsic minimum width uses
+        // that coord value as the minimum width.
+        if (aIsCell && w > minCoord &&
+            aFrame->PresContext()->CompatibilityMode() ==
+              eCompatibility_NavQuirks &&
+            aFrame->GetContent()->HasAttr(kNameSpaceID_None,
+                                          nsGkAtoms::nowrap)) {
+            minCoord = w;
+        }
+        prefCoord = PR_MAX(w, minCoord);
+    } else if (unit == eStyleUnit_Percent) {
+        prefPercent = aStylePos->mWidth.GetPercentValue();
+    } else if (unit == eStyleUnit_Enumerated && aIsCell) {
+        switch (aStylePos->mWidth.GetIntValue()) {
+            case NS_STYLE_WIDTH_INTRINSIC:
+                // 'width' only affects pref width, not min
+                // width, so don't change anything
+                break;
+            case NS_STYLE_WIDTH_MIN_INTRINSIC:
+                prefCoord = minCoord;
+                break;
+            case NS_STYLE_WIDTH_SHRINK_WRAP:
+            case NS_STYLE_WIDTH_FILL:
+                // act just like 'width: auto'
+                break;
+            default:
+                NS_NOTREACHED("unexpected enumerated value");
+        }
     }
 
-    switch (aStylePos->mMaxWidth.GetUnit()) {
-        // XXX To really implement 'max-width' well, we'd need to store
-        // it separately on the columns.
-        case eStyleUnit_Coord: {
-                nscoord w = aStylePos->mMaxWidth.GetCoordValue();
-                if (w < minCoord)
-                    minCoord = w;
-                if (w < prefCoord)
-                    prefCoord = w;
-            }
-            break;
-        case eStyleUnit_Percent: {
-                float p = aStylePos->mMaxWidth.GetPercentValue();
-                if (p < prefPercent)
-                    prefPercent = p;
-            }
-            break;
-        default:
-            break;
+    nsStyleCoord maxWidth(aStylePos->mMaxWidth);
+    if (maxWidth.GetUnit() == eStyleUnit_Enumerated) {
+        if (!aIsCell || maxWidth.GetIntValue() == NS_STYLE_WIDTH_FILL)
+            maxWidth.Reset();
+        else if (maxWidth.GetIntValue() == NS_STYLE_WIDTH_SHRINK_WRAP)
+            // for 'max-width', '-moz-shrink-wrap' is like
+            // '-moz-intrinsic'
+            maxWidth.SetIntValue(NS_STYLE_WIDTH_INTRINSIC,
+                                 eStyleUnit_Enumerated);
+    }
+    unit = maxWidth.GetUnit();
+    // XXX To really implement 'max-width' well, we'd need to store
+    // it separately on the columns.
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars ||
+        unit == eStyleUnit_Enumerated) {
+        nscoord w =
+            nsLayoutUtils::ComputeWidthValue(aRenderingContext, aFrame,
+                                             0, 0, 0, maxWidth);
+        if (w < minCoord)
+            minCoord = w;
+        if (w < prefCoord)
+            prefCoord = w;
+    } else if (unit == eStyleUnit_Percent) {
+        float p = aStylePos->mMaxWidth.GetPercentValue();
+        if (p < prefPercent)
+            prefPercent = p;
     }
 
-    switch (aStylePos->mMinWidth.GetUnit()) {
-        case eStyleUnit_Coord: {
-                nscoord w = aStylePos->mMinWidth.GetCoordValue();
-                if (w > minCoord)
-                    minCoord = w;
-                if (w > prefCoord)
-                    prefCoord = w;
-            }
-            break;
-        case eStyleUnit_Percent: {
-                float p = aStylePos->mMinWidth.GetPercentValue();
-                if (p > prefPercent)
-                    prefPercent = p;
-            }
-            break;
-        default:
-            break;
+    nsStyleCoord minWidth(aStylePos->mMinWidth);
+    if (minWidth.GetUnit() == eStyleUnit_Enumerated) {
+        if (!aIsCell || minWidth.GetIntValue() == NS_STYLE_WIDTH_FILL)
+            minWidth.SetCoordValue(0);
+        else if (minWidth.GetIntValue() == NS_STYLE_WIDTH_SHRINK_WRAP)
+            // for 'min-width', '-moz-shrink-wrap' is like
+            // '-moz-min-intrinsic'
+            minWidth.SetIntValue(NS_STYLE_WIDTH_MIN_INTRINSIC,
+                                 eStyleUnit_Enumerated);
+    }
+    unit = minWidth.GetUnit();
+    if (unit == eStyleUnit_Coord || unit == eStyleUnit_Chars ||
+        unit == eStyleUnit_Enumerated) {
+        nscoord w =
+            nsLayoutUtils::ComputeWidthValue(aRenderingContext, aFrame,
+                                             0, 0, 0, minWidth);
+        if (w > minCoord)
+            minCoord = w;
+        if (w > prefCoord)
+            prefCoord = w;
+    } else if (unit == eStyleUnit_Percent) {
+        float p = aStylePos->mMinWidth.GetPercentValue();
+        if (p > prefPercent)
+            prefPercent = p;
     }
 
     // XXX Should col frame have border/padding considered?
-    if (aCellFrame) {
+    if (aIsCell) {
         nsIFrame::IntrinsicWidthOffsetData offsets =
-            aCellFrame->IntrinsicWidthOffsets(aRenderingContext);
+            aFrame->IntrinsicWidthOffsets(aRenderingContext);
         // XXX Should we ignore percentage padding?
         nscoord add = offsets.hPadding + offsets.hBorder;
         minCoord += add;
         prefCoord += add;
     }
 
     return CellWidthInfo(minCoord, prefCoord, prefPercent, hasSpecifiedWidth);
 }
 
 static inline CellWidthInfo
 GetCellWidthInfo(nsIRenderingContext *aRenderingContext,
                  nsTableCellFrame *aCellFrame)
 {
-    return GetWidthInfo(aRenderingContext, aCellFrame,
+    return GetWidthInfo(aRenderingContext, aCellFrame, PR_TRUE,
                         aCellFrame->GetStylePosition());
 }
 
 static inline CellWidthInfo
 GetColWidthInfo(nsIRenderingContext *aRenderingContext,
                 nsIFrame *aFrame)
 {
-    return GetWidthInfo(aRenderingContext, nsnull, aFrame->GetStylePosition());
+    return GetWidthInfo(aRenderingContext, aFrame, PR_FALSE,
+                        aFrame->GetStylePosition());
 }
 
 
 /**
  * The algorithm in this function, in addition to meeting the
  * requirements of Web-compatibility, is also invariant under reordering
  * of the rows within a table (something that most, but not all, other
  * browsers are).
--- a/layout/tables/FixedTableLayoutStrategy.cpp
+++ b/layout/tables/FixedTableLayoutStrategy.cpp
@@ -93,32 +93,40 @@ FixedTableLayoutStrategy::GetMinWidth(ns
     for (PRInt32 col = 0; col < colCount; ++col) {
         nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
         if (!colFrame) {
             NS_ERROR("column frames out of sync with cell map");
             continue;
         }
         const nsStyleCoord *styleWidth =
             &colFrame->GetStylePosition()->mWidth;
-        if (styleWidth->GetUnit() == eStyleUnit_Coord) {
-            result += styleWidth->GetCoordValue();
+        if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+            styleWidth->GetUnit() == eStyleUnit_Chars) {
+            result += nsLayoutUtils::ComputeWidthValue(aRenderingContext,
+                        colFrame, 0, 0, 0, *styleWidth);
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             // do nothing
         } else {
-            NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto, "bad width");
+            NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
+                         styleWidth->GetUnit() == eStyleUnit_Enumerated,
+                         "bad width");
 
             // The 'table-layout: fixed' algorithm considers only cells
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
             if (cellFrame) {
                 styleWidth = &cellFrame->GetStylePosition()->mWidth;
-                if (styleWidth->GetUnit() == eStyleUnit_Coord) {
+                if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+                    styleWidth->GetUnit() == eStyleUnit_Chars ||
+                    (styleWidth->GetUnit() == eStyleUnit_Enumerated &&
+                     (styleWidth->GetIntValue() == NS_STYLE_WIDTH_INTRINSIC ||
+                      styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_INTRINSIC))) {
                     nscoord cellWidth = nsLayoutUtils::IntrinsicForContainer(
                         aRenderingContext, cellFrame, nsLayoutUtils::MIN_WIDTH);
                     if (colSpan > 1) {
                         // If a column-spanning cell is in the first
                         // row, split up the space evenly.  (XXX This
                         // isn't quite right if some of the columns it's
                         // in have specified widths.  Should we care?)
                         cellWidth = ((cellWidth + spacing) / colSpan) - spacing;
@@ -126,16 +134,18 @@ FixedTableLayoutStrategy::GetMinWidth(ns
                     result += cellWidth;
                 } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
                     if (colSpan > 1) {
                         // XXX Can this force columns to negative
                         // widths?
                         result -= spacing * (colSpan - 1);
                     }
                 }
+                // else, for 'auto', '-moz-fill', and '-moz-shrink-wrap'
+                // do nothing
             }
         }
     }
 
     return (mMinWidth = result);
 }
 
 /* virtual */ nscoord
@@ -201,52 +211,68 @@ FixedTableLayoutStrategy::ComputeColumnW
         if (!colFrame) {
             NS_ERROR("column frames out of sync with cell map");
             continue;
         }
         colFrame->ResetPrefPercent();
         const nsStyleCoord *styleWidth =
             &colFrame->GetStylePosition()->mWidth;
         nscoord colWidth;
-        if (styleWidth->GetUnit() == eStyleUnit_Coord) {
-            colWidth = styleWidth->GetCoordValue();
+        if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+            styleWidth->GetUnit() == eStyleUnit_Chars) {
+            colWidth = nsLayoutUtils::ComputeWidthValue(
+                         aReflowState.rendContext,
+                         colFrame, 0, 0, 0, *styleWidth);
         } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
             float pct = styleWidth->GetPercentValue();
             colWidth = NSToCoordFloor(pct * float(tableWidth));
             colFrame->AddPrefPercent(pct);
             pctTotal += pct;
         } else {
-            NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto, "bad width");
+            NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
+                         styleWidth->GetUnit() == eStyleUnit_Enumerated,
+                         "bad width");
 
             // The 'table-layout: fixed' algorithm considers only cells
             // in the first row.
             PRBool originates;
             PRInt32 colSpan;
             nsTableCellFrame *cellFrame =
                 cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
             if (cellFrame) {
                 styleWidth = &cellFrame->GetStylePosition()->mWidth;
-                if (styleWidth->GetUnit() == eStyleUnit_Coord) {
-                    colWidth = styleWidth->GetCoordValue();
+                if (styleWidth->GetUnit() == eStyleUnit_Coord ||
+                    styleWidth->GetUnit() == eStyleUnit_Chars ||
+                    (styleWidth->GetUnit() == eStyleUnit_Enumerated &&
+                     (styleWidth->GetIntValue() == NS_STYLE_WIDTH_INTRINSIC ||
+                      styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_INTRINSIC))) {
+                    // XXX This should use real percentage padding
+                    // Note that the difference between MIN_WIDTH and
+                    // PREF_WIDTH shouldn't matter for any of these
+                    // values of styleWidth; use MIN_WIDTH for symmetry
+                    // with GetMinWidth above, just in case there is a
+                    // difference.
+                    colWidth = nsLayoutUtils::IntrinsicForContainer(
+                                 aReflowState.rendContext,
+                                 cellFrame, nsLayoutUtils::MIN_WIDTH);
                 } else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
+                    // XXX This should use real percentage padding
+                    nsIFrame::IntrinsicWidthOffsetData offsets =
+                        cellFrame->IntrinsicWidthOffsets(aReflowState.rendContext);
                     float pct = styleWidth->GetPercentValue();
-                    colWidth = NSToCoordFloor(pct * float(tableWidth));
+                    colWidth = NSToCoordFloor(pct * float(tableWidth)) +
+                               offsets.hPadding + offsets.hBorder;
                     pct /= float(colSpan);
                     colFrame->AddPrefPercent(pct);
                     pctTotal += pct;
                 } else {
+                    // 'auto', '-moz-fill', and '-moz-shrink-wrap'
                     colWidth = unassignedMarker;
                 }
                 if (colWidth != unassignedMarker) {
-                    // Add in cell's padding and border.
-                    // XXX This should use real percentage padding
-                    nsIFrame::IntrinsicWidthOffsetData offsets =
-                        cellFrame->IntrinsicWidthOffsets(aReflowState.rendContext);
-                    colWidth += offsets.hPadding + offsets.hBorder;
-
                     if (colSpan > 1) {
                         // If a column-spanning cell is in the first
                         // row, split up the space evenly.  (XXX This
                         // isn't quite right if some of the columns it's
                         // in have specified widths.  Should we care?)
                         colWidth = ((colWidth + spacing) / colSpan) - spacing;
                         if (colWidth < 0)
                             colWidth = 0;
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -3363,16 +3363,17 @@ nsTableFrame::IsAutoWidth(PRBool* aIsPct
 {
   const nsStyleCoord& width = GetStylePosition()->mWidth;
 
   if (aIsPctWidth) {
     // XXX The old code also made the return value true for 0%, but that
     // seems silly.
     *aIsPctWidth = width.GetUnit() == eStyleUnit_Percent &&
                    width.GetPercentValue() > 0.0f;
+    // Should this handle -moz-fill and -moz-shrink-wrap?
   }
   return width.GetUnit() == eStyleUnit_Auto;
 }
 
 PRBool 
 nsTableFrame::IsAutoHeight()
 {
   PRBool isAuto = PR_TRUE;  // the default
@@ -3409,20 +3410,27 @@ nsTableFrame::CalcBorderBoxHeight(const 
   height = PR_MAX(0, height);
 
   return height;
 }
 
 PRBool 
 nsTableFrame::IsAutoLayout()
 {
+  if (GetStyleTable()->mLayoutStrategy == NS_STYLE_TABLE_LAYOUT_AUTO)
+    return PR_TRUE;
   // a fixed-layout inline-table must have a width
-  return GetStyleTable()->mLayoutStrategy == NS_STYLE_TABLE_LAYOUT_AUTO ||
-         (GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE &&
-          GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto);
+  // and tables with 'width: -moz-intrinsic' must be auto-layout
+  // (at least as long as FixedTableLayoutStrategy::GetPrefWidth returns
+  // nscoord_MAX)
+  const nsStyleCoord &width = GetStylePosition()->mWidth;
+  return (GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE &&
+          width.GetUnit() == eStyleUnit_Auto) ||
+         (width.GetUnit() == eStyleUnit_Enumerated &&
+          width.GetIntValue() == NS_STYLE_WIDTH_INTRINSIC);
 }
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTableFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Table"), aResult);
 }
--- a/layout/xul/base/src/grid/nsGridRowLeafFrame.cpp
+++ b/layout/xul/base/src/grid/nsGridRowLeafFrame.cpp
@@ -79,17 +79,17 @@ nsGridRowLeafFrame::GetBorderAndPadding(
   PRInt32 index = 0;
   nsGrid* grid = part->GetGrid(this, &index);
 
   if (!grid) 
     return rv;
 
   PRBool isHorizontal = IsHorizontal();
 
-  nsBoxLayoutState state((nsPresContext*) PresContext());
+  nsBoxLayoutState state(PresContext());
 
   PRInt32 firstIndex = 0;
   PRInt32 lastIndex = 0;
   nsGridRow* firstRow = nsnull;
   nsGridRow* lastRow = nsnull;
   grid->GetFirstAndLastRow(state, firstIndex, lastIndex, firstRow, lastRow, isHorizontal);
 
   // only the first and last rows can be affected.
--- a/layout/xul/base/src/nsBox.cpp
+++ b/layout/xul/base/src/nsBox.cpp
@@ -679,29 +679,32 @@ nsIBox::AddCSSPrefSize(nsBoxLayoutState&
     // add in the css min, max, pref
     const nsStylePosition* position = aBox->GetStylePosition();
 
     // see if the width or height was specifically set
     if (position->mWidth.GetUnit() == eStyleUnit_Coord)  {
         aSize.width = position->mWidth.GetCoordValue();
         widthSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars, eStyleUnit_Enumerated?
+    // (Handling the eStyleUnit_Enumerated types requires
+    // GetPrefSize/GetMinSize methods that don't consider
+    // (min-/max-/)(width/height) properties.
 
     if (position->mHeight.GetUnit() == eStyleUnit_Coord) {
         aSize.height = position->mHeight.GetCoordValue();     
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
     
     nsIContent* content = aBox->GetContent();
     // ignore 'height' and 'width' attributes if the actual element is not XUL
     // For example, we might be magic XUL frames whose primary content is an HTML
     // <select>
     if (content && content->IsNodeOfType(nsINode::eXUL)) {
-        nsPresContext* presContext = aState.PresContext();
-
         nsAutoString value;
         PRInt32 error;
 
         content->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
         if (!value.IsEmpty()) {
             value.Trim("%");
 
             aSize.width =
@@ -765,34 +768,37 @@ nsIBox::AddCSSMinSize(nsBoxLayoutState& 
            widthSet = PR_TRUE;
         }
     } else if (position->mMinWidth.GetUnit() == eStyleUnit_Percent) {
         float min = position->mMinWidth.GetPercentValue();
         NS_ASSERTION(min == 0.0f, "Non-zero percentage values not currently supported");
         aSize.width = 0;
         widthSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars, eStyleUnit_Enumerated?
+    // (Handling the eStyleUnit_Enumerated types requires
+    // GetPrefSize/GetMinSize methods that don't consider
+    // (min-/max-/)(width/height) properties.
 
     if (position->mMinHeight.GetUnit() == eStyleUnit_Coord) {
         nscoord min = position->mMinHeight.GetCoordValue();
         if (min && (!heightSet || (min > aSize.height && canOverride))) {
            aSize.height = min;
            heightSet = PR_TRUE;
         }
     } else if (position->mMinHeight.GetUnit() == eStyleUnit_Percent) {
         float min = position->mMinHeight.GetPercentValue();
         NS_ASSERTION(min == 0.0f, "Non-zero percentage values not currently supported");
         aSize.height = 0;
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
 
     nsIContent* content = aBox->GetContent();
     if (content) {
-        nsPresContext* presContext = aState.PresContext();
-
         nsAutoString value;
         PRInt32 error;
 
         content->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value);
         if (!value.IsEmpty())
         {
             value.Trim("%");
 
@@ -831,27 +837,30 @@ nsIBox::AddCSSMaxSize(nsBoxLayoutState& 
     const nsStylePosition* position = aBox->GetStylePosition();
 
     // and max
     if (position->mMaxWidth.GetUnit() == eStyleUnit_Coord) {
         nscoord max = position->mMaxWidth.GetCoordValue();
         aSize.width = max;
         widthSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars, eStyleUnit_Enumerated?
+    // (Handling the eStyleUnit_Enumerated types requires
+    // GetPrefSize/GetMinSize methods that don't consider
+    // (min-/max-/)(width/height) properties.
 
     if (position->mMaxHeight.GetUnit() == eStyleUnit_Coord) {
         nscoord max = position->mMaxHeight.GetCoordValue();
         aSize.height = max;
         heightSet = PR_TRUE;
     }
+    // XXX Handle eStyleUnit_Chars?
 
     nsIContent* content = aBox->GetContent();
     if (content) {
-        nsPresContext* presContext = aState.PresContext();
-
         nsAutoString value;
         PRInt32 error;
 
         content->GetAttr(kNameSpaceID_None, nsGkAtoms::maxwidth, value);
         if (!value.IsEmpty()) {
             value.Trim("%");
 
             nscoord val =