Bug 1334330 - Part 6: stylo: Use GenericSpecifiedValue abstraction for table elements; r?emilio draft
authorManish Goregaokar <manishearth@gmail.com>
Thu, 26 Jan 2017 16:51:01 -0800
changeset 480661 1764700ff0edb7259383d0d76e6be9a19b6e7f7f
parent 480660 e093ba5ef7c21debaf9f4e4637166e53901645d9
child 480662 8ce0d719dbf9da64f60493fb43753c1339ac4ccb
push id44619
push userbmo:manishearth@gmail.com
push dateWed, 08 Feb 2017 19:34:01 +0000
reviewersemilio
bugs1334330
milestone54.0a1
Bug 1334330 - Part 6: stylo: Use GenericSpecifiedValue abstraction for table elements; r?emilio MozReview-Commit-ID: 6wo4iw4zEWP
dom/html/HTMLTableCaptionElement.cpp
dom/html/HTMLTableCellElement.cpp
dom/html/HTMLTableColElement.cpp
dom/html/HTMLTableElement.cpp
dom/html/HTMLTableRowElement.cpp
dom/html/HTMLTableSectionElement.cpp
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
layout/style/GenericSpecifiedValues.h
layout/style/nsRuleData.h
--- a/dom/html/HTMLTableCaptionElement.cpp
+++ b/dom/html/HTMLTableCaptionElement.cpp
@@ -46,29 +46,27 @@ HTMLTableCaptionElement::ParseAttribute(
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableCaptionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               GenericSpecifiedValues* aGenericData)
+                                               GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
-    nsCSSValue* captionSide = aData->ValueForCaptionSide();
-    if (captionSide->GetUnit() == eCSSUnit_Null) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(TableBorder))) {
+    if (!aData->PropertyIsSet(eCSSProperty_caption_side)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
       if (value && value->Type() == nsAttrValue::eEnum)
-        captionSide->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
+        aData->SetKeywordValue(eCSSProperty_caption_side, value->GetEnumValue());
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCaptionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { nullptr }
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -435,88 +435,68 @@ HTMLTableCellElement::ParseAttribute(int
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                            GenericSpecifiedValues* aGenericData)
+                                            GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
     // width: value
-    nsCSSValue* width = aData->ValueForWidth();
-    if (width->GetUnit() == eCSSUnit_Null) {
+    if (!aData->PropertyIsSet(eCSSProperty_width)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
       if (value && value->Type() == nsAttrValue::eInteger) {
         if (value->GetIntegerValue() > 0)
-          width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
+          aData->SetPixelValue(eCSSProperty_width, (float)value->GetIntegerValue());
         // else 0 implies auto for compatibility.
       }
       else if (value && value->Type() == nsAttrValue::ePercent) {
         if (value->GetPercentValue() > 0.0f)
-          width->SetPercentValue(value->GetPercentValue());
+          aData->SetPercentValue(eCSSProperty_width, value->GetPercentValue());
         // else 0 implies auto for compatibility
       }
     }
-
     // height: value
-    nsCSSValue* height = aData->ValueForHeight();
-    if (height->GetUnit() == eCSSUnit_Null) {
+    if (!aData->PropertyIsSet(eCSSProperty_height)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger) {
         if (value->GetIntegerValue() > 0)
-          height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+          aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
         // else 0 implies auto for compatibility.
       }
       else if (value && value->Type() == nsAttrValue::ePercent) {
         if (value->GetPercentValue() > 0.0f)
-          height->SetPercentValue(value->GetPercentValue());
+          aData->SetPercentValue(eCSSProperty_height, value->GetPercentValue());
         // else 0 implies auto for compatibility
       }
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
-    nsCSSValue* textAlign = aData->ValueForTextAlign();
-    if (textAlign->GetUnit() == eCSSUnit_Null) {
-      // align: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-
-    nsCSSValue* whiteSpace = aData->ValueForWhiteSpace();
-    if (whiteSpace->GetUnit() == eCSSUnit_Null) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
+    if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
       // nowrap: enum
       if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
         // See if our width is not a nonzero integer width.
         const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-        nsCompatibility mode = aData->mPresContext->CompatibilityMode();
+        nsCompatibility mode = aData->PresContext()->CompatibilityMode();
         if (!value || value->Type() != nsAttrValue::eInteger ||
             value->GetIntegerValue() == 0 ||
             eCompatibility_NavQuirks != mode) {
-          whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_NOWRAP, eCSSUnit_Enumerated);
+          aData->SetKeywordValue(eCSSProperty_white_space, NS_STYLE_WHITESPACE_NOWRAP);
         }
       }
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
-    nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
-    if (verticalAlign->GetUnit() == eCSSUnit_Null) {
-      // valign: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-  
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCellElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align }, 
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableColElement.cpp
+++ b/dom/html/HTMLTableColElement.cpp
@@ -59,76 +59,38 @@ HTMLTableColElement::ParseAttribute(int3
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableColElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           GenericSpecifiedValues* aGenericData)
+                                           GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
-    nsCSSValue *span = aData->ValueForSpan();
-    if (span->GetUnit() == eCSSUnit_Null) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Table))) {
+    if (!aData->PropertyIsSet(eCSSProperty__x_span)) {
       // span: int
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::span);
       if (value && value->Type() == nsAttrValue::eInteger) {
         int32_t val = value->GetIntegerValue();
         // Note: Do NOT use this code for table cells!  The value "0"
         // means something special for colspan and rowspan, but for <col
         // span> and <colgroup span> it's just disallowed.
         if (val > 0) {
-          span->SetIntValue(value->GetIntegerValue(), eCSSUnit_Integer);
+          aData->SetIntValue(eCSSProperty__x_span, value->GetIntegerValue());
         }
       }
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
-    nsCSSValue* width = aData->ValueForWidth();
-    if (width->GetUnit() == eCSSUnit_Null) {
-      // width
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-      if (value) {
-        switch (value->Type()) {
-        case nsAttrValue::ePercent: {
-          width->SetPercentValue(value->GetPercentValue());
-          break;
-        }
-        case nsAttrValue::eInteger: {
-          width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-          break;
-        }
-        default:
-          break;
-        }
-      }
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
-    nsCSSValue* textAlign = aData->ValueForTextAlign();
-    if (textAlign->GetUnit() == eCSSUnit_Null) {
-      // align: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
-    nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
-    if (verticalAlign->GetUnit() == eCSSUnit_Null) {
-      // valign: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableColElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::align },
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -702,153 +702,102 @@ HTMLTableElement::ParseAttribute(int32_t
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 
 
 void
 HTMLTableElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aGenericData)
+                                        GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
   // XXX Bug 211636:  This function is used by a single style rule
   // that's used to match two different type of elements -- tables, and
   // table cells.  (nsHTMLTableCellElement overrides
   // WalkContentStyleRules so that this happens.)  This violates the
   // nsIStyleRule contract, since it's the same style rule object doing
   // the mapping in two different ways.  It's also incorrect since it's
   // testing the display type of the style context rather than checking
   // which *element* it's matching (style rules should not stop matching
   // when the display type is changed).
 
-  nsPresContext* presContext = aData->mPresContext;
+  nsPresContext* presContext = aData->PresContext();
   nsCompatibility mode = presContext->CompatibilityMode();
 
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(TableBorder))) {
     // cellspacing
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
-    nsCSSValue* borderSpacing = aData->ValueForBorderSpacing();
     if (value && value->Type() == nsAttrValue::eInteger &&
-        borderSpacing->GetUnit() == eCSSUnit_Null) {
-      borderSpacing->
-        SetFloatValue(float(value->GetIntegerValue()), eCSSUnit_Pixel);
+        !aData->PropertyIsSet(eCSSProperty_border_spacing)) {
+      aData->SetPixelValue(eCSSProperty_border_spacing, float(value->GetIntegerValue()));
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Margin))) {
     // align; Check for enumerated type (it may be another type if
     // illegal)
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
 
     if (value && value->Type() == nsAttrValue::eEnum) {
       if (value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_CENTER ||
           value->GetEnumValue() == NS_STYLE_TEXT_ALIGN_MOZ_CENTER) {
-        nsCSSValue* marginLeft = aData->ValueForMarginLeft();
-        if (marginLeft->GetUnit() == eCSSUnit_Null)
-          marginLeft->SetAutoValue();
-        nsCSSValue* marginRight = aData->ValueForMarginRight();
-        if (marginRight->GetUnit() == eCSSUnit_Null)
-          marginRight->SetAutoValue();
+        aData->SetAutoValueIfUnset(eCSSProperty_margin_left);
+        aData->SetAutoValueIfUnset(eCSSProperty_margin_right);
       }
     }
 
     // hspace is mapped into left and right margin,
     // vspace is mapped into top and bottom margins
     // - *** Quirks Mode only ***
     if (eCompatibility_NavQuirks == mode) {
       value = aAttributes->GetAttr(nsGkAtoms::hspace);
 
       if (value && value->Type() == nsAttrValue::eInteger) {
-        nsCSSValue* marginLeft = aData->ValueForMarginLeft();
-        if (marginLeft->GetUnit() == eCSSUnit_Null)
-          marginLeft->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        nsCSSValue* marginRight = aData->ValueForMarginRight();
-        if (marginRight->GetUnit() == eCSSUnit_Null)
-          marginRight->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+        aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)value->GetIntegerValue());
+        aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)value->GetIntegerValue());
       }
 
       value = aAttributes->GetAttr(nsGkAtoms::vspace);
 
       if (value && value->Type() == nsAttrValue::eInteger) {
-        nsCSSValue* marginTop = aData->ValueForMarginTop();
-        if (marginTop->GetUnit() == eCSSUnit_Null)
-          marginTop->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-        nsCSSValue* marginBottom = aData->ValueForMarginBottom();
-        if (marginBottom->GetUnit() == eCSSUnit_Null)
-          marginBottom->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+        aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)value->GetIntegerValue());
+        aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)value->GetIntegerValue());
       }
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
-    // width: value
-    nsCSSValue* width = aData->ValueForWidth();
-    if (width->GetUnit() == eCSSUnit_Null) {
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-      if (value && value->Type() == nsAttrValue::eInteger)
-        width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-      else if (value && value->Type() == nsAttrValue::ePercent)
-        width->SetPercentValue(value->GetPercentValue());
-    }
-
-    // height: value
-    nsCSSValue* height = aData->ValueForHeight();
-    if (height->GetUnit() == eCSSUnit_Null) {
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
-      if (value && value->Type() == nsAttrValue::eInteger)
-        height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-      else if (value && value->Type() == nsAttrValue::ePercent)
-        height->SetPercentValue(value->GetPercentValue());
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))) {
     // bordercolor
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
     nscolor color;
     if (value && presContext->UseDocumentColors() &&
         value->GetColorValue(color)) {
-      nsCSSValue* borderLeftColor = aData->ValueForBorderLeftColor();
-      if (borderLeftColor->GetUnit() == eCSSUnit_Null)
-        borderLeftColor->SetColorValue(color);
-      nsCSSValue* borderRightColor = aData->ValueForBorderRightColor();
-      if (borderRightColor->GetUnit() == eCSSUnit_Null)
-        borderRightColor->SetColorValue(color);
-      nsCSSValue* borderTopColor = aData->ValueForBorderTopColor();
-      if (borderTopColor->GetUnit() == eCSSUnit_Null)
-        borderTopColor->SetColorValue(color);
-      nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
-      if (borderBottomColor->GetUnit() == eCSSUnit_Null)
-        borderBottomColor->SetColorValue(color);
+      aData->SetColorValueIfUnset(eCSSProperty_border_top_color, color);
+      aData->SetColorValueIfUnset(eCSSProperty_border_left_color, color);
+      aData->SetColorValueIfUnset(eCSSProperty_border_bottom_color, color);
+      aData->SetColorValueIfUnset(eCSSProperty_border_right_color, color);
     }
 
     // border
     const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
     if (borderValue) {
       // border = 1 pixel default
       int32_t borderThickness = 1;
 
       if (borderValue->Type() == nsAttrValue::eInteger)
         borderThickness = borderValue->GetIntegerValue();
 
       // by default, set all border sides to the specified width
-      nsCSSValue* borderLeftWidth = aData->ValueForBorderLeftWidth();
-      if (borderLeftWidth->GetUnit() == eCSSUnit_Null)
-        borderLeftWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-      nsCSSValue* borderRightWidth = aData->ValueForBorderRightWidth();
-      if (borderRightWidth->GetUnit() == eCSSUnit_Null)
-        borderRightWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-      nsCSSValue* borderTopWidth = aData->ValueForBorderTopWidth();
-      if (borderTopWidth->GetUnit() == eCSSUnit_Null)
-        borderTopWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
-      nsCSSValue* borderBottomWidth = aData->ValueForBorderBottomWidth();
-      if (borderBottomWidth->GetUnit() == eCSSUnit_Null)
-        borderBottomWidth->SetFloatValue((float)borderThickness, eCSSUnit_Pixel);
+      aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)borderThickness);
+      aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)borderThickness);
+      aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)borderThickness);
+      aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)borderThickness);
     }
   }
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::cellpadding },
     { &nsGkAtoms::cellspacing },
