Bug 1334330 - Part 1: stylo: Abstractify nsMappedAttributes to work on arbitrary containers of specified value data; r?emilio draft
authorManish Goregaokar <manishearth@gmail.com>
Thu, 26 Jan 2017 13:39:13 -0800
changeset 480656 d3474f8a1d82af7c5c3e74f61637a2548245e266
parent 480619 5e17f9181c6cb0968966280d1c1d96e725702af1
child 480657 aa2347ccb61cd1276d3fa063e707b5a1c8f19041
push id44619
push userbmo:manishearth@gmail.com
push dateWed, 08 Feb 2017 19:34:01 +0000
reviewersemilio
bugs1334330
milestone54.0a1
Bug 1334330 - Part 1: stylo: Abstractify nsMappedAttributes to work on arbitrary containers of specified value data; r?emilio MozReview-Commit-ID: BSM4TC9RKot
dom/base/nsMappedAttributeElement.cpp
dom/base/nsMappedAttributeElement.h
dom/base/nsMappedAttributes.cpp
dom/html/HTMLBRElement.cpp
dom/html/HTMLBRElement.h
dom/html/HTMLBodyElement.cpp
dom/html/HTMLBodyElement.h
dom/html/HTMLDivElement.cpp
dom/html/HTMLDivElement.h
dom/html/HTMLFontElement.cpp
dom/html/HTMLFontElement.h
dom/html/HTMLFrameElement.h
dom/html/HTMLHRElement.cpp
dom/html/HTMLHRElement.h
dom/html/HTMLHeadingElement.cpp
dom/html/HTMLHeadingElement.h
dom/html/HTMLIFrameElement.cpp
dom/html/HTMLIFrameElement.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLImageElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLLIElement.cpp
dom/html/HTMLLIElement.h
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
dom/html/HTMLParagraphElement.cpp
dom/html/HTMLParagraphElement.h
dom/html/HTMLPreElement.cpp
dom/html/HTMLPreElement.h
dom/html/HTMLSelectElement.cpp
dom/html/HTMLSelectElement.h
dom/html/HTMLSharedElement.cpp
dom/html/HTMLSharedListElement.cpp
dom/html/HTMLSharedListElement.h
dom/html/HTMLSharedObjectElement.cpp
dom/html/HTMLSharedObjectElement.h
dom/html/HTMLTableCaptionElement.cpp
dom/html/HTMLTableCaptionElement.h
dom/html/HTMLTableCellElement.cpp
dom/html/HTMLTableCellElement.h
dom/html/HTMLTableColElement.cpp
dom/html/HTMLTableColElement.h
dom/html/HTMLTableElement.cpp
dom/html/HTMLTableElement.h
dom/html/HTMLTableRowElement.cpp
dom/html/HTMLTableRowElement.h
dom/html/HTMLTableSectionElement.cpp
dom/html/HTMLTableSectionElement.h
dom/html/HTMLTextAreaElement.cpp
dom/html/HTMLTextAreaElement.h
dom/html/HTMLVideoElement.cpp
dom/html/HTMLVideoElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/mathml/nsMathMLElement.cpp
dom/mathml/nsMathMLElement.h
layout/style/GenericSpecifiedValues.h
layout/style/moz.build
layout/style/nsRuleData.h
--- a/dom/base/nsMappedAttributeElement.cpp
+++ b/dom/base/nsMappedAttributeElement.cpp
@@ -32,11 +32,11 @@ nsMappedAttributeElement::SetMappedAttri
 nsMapRuleToAttributesFunc
 nsMappedAttributeElement::GetAttributeMappingFunction() const
 {
   return &MapNoAttributesInto;
 }
 
 void
 nsMappedAttributeElement::MapNoAttributesInto(const nsMappedAttributes* aAttributes,
-                                              nsRuleData* aData)
+                                              GenericSpecifiedValues* aGenericData)
 {
 }
--- a/dom/base/nsMappedAttributeElement.h
+++ b/dom/base/nsMappedAttributeElement.h
@@ -8,40 +8,41 @@
  * nsMappedAttributeElement is the base for elements supporting style mapped
  * attributes via nsMappedAttributes (HTML and MathML).
  */
 
 #ifndef NS_MAPPEDATTRIBUTEELEMENT_H_
 #define NS_MAPPEDATTRIBUTEELEMENT_H_
 
 #include "mozilla/Attributes.h"
+#include "mozilla/GenericSpecifiedValues.h"
 #include "nsStyledElement.h"
 
 class nsMappedAttributes;
 struct nsRuleData;
 
 typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes, 
-                                          nsRuleData* aData);
+                                          GenericSpecifiedValues* aData);
 
 typedef nsStyledElement nsMappedAttributeElementBase;
 
 class nsMappedAttributeElement : public nsMappedAttributeElementBase
 {
 
 protected:
 
   explicit nsMappedAttributeElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsMappedAttributeElementBase(aNodeInfo)
   {}
 
 public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   static void MapNoAttributesInto(const nsMappedAttributes* aAttributes, 
-                                  nsRuleData* aRuleData);
+                                  GenericSpecifiedValues* aGenericData);
 
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
   virtual bool SetMappedAttribute(nsIDocument* aDocument,
                                     nsIAtom* aName,
                                     nsAttrValue& aValue,
                                     nsresult* aRetval) override;
 };
 
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -6,18 +6,19 @@
 
 /*
  * A unique per-element set of attributes that is used as an
  * nsIStyleRule; used to implement presentational attributes.
  */
 
 #include "nsMappedAttributes.h"
 #include "nsHTMLStyleSheet.h"
+#include "nsRuleData.h"
 #include "nsRuleWalker.h"
-#include "nsRuleData.h"
+#include "mozilla/GenericSpecifiedValues.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ServoDeclarationBlock.h"
 
 using namespace mozilla;
 
 nsMappedAttributes::nsMappedAttributes(nsHTMLStyleSheet* aSheet,
                                        nsMapRuleToAttributesFunc aMapRuleFunc)
--- a/dom/html/HTMLBRElement.cpp
+++ b/dom/html/HTMLBRElement.cpp
@@ -48,28 +48,29 @@ HTMLBRElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     nsRuleData* aData)
+                                     GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     nsCSSValue* clear = aData->ValueForClear();
     if (clear->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::clear);
       if (value && value->Type() == nsAttrValue::eEnum)
         clear->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLBRElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::clear },
     { nullptr }
--- a/dom/html/HTMLBRElement.h
+++ b/dom/html/HTMLBRElement.h
@@ -41,16 +41,16 @@ public:
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   virtual ~HTMLBRElement();
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -355,18 +355,19 @@ HTMLBodyElement::UnbindFromTree(bool aDe
     mContentStyleRule = nullptr;
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);  
 }
 
 void
 HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                       nsRuleData* aData)
+                                       GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     // When display if first asked for, go ahead and get our colors set up.
     nsIPresShell *presShell = aData->mPresContext->GetPresShell();
     if (presShell) {
       nsIDocument *doc = presShell->GetDocument();
       if (doc) {
         nsHTMLStyleSheet* styleSheet = doc->GetAttributeStyleSheet();
         if (styleSheet) {
@@ -398,18 +399,18 @@ HTMLBodyElement::MapAttributesIntoRule(c
       // color: color
       nscolor color;
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::text);
       if (value && value->GetColorValue(color))
         colorValue->SetColorValue(color);
     }
   }
 
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 nsMapRuleToAttributesFunc
 HTMLBodyElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -139,15 +139,15 @@ protected:
   virtual ~HTMLBodyElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   RefPtr<BodyRule> mContentStyleRule;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLBodyElement_h___ */
--- a/dom/html/HTMLDivElement.cpp
+++ b/dom/html/HTMLDivElement.cpp
@@ -55,29 +55,31 @@ HTMLDivElement::ParseAttribute(int32_t a
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLDivElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                      nsRuleData* aData)
+                                      GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 static void
-MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBGColorInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapBGColorInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLDivElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   if (mNodeInfo->Equals(nsGkAtoms::div)) {
     static const MappedAttributeEntry* const map[] = {
       sDivAlignAttributeMap,
--- a/dom/html/HTMLDivElement.h
+++ b/dom/html/HTMLDivElement.h
@@ -39,15 +39,15 @@ public:
 
 protected:
   virtual ~HTMLDivElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLDivElement_h___ */
--- a/dom/html/HTMLFontElement.cpp
+++ b/dom/html/HTMLFontElement.cpp
@@ -50,18 +50,19 @@ HTMLFontElement::ParseAttribute(int32_t 
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLFontElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                       nsRuleData* aData)
+                                       GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
     // face: string list
     nsCSSValue* family = aData->ValueForFontFamily();
     if (family->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::face);
       if (value && value->Type() == nsAttrValue::eString &&
           !value->IsEmptyString()) {
         nsCSSParser parser;
@@ -103,17 +104,17 @@ HTMLFontElement::MapAttributesIntoRule(c
       int32_t newValue = NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
       if (decoration->GetUnit() == eCSSUnit_Enumerated) {
         newValue |= decoration->GetIntValue();
       }
       decoration->SetIntValue(newValue, eCSSUnit_Enumerated);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLFontElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::face },
     { &nsGkAtoms::size },
--- a/dom/html/HTMLFontElement.h
+++ b/dom/html/HTMLFontElement.h
@@ -55,15 +55,15 @@ public:
 
 protected:
   virtual ~HTMLFontElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLFontElement_h___ */
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -94,15 +94,15 @@ public:
 
 protected:
   virtual ~HTMLFrameElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLFrameElement_h
--- a/dom/html/HTMLHRElement.cpp
+++ b/dom/html/HTMLHRElement.cpp
@@ -62,18 +62,19 @@ HTMLHRElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     nsRuleData* aData)
+                                     GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   bool noshade = false;
 
   const nsAttrValue* colorValue = aAttributes->GetAttr(nsGkAtoms::color);
   nscolor color;
   bool colorIsSet = colorValue && colorValue->GetColorValue(color);
 
   if (aData->mSIDs & (NS_STYLE_INHERIT_BIT(Position) |
                       NS_STYLE_INHERIT_BIT(Border))) {
@@ -222,17 +223,17 @@ HTMLHRElement::MapAttributesIntoRule(con
     nsCSSValue* colorValue = aData->ValueForColor();
     if (colorIsSet &&
         colorValue->GetUnit() == eCSSUnit_Null &&
         aData->mPresContext->UseDocumentColors()) {
       colorValue->SetColorValue(color);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLHRElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::width },
--- a/dom/html/HTMLHRElement.h
+++ b/dom/html/HTMLHRElement.h
@@ -72,15 +72,15 @@ public:
 
 protected:
   virtual ~HTMLHRElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLHRElement_h
--- a/dom/html/HTMLHeadingElement.cpp
+++ b/dom/html/HTMLHeadingElement.cpp
@@ -41,20 +41,21 @@ HTMLHeadingElement::ParseAttribute(int32
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLHeadingElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                          nsRuleData* aData)
+                                          GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLHeadingElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sDivAlignAttributeMap,
     sCommonAttributeMap
--- a/dom/html/HTMLHeadingElement.h
+++ b/dom/html/HTMLHeadingElement.h
@@ -40,15 +40,15 @@ public:
 
 protected:
   virtual ~HTMLHeadingElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLHeadingElement_h
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -96,18 +96,19 @@ HTMLIFrameElement::ParseAttribute(int32_
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
                                                    aValue, aResult);
 }
 
 void
 HTMLIFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                         nsRuleData* aData)
+                                         GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
     // frameborder: 0 | 1 (| NO | YES in quirks mode)
     // If frameborder is 0 or No, set border to 0
     // else leave it as the value set in html.css
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::frameborder);
     if (value && value->Type() == nsAttrValue::eEnum) {
       int32_t frameborder = value->GetEnumValue();
       if (NS_STYLE_FRAME_0 == frameborder ||
@@ -145,18 +146,18 @@ HTMLIFrameElement::MapAttributesIntoRule
       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());
     }
   }
 
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLIFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::height },
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -193,17 +193,17 @@ public:
 
 protected:
   virtual ~HTMLIFrameElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 
   static const DOMTokenListSupportedToken sSupportedSandboxTokens[];
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -314,23 +314,24 @@ HTMLImageElement::ParseAttribute(int32_t
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
+                                        GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 nsChangeHint
 HTMLImageElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -356,17 +356,17 @@ protected:
 
   // Created when we're tracking responsive image state
   RefPtr<ResponsiveImageSelector> mResponsiveSelector;
 
 private:
   bool SourceElementMatches(nsIContent* aSourceNode);
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 
   bool mInDocResponsiveContent;
   RefPtr<ImageLoadTask> mPendingImageLoadTask;
 
   // Last URL that was attempted to load by this element.
   nsCOMPtr<nsIURI> mLastSelectedSource;
   // Last pixel density that was selected.
   double mCurrentDensity;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -5907,29 +5907,30 @@ HTMLInputElement::ParseAttribute(int32_t
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLInputElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
-{
+                                        GenericSpecifiedValues* aGenericData)
+{
+  nsRuleData* aData = aGenericData->AsRuleData();
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
   if (value && value->Type() == nsAttrValue::eEnum &&
       value->GetEnumValue() == NS_FORM_INPUT_IMAGE) {
-    nsGenericHTMLFormElementWithState::MapImageBorderAttributeInto(aAttributes, aData);
-    nsGenericHTMLFormElementWithState::MapImageMarginAttributeInto(aAttributes, aData);
-    nsGenericHTMLFormElementWithState::MapImageSizeAttributesInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageBorderAttributeInto(aAttributes, aGenericData);
+    nsGenericHTMLFormElementWithState::MapImageMarginAttributeInto(aAttributes, aGenericData);
+    nsGenericHTMLFormElementWithState::MapImageSizeAttributesInto(aAttributes, aGenericData);
     // Images treat align as "float"
-    nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
-  }
-
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aGenericData);
+  }
+
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 nsChangeHint
 HTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -1617,17 +1617,17 @@ protected:
   bool                     mIsDraggingRange     : 1;
   bool                     mNumberControlSpinnerIsSpinning : 1;
   bool                     mNumberControlSpinnerSpinsUp : 1;
   bool                     mPickerRunning : 1;
   bool                     mSelectionCached : 1;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 
   /**
    * Returns true if this input's type will fire a DOM "change" event when it
    * loses focus if its value has changed since it gained focus.
    */
   bool MayFireChangeOnBlur() const {
     return MayFireChangeOnBlur(mType);
   }
--- a/dom/html/HTMLLIElement.cpp
+++ b/dom/html/HTMLLIElement.cpp
@@ -67,29 +67,30 @@ HTMLLIElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLLIElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     nsRuleData* aData)
+                                     GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
     nsCSSValue* listStyleType = aData->ValueForListStyleType();
     if (listStyleType->GetUnit() == eCSSUnit_Null) {
       // type: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
       if (value && value->Type() == nsAttrValue::eEnum)
         listStyleType->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLLIElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::type },
     { nullptr },