@@ -876,45 +825,29 @@ HTMLTableElement::IsAttributeMapped(cons
 nsMapRuleToAttributesFunc
 HTMLTableElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 static void
 MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData)
+                                    GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Padding)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Padding))) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellpadding);
     if (value && value->Type() == nsAttrValue::eInteger) {
       // We have cellpadding.  This will override our padding values if we
       // don't have any set.
-      nsCSSValue padVal(float(value->GetIntegerValue()), eCSSUnit_Pixel);
-
-      nsCSSValue* paddingLeft = aData->ValueForPaddingLeft();
-      if (paddingLeft->GetUnit() == eCSSUnit_Null) {
-        *paddingLeft = padVal;
-      }
+      float pad = float(value->GetIntegerValue());
 
-      nsCSSValue* paddingRight = aData->ValueForPaddingRight();
-      if (paddingRight->GetUnit() == eCSSUnit_Null) {
-        *paddingRight = padVal;
-      }
-
-      nsCSSValue* paddingTop = aData->ValueForPaddingTop();
-      if (paddingTop->GetUnit() == eCSSUnit_Null) {
-        *paddingTop = padVal;
-      }
-
-      nsCSSValue* paddingBottom = aData->ValueForPaddingBottom();
-      if (paddingBottom->GetUnit() == eCSSUnit_Null) {
-        *paddingBottom = padVal;
-      }
+      aData->SetPixelValueIfUnset(eCSSProperty_padding_top, pad);
+      aData->SetPixelValueIfUnset(eCSSProperty_padding_right, pad);
+      aData->SetPixelValueIfUnset(eCSSProperty_padding_bottom, pad);
+      aData->SetPixelValueIfUnset(eCSSProperty_padding_left, pad);
     }
   }
 }
 
 nsMappedAttributes*
 HTMLTableElement::GetAttributesMappedForCell()
 {
   if (mTableInheritedAttributes) {
--- a/dom/html/HTMLTableRowElement.cpp
+++ b/dom/html/HTMLTableRowElement.cpp
@@ -259,51 +259,23 @@ HTMLTableRowElement::ParseAttribute(int3
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           GenericSpecifiedValues* aGenericData)
+                                           GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
-    // height: value
-    nsCSSValue* height = aData->ValueForHeight();
-    if (height->GetUnit() == eCSSUnit_Null) {
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
-      if (value && value->Type() == nsAttrValue::eInteger)
-        height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
-      else if (value && value->Type() == nsAttrValue::ePercent)
-        height->SetPercentValue(value->GetPercentValue());
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
-    nsCSSValue* textAlign = aData->ValueForTextAlign();
-    if (textAlign->GetUnit() == eCSSUnit_Null) {
-      // align: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
-    nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
-    if (verticalAlign->GetUnit() == eCSSUnit_Null) {
-      // valign: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableRowElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign }, 
--- a/dom/html/HTMLTableSectionElement.cpp
+++ b/dom/html/HTMLTableSectionElement.cpp
@@ -162,49 +162,30 @@ HTMLTableSectionElement::ParseAttribute(
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableSectionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               GenericSpecifiedValues* aGenericData)
+                                               GenericSpecifiedValues* aData)
 {
-  nsRuleData* aData = aGenericData->AsRuleData();
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
     // height: value
-    nsCSSValue* height = aData->ValueForHeight();
-    if (height->GetUnit() == eCSSUnit_Null) {
+    if (!aData->PropertyIsSet(eCSSProperty_height)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
-        height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
+        aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
     }
   }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
-    nsCSSValue* textAlign = aData->ValueForTextAlign();
-    if (textAlign->GetUnit() == eCSSUnit_Null) {
-      // align: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        textAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
-    nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
-    if (verticalAlign->GetUnit() == eCSSUnit_Null) {
-      // valign: enum
-      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
-      if (value && value->Type() == nsAttrValue::eEnum)
-        verticalAlign->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
-    }
-  }
-
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1368,16 +1368,29 @@ nsGenericHTMLElement::MapDivAlignAttribu
       // align: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
       if (value && value->Type() == nsAttrValue::eEnum)
         aData->SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
     }
   }
 }
 
+void
+nsGenericHTMLElement::MapVAlignAttributeInto(const nsMappedAttributes* aAttributes,
+                                             GenericSpecifiedValues* aData)
+{
+  if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
+    if (!aData->PropertyIsSet(eCSSProperty_vertical_align)) {
+      // align: enum
+      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::valign);
+      if (value && value->Type() == nsAttrValue::eEnum)
+        aData->SetKeywordValue(eCSSProperty_vertical_align, value->GetEnumValue());
+    }
+  }
+}
 
 void
 nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
                                                   GenericSpecifiedValues* aData)
 {
   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Margin)))
     return;
 