--- a/dom/html/HTMLLIElement.h
+++ b/dom/html/HTMLLIElement.h
@@ -58,15 +58,15 @@ public:
 
 protected:
   virtual ~HTMLLIElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLLIElement_h
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -500,23 +500,23 @@ HTMLObjectElement::ParseAttribute(int32_
   }
 
   return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
                                                   aValue, aResult);
 }
 
 void
 HTMLObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                                         nsRuleData *aData)
+                                         GenericSpecifiedValues *aGenericData)
 {
-  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap,
     sImageMarginSizeAttributeMap,
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -264,17 +264,17 @@ private:
     return nsIContentPolicy::TYPE_INTERNAL_OBJECT;
   }
 
   virtual ~HTMLObjectElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 
   bool mIsDoneAddingChildren;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLObjectElement_h
--- a/dom/html/HTMLParagraphElement.cpp
+++ b/dom/html/HTMLParagraphElement.cpp
@@ -39,20 +39,21 @@ HTMLParagraphElement::ParseAttribute(int
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLParagraphElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                            nsRuleData* aData)
+                                            GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLParagraphElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sDivAlignAttributeMap,
     sCommonAttributeMap,
--- a/dom/html/HTMLParagraphElement.h
+++ b/dom/html/HTMLParagraphElement.h
@@ -48,15 +48,15 @@ public:
 
 protected:
   virtual ~HTMLParagraphElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLParagraphElement_h
--- a/dom/html/HTMLPreElement.cpp
+++ b/dom/html/HTMLPreElement.cpp
@@ -42,28 +42,29 @@ HTMLPreElement::ParseAttribute(int32_t a
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLPreElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                      nsRuleData* aData)
+                                      GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
     nsCSSValue* whiteSpace = aData->ValueForWhiteSpace();
     if (whiteSpace->GetUnit() == eCSSUnit_Null) {
       // wrap: empty
       if (aAttributes->GetAttr(nsGkAtoms::wrap))
         whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_PRE_WRAP, eCSSUnit_Enumerated);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLPreElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   if (!mNodeInfo->Equals(nsGkAtoms::pre)) {
     return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
   }
--- a/dom/html/HTMLPreElement.h
+++ b/dom/html/HTMLPreElement.h
@@ -52,15 +52,15 @@ public:
 
 protected:
   virtual ~HTMLPreElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLPreElement_h
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1407,20 +1407,21 @@ HTMLSelectElement::ParseAttribute(int32_
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLSelectElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                         nsRuleData* aData)
+                                         GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 nsChangeHint
 HTMLSelectElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                           int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -650,15 +650,15 @@ protected:
 
   /**
    * The live list of selected options.
   */
   RefPtr<nsContentList> mSelectedOptions;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSelectElement_h
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -108,34 +108,35 @@ HTMLSharedElement::ParseAttribute(int32_
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 static void
 DirectoryMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                               nsRuleData* aData)