@@ -1412,48 +1425,65 @@ nsGenericHTMLElement::MapImageMarginAttr
                                     value->GetPercentValue());
       aData->SetPercentValueIfUnset(eCSSProperty_margin_bottom,
                                     value->GetPercentValue());
     }
   }
 }
 
 void
-nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
-                                                 GenericSpecifiedValues* aData)
+nsGenericHTMLElement::MapWidthAttributeInto(const nsMappedAttributes* aAttributes,
+                                            GenericSpecifiedValues* aData)
 {
-  if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position)))
+  if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
     return;
+  }
 
   // width: value
   if (!aData->PropertyIsSet(eCSSProperty_width)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
     if (value && value->Type() == nsAttrValue::eInteger) {
       aData->SetPixelValue(eCSSProperty_width,
                            (float)value->GetIntegerValue());
     } else if (value && value->Type() == nsAttrValue::ePercent) {
       aData->SetPercentValue(eCSSProperty_width,
                              value->GetPercentValue());
     }
   }
+}
+
+void
+nsGenericHTMLElement::MapHeightAttributeInto(const nsMappedAttributes* aAttributes,
+                                             GenericSpecifiedValues* aData)
+{
+  if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position)))
+    return;
 
   // height: value
   if (!aData->PropertyIsSet(eCSSProperty_height)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
     if (value && value->Type() == nsAttrValue::eInteger) {
       aData->SetPixelValue(eCSSProperty_height,
                            (float)value->GetIntegerValue());
     } else if (value && value->Type() == nsAttrValue::ePercent) {
       aData->SetPercentValue(eCSSProperty_height,
                              value->GetPercentValue());
     }
   }
 }
 
 void
+nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
+                                                 GenericSpecifiedValues* aData)
+{
+  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
+}
+
+void
 nsGenericHTMLElement::MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
                                                   GenericSpecifiedValues* aData)
 {
   if (!(aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))))
     return;
 
   // border: pixels
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -687,17 +687,28 @@ public:
    * Helper to map the align attribute into a style struct for things
    * like <div>, <h1>, etc.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                       GenericSpecifiedValues* aGenericData);
+                                    GenericSpecifiedValues* aGenericData);
+
+  /**
+   * Helper to map the valign attribute into a style struct for things
+   * like <col>, <tr>, <section>, etc.
+   *
+   * @param aAttributes the list of attributes to map
+   * @param aData the returned rule data [INOUT]
+   * @see GetAttributeMappingFunction
+   */
+  static void MapVAlignAttributeInto(const nsMappedAttributes* aAttributes,
+                                    GenericSpecifiedValues* aGenericData);
 
   /**
    * Helper to map the image border attribute into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
@@ -716,16 +727,35 @@ public:
    * Helper to map the image position attribute into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
                                          GenericSpecifiedValues* aGenericData);
+
+  /**
+   * Helper to map `width` attribute into a style struct.
+   *
+   * @param aAttributes the list of attributes to map
+   * @param aData the returned rule data [INOUT]
+   * @see GetAttributeMappingFunction
+   */
+  static void MapWidthAttributeInto(const nsMappedAttributes* aAttributes,
+                                    GenericSpecifiedValues* aGenericData);
+  /**
+   * Helper to map `height` attribute into a style struct.
+   *
+   * @param aAttributes the list of attributes to map
+   * @param aData the returned rule data [INOUT]
+   * @see GetAttributeMappingFunction
+   */
+  static void MapHeightAttributeInto(const nsMappedAttributes* aAttributes,
+                                     GenericSpecifiedValues* aGenericData);
   /**
    * Helper to map the background attribute
    * into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
--- a/layout/style/GenericSpecifiedValues.h
+++ b/layout/style/GenericSpecifiedValues.h
@@ -51,27 +51,34 @@ public:
     template<typename T,
              typename = typename std::enable_if<std::is_enum<T>::value>::type>
     void SetKeywordValueIfUnset(nsCSSPropertyID aId, T aValue) {
         static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
                       "aValue must be an enum that fits within 32 bits");
         SetKeywordValueIfUnset(aId, static_cast<int32_t>(aValue));
     }
 
+    // Set a property to an integer value
+    virtual void SetIntValue(nsCSSPropertyID aId, int32_t aValue) = 0;
     // Set a property to a pixel value
     virtual void SetPixelValue(nsCSSPropertyID aId, float aValue) = 0;
     virtual void SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue) = 0;
 
     // Set a property to a percent value
     virtual void SetPercentValue(nsCSSPropertyID aId, float aValue) = 0;
     virtual void SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue) = 0;
 
+    // Set a property to `auto`
+    virtual void SetAutoValue(nsCSSPropertyID aId) = 0;
+    virtual void SetAutoValueIfUnset(nsCSSPropertyID aId) = 0;
+
     // Set a property to `currentcolor`
     virtual void SetCurrentColor(nsCSSPropertyID aId) = 0;
     virtual void SetCurrentColorIfUnset(nsCSSPropertyID aId) = 0;
 
     // Set a property to an RGBA nscolor value
     virtual void SetColorValue(nsCSSPropertyID aId, nscolor aValue) = 0;
+    virtual void SetColorValueIfUnset(nsCSSPropertyID aId, nscolor aValue) = 0;
 
     virtual nsRuleData* AsRuleData() = 0;
 };
 
-#endif // mozilla_GenericSpecifiedValues_h
\ No newline at end of file
+#endif // mozilla_GenericSpecifiedValues_h
--- a/layout/style/nsRuleData.h
+++ b/layout/style/nsRuleData.h
@@ -153,16 +153,22 @@ struct nsRuleData final: GenericSpecifie
 
   void SetKeywordValueIfUnset(nsCSSPropertyID aId,
                               int32_t aValue) override {
     if (!PropertyIsSet(aId)) {
       SetKeywordValue(aId, aValue);
     }
   }
 
+
+  void SetIntValue(nsCSSPropertyID aId,
+                   int32_t aValue) override {
+    ValueFor(aId)->SetIntValue(aValue, eCSSUnit_Integer);
+  }
+
   void SetPixelValue(nsCSSPropertyID aId,
                      float aValue) override {
     ValueFor(aId)->SetFloatValue(aValue, eCSSUnit_Pixel);
   }
 
   void SetPixelValueIfUnset(nsCSSPropertyID aId,
                             float aValue) override {
     if (!PropertyIsSet(aId)) {
@@ -170,16 +176,26 @@ struct nsRuleData final: GenericSpecifie
     }
   }
 
   void SetPercentValue(nsCSSPropertyID aId,
                        float aValue) override {
     ValueFor(aId)->SetPercentValue(aValue);
   }
 
+  void SetAutoValue(nsCSSPropertyID aId) override {
+    ValueFor(aId)->SetAutoValue();
+  }
+
+  void SetAutoValueIfUnset(nsCSSPropertyID aId) override {
+    if (!PropertyIsSet(aId)) {
+      SetAutoValue(aId);
+    }
+  }
+
   void SetPercentValueIfUnset(nsCSSPropertyID aId,
                               float aValue) override {
     if (!PropertyIsSet(aId)) {
       SetPercentValue(aId, aValue);
     }
   }
 
   void SetCurrentColor(nsCSSPropertyID aId) override {
@@ -192,16 +208,23 @@ struct nsRuleData final: GenericSpecifie
     }
   }
 
   void SetColorValue(nsCSSPropertyID aId,
                      nscolor aValue) override {
     ValueFor(aId)->SetColorValue(aValue);
   }
 
+  void SetColorValueIfUnset(nsCSSPropertyID aId,
+                            nscolor aValue) override {
+    if (!PropertyIsSet(aId)) {
+      SetColorValue(aId, aValue);
+    }
+  }
+
   nsRuleData* AsRuleData() override {
     return this;
   }
 
 private:
   inline size_t GetPoisonOffset();
 
 };