+                               GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
     nsCSSValue* listStyleType = aData->ValueForListStyleType();
     if (listStyleType->GetUnit() == eCSSUnit_Null) {
       // type: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
       if (value) {
         if (value->Type() == nsAttrValue::eEnum) {
           listStyleType->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
         } else {
           listStyleType->SetIntValue(NS_STYLE_LIST_STYLE_DISC, eCSSUnit_Enumerated);
         }
       }
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   if (mNodeInfo->Equals(nsGkAtoms::dir)) {
     static const MappedAttributeEntry attributes[] = {
       { &nsGkAtoms::type },
--- a/dom/html/HTMLSharedListElement.cpp
+++ b/dom/html/HTMLSharedListElement.cpp
@@ -87,30 +87,31 @@ HTMLSharedListElement::ParseAttribute(in
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLSharedListElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                             nsRuleData* aData)
+                                             GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
     nsCSSValue* listStyleType = aData->ValueForListStyleType();
     if (listStyleType->GetUnit() == eCSSUnit_Null) {
       // type: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
       if (value && value->Type() == nsAttrValue::eEnum) {
         listStyleType->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
       }
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedListElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   if (mNodeInfo->Equals(nsGkAtoms::ol) ||
       mNodeInfo->Equals(nsGkAtoms::ul)) {
     static const MappedAttributeEntry attributes[] = {
--- a/dom/html/HTMLSharedListElement.h
+++ b/dom/html/HTMLSharedListElement.h
@@ -78,15 +78,15 @@ public:
 
 protected:
   virtual ~HTMLSharedListElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedListElement_h
--- a/dom/html/HTMLSharedObjectElement.cpp
+++ b/dom/html/HTMLSharedObjectElement.cpp
@@ -254,38 +254,38 @@ HTMLSharedObjectElement::ParseAttribute(
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 static void
 MapAttributesIntoRuleBase(const nsMappedAttributes *aAttributes,
-                          nsRuleData *aData)
+                          GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aGenericData);
 }
 
 static void
 MapAttributesIntoRuleExceptHidden(const nsMappedAttributes *aAttributes,
-                                  nsRuleData *aData)
+                                  GenericSpecifiedValues* aGenericData)
 {
-  MapAttributesIntoRuleBase(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aData);
+  MapAttributesIntoRuleBase(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aGenericData);
 }
 
 void
 HTMLSharedObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                                               nsRuleData *aData)
+                                               GenericSpecifiedValues* aGenericData)
 {
-  MapAttributesIntoRuleBase(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  MapAttributesIntoRuleBase(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap,
     sImageMarginSizeAttributeMap,
--- a/dom/html/HTMLSharedObjectElement.h
+++ b/dom/html/HTMLSharedObjectElement.h
@@ -214,17 +214,17 @@ private:
 
   // mIsDoneAddingChildren is only really used for <applet>.  This boolean is
   // always true for <embed>, per the documentation in nsIContent.h.
   bool mIsDoneAddingChildren;
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 
   /**
    * Decides whether we should load embed node content.
    *
    * If this is an embed node there are cases in which we should not try to load
    * the content:
    *
    * - If the embed node is the child of a media element
--- a/dom/html/HTMLTableCaptionElement.cpp
+++ b/dom/html/HTMLTableCaptionElement.cpp
@@ -46,28 +46,29 @@ HTMLTableCaptionElement::ParseAttribute(
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableCaptionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               nsRuleData* aData)
+                                               GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
     nsCSSValue* captionSide = aData->ValueForCaptionSide();
     if (captionSide->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
       if (value && value->Type() == nsAttrValue::eEnum)
         captionSide->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCaptionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { nullptr }
--- a/dom/html/HTMLTableCaptionElement.h
+++ b/dom/html/HTMLTableCaptionElement.h
@@ -41,15 +41,15 @@ public:
 
 protected:
   virtual ~HTMLTableCaptionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCaptionElement_h */
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -435,18 +435,19 @@ HTMLTableCellElement::ParseAttribute(int
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                            nsRuleData* aData)
+                                            GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   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) {
         if (value->GetIntegerValue() > 0)
           width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
@@ -504,18 +505,18 @@ HTMLTableCellElement::MapAttributesIntoR
     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, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCellElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align }, 
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -157,15 +157,15 @@ protected:
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   HTMLTableElement* GetTable() const;
 
   HTMLTableRowElement* GetRow() const;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCellElement_h */
--- a/dom/html/HTMLTableColElement.cpp
+++ b/dom/html/HTMLTableColElement.cpp
@@ -59,18 +59,19 @@ HTMLTableColElement::ParseAttribute(int3
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableColElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           nsRuleData* aData)
+                                           GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
     nsCSSValue *span = aData->ValueForSpan();
     if (span->GetUnit() == eCSSUnit_Null) {
       // 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"
@@ -117,17 +118,17 @@ HTMLTableColElement::MapAttributesIntoRu
     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, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableColElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::align },
--- a/dom/html/HTMLTableColElement.h
+++ b/dom/html/HTMLTableColElement.h
@@ -83,15 +83,15 @@ public:
 
 protected:
   virtual ~HTMLTableColElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableColElement_h */
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -702,18 +702,19 @@ HTMLTableElement::ParseAttribute(int32_t
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 
 
 void
 HTMLTableElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
+                                        GenericSpecifiedValues* aGenericData)
 {
+  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
@@ -836,18 +837,18 @@ HTMLTableElement::MapAttributesIntoRule(
       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);
     }
   }
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::cellpadding },
     { &nsGkAtoms::cellspacing },
@@ -875,18 +876,19 @@ HTMLTableElement::IsAttributeMapped(cons
 nsMapRuleToAttributesFunc
 HTMLTableElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 static void
 MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData)
+                                    GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & 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();
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -223,15 +223,15 @@ protected:
   // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
   // to be recalculated.
   nsMappedAttributes *mTableInheritedAttributes;
   void BuildInheritedAttributes();
   void ReleaseInheritedAttributes();
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableElement_h */
--- a/dom/html/HTMLTableRowElement.cpp
+++ b/dom/html/HTMLTableRowElement.cpp
@@ -259,18 +259,19 @@ HTMLTableRowElement::ParseAttribute(int3
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           nsRuleData* aData)
+                                           GenericSpecifiedValues* aGenericData)
 {
+  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)
@@ -291,18 +292,18 @@ HTMLTableRowElement::MapAttributesIntoRu
     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, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableRowElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign }, 
--- a/dom/html/HTMLTableRowElement.h
+++ b/dom/html/HTMLTableRowElement.h
@@ -96,15 +96,15 @@ protected:
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   HTMLTableSectionElement* GetSection() const;
   HTMLTableElement* GetTable() const;
   RefPtr<nsContentList> mCells;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/dom/html/HTMLTableSectionElement.cpp
+++ b/dom/html/HTMLTableSectionElement.cpp
@@ -162,18 +162,19 @@ HTMLTableSectionElement::ParseAttribute(
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTableSectionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               nsRuleData* aData)
+                                               GenericSpecifiedValues* aGenericData)
 {
+  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);
     }
@@ -192,18 +193,18 @@ HTMLTableSectionElement::MapAttributesIn
     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, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableSectionElement.h
+++ b/dom/html/HTMLTableSectionElement.h
@@ -78,15 +78,15 @@ protected:
   virtual ~HTMLTableSectionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   RefPtr<nsContentList> mRows;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableSectionElement_h */
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -431,32 +431,33 @@ HTMLTextAreaElement::ParseAttribute(int3
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
 HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           nsRuleData* aData)
+                                           GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
     // wrap=off
     nsCSSValue* whiteSpace = aData->ValueForWhiteSpace();
     if (whiteSpace->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
       if (value && value->Type() == nsAttrValue::eString &&
           value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
         whiteSpace->SetIntValue(NS_STYLE_WHITESPACE_PRE, eCSSUnit_Enumerated);
       }
     }
   }
 
-  nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aGenericData);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 nsChangeHint
 HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                             int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -389,16 +389,16 @@ protected:
    * Returns whether the current value is the empty string.
    *
    * @return whether the current value is the empty string.
    */
   bool IsValueEmpty() const;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -93,20 +93,21 @@ HTMLVideoElement::ParseAttribute(int32_t
    }
 
    return HTMLMediaElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                            aResult);
 }
 
 void
 HTMLVideoElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
+                                        GenericSpecifiedValues* aGenericData)
 {
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsRuleData* aData = aGenericData->AsRuleData();
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aGenericData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aGenericData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLVideoElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::height },
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -144,15 +144,15 @@ protected:
   virtual void WakeLockRelease() override;
   void UpdateScreenWakeLock();
 
   bool mUseScreenWakeLock;
   RefPtr<WakeLock> mScreenWakeLock;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    nsRuleData* aData);
+                                    GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLVideoElement_h
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1201,18 +1201,19 @@ nsGenericHTMLElement::ParseFrameborderVa
 bool
 nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
                                           nsAttrValue& aResult)
 {
   return aResult.ParseEnumValue(aString, kScrollingTable, false);
 }
 
 static inline void
-MapLangAttributeInto(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+MapLangAttributeInto(const nsMappedAttributes* aAttributes, GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & (NS_STYLE_INHERIT_BIT(Font) |
                         NS_STYLE_INHERIT_BIT(Text)))) {
     return;
   }
 
   const nsAttrValue* langValue = aAttributes->GetAttr(nsGkAtoms::lang);
   if (!langValue || langValue->Type() != nsAttrValue::eString) {
     return;
@@ -1242,18 +1243,19 @@ MapLangAttributeInto(const nsMappedAttri
   }
 }
 
 /**
  * Handle attributes common to all html elements
  */
 void
 nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(const nsMappedAttributes* aAttributes,
-                                                          nsRuleData* aData)
+                                                          GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(UserInterface)) {
     nsCSSValue* userModify = aData->ValueForUserModify();
     if (userModify->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value =
         aAttributes->GetAttr(nsGkAtoms::contenteditable);
       if (value) {
         if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
             value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
@@ -1266,18 +1268,19 @@ nsGenericHTMLElement::MapCommonAttribute
     }
   }
 
   MapLangAttributeInto(aAttributes, aData);
 }
 
 void
 nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
-                                              nsRuleData* aData)
+                                              GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   MapCommonAttributesIntoExceptHidden(aAttributes, aData);
 
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     nsCSSValue* display = aData->ValueForDisplay();
     if (display->GetUnit() == eCSSUnit_Null) {
       if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
         display->SetEnumValue(StyleDisplay::None);
       }
@@ -1330,65 +1333,68 @@ nsGenericHTMLElement::sBackgroundAttribu
 /* static */ const Element::MappedAttributeEntry
 nsGenericHTMLElement::sBackgroundColorAttributeMap[] = {
   { &nsGkAtoms::bgcolor },
   { nullptr }
 };
 
 void
 nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                                 nsRuleData* aRuleData)
+                                                 GenericSpecifiedValues* aGenericData)
 {
-  if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
+  nsRuleData* aData = aGenericData->AsRuleData();
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
     if (value && value->Type() == nsAttrValue::eEnum) {
       int32_t align = value->GetEnumValue();
-      nsCSSValue* cssFloat = aRuleData->ValueForFloat();
+      nsCSSValue* cssFloat = aData->ValueForFloat();
       if (cssFloat->GetUnit() == eCSSUnit_Null) {
         if (align == NS_STYLE_TEXT_ALIGN_LEFT) {
           cssFloat->SetEnumValue(StyleFloat::Left);
         } else if (align == NS_STYLE_TEXT_ALIGN_RIGHT) {
           cssFloat->SetEnumValue(StyleFloat::Right);
         }
       }
-      nsCSSValue* verticalAlign = aRuleData->ValueForVerticalAlign();
+      nsCSSValue* verticalAlign = aData->ValueForVerticalAlign();
       if (verticalAlign->GetUnit() == eCSSUnit_Null) {
         switch (align) {
         case NS_STYLE_TEXT_ALIGN_LEFT:
         case NS_STYLE_TEXT_ALIGN_RIGHT:
           break;
         default:
           verticalAlign->SetIntValue(align, eCSSUnit_Enumerated);
           break;
         }
       }
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                               nsRuleData* aRuleData)
+                                               GenericSpecifiedValues* aGenericData)
 {
-  if (aRuleData->mSIDs & NS_STYLE_INHERIT_BIT(Text)) {
-    nsCSSValue* textAlign = aRuleData->ValueForTextAlign();
+  nsRuleData* aData = aGenericData->AsRuleData();
+  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);
     }
   }
 }
 
 
 void
 nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
-                                                  nsRuleData* aData)
+                                                  GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)))
     return;
 
   const nsAttrValue* value;
 
   // hspace: value
   value = aAttributes->GetAttr(nsGkAtoms::hspace);
   if (value) {
@@ -1425,18 +1431,19 @@ nsGenericHTMLElement::MapImageMarginAttr
       if (bottom->GetUnit() == eCSSUnit_Null)
         *bottom = vval;
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
-                                                 nsRuleData* aData)
+                                                 GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)))
     return;
 
   // width: value
   nsCSSValue* width = aData->ValueForWidth();
   if (width->GetUnit() == eCSSUnit_Null) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
     if (value && value->Type() == nsAttrValue::eInteger)
@@ -1453,18 +1460,19 @@ nsGenericHTMLElement::MapImageSizeAttrib
       height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); 
     else if (value && value->Type() == nsAttrValue::ePercent)
       height->SetPercentValue(value->GetPercentValue());
   }
 }
 
 void
 nsGenericHTMLElement::MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
-                                                  nsRuleData* aData)
+                                                  GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)))
     return;
 
   // border: pixels
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
   if (!value)
     return;
   
@@ -1509,18 +1517,19 @@ nsGenericHTMLElement::MapImageBorderAttr
     borderRightColor->SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
   nsCSSValue* borderBottomColor = aData->ValueForBorderBottomColor();
   if (borderBottomColor->GetUnit() == eCSSUnit_Null)
     borderBottomColor->SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
 }
 
 void
 nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData)
+                                        GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
     return;
 
   nsPresContext* presContext = aData->mPresContext;
   nsCSSValue* backImage = aData->ValueForBackgroundImage();
   if (backImage->GetUnit() == eCSSUnit_Null &&
       presContext->UseDocumentColors()) {
     // background
@@ -1537,36 +1546,38 @@ nsGenericHTMLElement::MapBackgroundInto(
         list->mValue.SetImageValue(value->GetImageValue());
       }
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
-                                     nsRuleData* aData)
+                                     GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)))
     return;
 
   nsCSSValue* backColor = aData->ValueForBackgroundColor();
   if (backColor->GetUnit() == eCSSUnit_Null &&
       aData->mPresContext->UseDocumentColors()) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
     nscolor color;
     if (value && value->GetColorValue(color)) {
       backColor->SetColorValue(color);
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
-                                                  nsRuleData* aData)
+                                                  GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   MapBackgroundInto(aAttributes, aData);
   MapBGColorInto(aAttributes, aData);
 }
 
 //----------------------------------------------------------------------
 
 nsresult
 nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue)
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -649,26 +649,26 @@ public:
    * called by subclasses' attribute mapping functions.  Currently handles
    * dir, lang and hidden, could handle others.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapCommonAttributesInto(const nsMappedAttributes* aAttributes, 
-                                      nsRuleData* aRuleData);
+                                      GenericSpecifiedValues* aGenericData);
   /**
    * Same as MapCommonAttributesInto except that it does not handle hidden.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapCommonAttributesIntoExceptHidden(const nsMappedAttributes* aAttributes,
-                                                  nsRuleData* aRuleData);
+                                                  GenericSpecifiedValues* aGenericData);
 
   static const MappedAttributeEntry sCommonAttributeMap[];
   static const MappedAttributeEntry sImageMarginSizeAttributeMap[];
   static const MappedAttributeEntry sImageBorderAttributeMap[];
   static const MappedAttributeEntry sImageAlignAttributeMap[];
   static const MappedAttributeEntry sDivAlignAttributeMap[];
   static const MappedAttributeEntry sBackgroundAttributeMap[];
   static const MappedAttributeEntry sBackgroundColorAttributeMap[];
@@ -676,96 +676,96 @@ public:
   /**
    * Helper to map the align attribute into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                         nsRuleData* aData);
+                                         GenericSpecifiedValues* aGenericData);
 
   /**
    * 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,
-                                       nsRuleData* aData);
+                                       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
    */
   static void MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
-                                          nsRuleData* aData);
+                                          GenericSpecifiedValues* aGenericData);
   /**
    * Helper to map the image margin attribute into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
-                                          nsRuleData* aData);
+                                          GenericSpecifiedValues* aGenericData);
   /**
    * 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,
-                                         nsRuleData* aData);
+                                         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
    */
   static void MapBackgroundInto(const nsMappedAttributes* aAttributes,
-                                nsRuleData* aData);
+                                GenericSpecifiedValues* aGenericData);
   /**
    * Helper to map the bgcolor attribute
    * into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapBGColorInto(const nsMappedAttributes* aAttributes,
-                             nsRuleData* aData);
+                             GenericSpecifiedValues* aGenericData);
   /**
    * Helper to map the background attributes (currently background and bgcolor)
    * into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
-                                          nsRuleData* aData);
+                                          GenericSpecifiedValues* aGenericData);
   /**
    * Helper to map the scrolling attribute on FRAME and IFRAME
    * into a style struct.
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
-                                        nsRuleData* aData);
+                                        GenericSpecifiedValues* aGenericData);
   /**
    * Get the presentation context for this content node.
    * @return the presentation context
    */
   enum PresContextFor
   {
     eForComposedDoc,
     eForUncomposedDoc
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -482,18 +482,19 @@ nsMathMLElement::ParseNumericValue(const
   }
 
   aCSSValue.SetFloatValue(floatValue, cssUnit);
   return true;
 }
 
 void
 nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
-                                         nsRuleData* aData)
+                                         GenericSpecifiedValues* aGenericData)
 {
+  nsRuleData* aData = aGenericData->AsRuleData();
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
     // scriptsizemultiplier
     //
     // "Specifies the multiplier to be used to adjust font size due to changes
     // in scriptlevel.
     //
     // values: number
     // default: 0.71
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -67,17 +67,17 @@ public:
                                    uint32_t        aFlags);
 
   static bool ParseNumericValue(const nsString& aString,
                                 nsCSSValue&     aCSSValue,
                                 uint32_t        aFlags,
                                 nsIDocument*    aDocument);
 
   static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes, 
-                                      nsRuleData* aRuleData);
+                                      GenericSpecifiedValues* aGenericData);
   
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      mozilla::EventChainPostVisitor& aVisitor) override;
   nsresult Clone(mozilla::dom::NodeInfo*, nsINode**) const override;
   virtual mozilla::EventStates IntrinsicState() const override;
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
new file mode 100644
--- /dev/null
+++ b/layout/style/GenericSpecifiedValues.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Generic representation of a container of specified CSS values, which
+ * could potentially be Servo- or Gecko- format. Used to make attribute mapping
+ * code generic over style backends.
+ */
+
+#ifndef mozilla_GenericSpecifiedValues_h
+#define mozilla_GenericSpecifiedValues_h
+
+#include "nsCSSProps.h"
+#include "nsCSSValue.h"
+#include "nsPresContext.h"
+
+struct nsRuleData;
+
+// This provides a common interface for attribute mappers (MapAttributesIntoRule)
+// to use regardless of the style backend. If the style backend is Gecko,
+// this will contain an nsRuleData. If it is Servo, it will be a PropertyDeclarationBlock.
+class GenericSpecifiedValues {
+public:
+    // Check if we already contain a certain longhand
+    virtual bool PropertyIsSet(nsCSSPropertyID aId) = 0;
+
+    virtual nsRuleData* AsRuleData() = 0;
+};
+
+#endif // mozilla_GenericSpecifiedValues_h
\ No newline at end of file
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -81,16 +81,17 @@ EXPORTS.mozilla += [
     'CSSEnabledState.h',
     'CSSStyleSheet.h',
     'CSSVariableDeclarations.h',
     'CSSVariableResolver.h',
     'CSSVariableValues.h',
     'DeclarationBlock.h',
     'DeclarationBlockInlines.h',
     'DocumentStyleRootIterator.h',
+    'GenericSpecifiedValues.h',
     'HandleRefPtr.h',
     'IncrementalClearCOMRuleArray.h',
     'LayerAnimationInfo.h',
     'PreloadedStyleSheet.h',
     'RuleNodeCacheConditions.h',
     'RuleProcessorCache.h',
     'ServoArcTypeList.h',
     'ServoBindingList.h',
--- a/layout/style/nsRuleData.h
+++ b/layout/style/nsRuleData.h
@@ -7,30 +7,31 @@
  * temporary (expanded) representation of property-value pairs used to
  * hold data from matched rules during style data computation.
  */
 
 #ifndef nsRuleData_h_
 #define nsRuleData_h_
 
 #include "mozilla/CSSVariableDeclarations.h"
+#include "mozilla/GenericSpecifiedValues.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "mozilla/SheetType.h"
 #include "nsAutoPtr.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsStyleStructFwd.h"
 
 class nsPresContext;
 class nsStyleContext;
 struct nsRuleData;
 
 typedef void (*nsPostResolveFunc)(void* aStyleStruct, nsRuleData* aData);
 
-struct nsRuleData
+struct nsRuleData final: GenericSpecifiedValues
 {
   const uint32_t mSIDs;
   mozilla::RuleNodeCacheConditions mConditions;
   bool mIsImportantRule;
   mozilla::SheetType mLevel;
   nsPresContext* const mPresContext;
   nsStyleContext* const mStyleContext;
 
@@ -115,14 +116,23 @@ struct nsRuleData
       return const_cast<nsRuleData*>(this)->ValueFor##method_();             \
     }
   #define CSS_PROP_LIST_EXCLUDE_LOGICAL
   #include "nsCSSPropList.h"
   #undef CSS_PROP_LIST_EXCLUDE_LOGICAL
   #undef CSS_PROP
   #undef CSS_PROP_PUBLIC_OR_PRIVATE
 
+  // GenericSpecifiedValues overrides
+  bool PropertyIsSet(nsCSSPropertyID aId) override {
+    return ValueFor(aId)->GetUnit() != eCSSUnit_Null;
+  }
+
+  nsRuleData* AsRuleData() override {
+    return this;
+  }
+
 private:
   inline size_t GetPoisonOffset();
 
 };
 
 #endif