Bug 1449806: Merge {Servo,Generic}SpecifiedValues into MappedDeclarations. r=xidorn
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 22 Jun 2018 18:48:42 +0200
changeset 481269 5ba328c141b7b84bb0b6b836740b22d1d84b5380
parent 481268 86726e4cfa461aea420f7763f575d6695d7eff5f
child 481270 d535d6534b35f426f03bfa23a9c115cd2eedd746
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1449806
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1449806: Merge {Servo,Generic}SpecifiedValues into MappedDeclarations. r=xidorn The idea would be that this header is only included in cpp files, thus it's ok to include ServoBindings, etc. MozReview-Commit-ID: EgQEsR0cZd4
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/HTMLEmbedElement.cpp
dom/html/HTMLEmbedElement.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/HTMLOptionsCollection.cpp
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/HTMLSpanElement.cpp
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/HTMLTemplateElement.cpp
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/GenericSpecifiedValuesInlines.h
layout/style/MappedDeclarations.cpp
layout/style/MappedDeclarations.h
layout/style/ServoSpecifiedValues.cpp
layout/style/ServoSpecifiedValues.h
layout/style/moz.build
--- a/dom/base/nsMappedAttributeElement.cpp
+++ b/dom/base/nsMappedAttributeElement.cpp
@@ -22,18 +22,18 @@ nsMappedAttributeElement::SetAndSwapMapp
 
 nsMapRuleToAttributesFunc
 nsMappedAttributeElement::GetAttributeMappingFunction() const
 {
   return &MapNoAttributesInto;
 }
 
 void
-nsMappedAttributeElement::MapNoAttributesInto(const nsMappedAttributes* aAttributes,
-                                              mozilla::GenericSpecifiedValues* aGenericData)
+nsMappedAttributeElement::MapNoAttributesInto(const nsMappedAttributes*,
+                                              mozilla::MappedDeclarations&)
 {
 }
 
 void
 nsMappedAttributeElement::NodeInfoChanged(nsIDocument* aOldDoc)
 {
   nsHTMLStyleSheet* sheet = OwnerDoc()->GetAttributeStyleSheet();
   mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
--- a/dom/base/nsMappedAttributeElement.h
+++ b/dom/base/nsMappedAttributeElement.h
@@ -8,41 +8,44 @@
  * 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"
 
+namespace mozilla {
+class MappedDeclarations;
+}
+
 class nsMappedAttributes;
 struct nsRuleData;
 
 typedef void (*nsMapRuleToAttributesFunc)(const nsMappedAttributes* aAttributes,
-                                          mozilla::GenericSpecifiedValues* aData);
+                                          mozilla::MappedDeclarations&);
 
 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,
-                                  mozilla::GenericSpecifiedValues* aGenericData);
+                                  mozilla::MappedDeclarations&);
 
   virtual bool SetAndSwapMappedAttribute(nsAtom* aName,
                                          nsAttrValue& aValue,
                                          bool* aValueWasSet,
                                          nsresult* aRetval) override;
 
   virtual void NodeInfoChanged(nsIDocument* aOldDoc) override;
 };
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -7,20 +7,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 "mozilla/DeclarationBlock.h"
-#include "mozilla/GenericSpecifiedValues.h"
 #include "mozilla/HashFunctions.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/MemoryReporting.h"
-#include "mozilla/ServoSpecifiedValues.h"
 
 using namespace mozilla;
 
 bool
 nsMappedAttributes::sShuttingDown = false;
 nsTArray<void*>*
 nsMappedAttributes::sCachedMappedAttributeAllocations = nullptr;
 
@@ -306,13 +305,14 @@ nsMappedAttributes::SizeOfIncludingThis(
 
 void
 nsMappedAttributes::LazilyResolveServoDeclaration(nsIDocument* aDoc)
 {
 
   MOZ_ASSERT(!mServoStyle,
              "LazilyResolveServoDeclaration should not be called if mServoStyle is already set");
   if (mRuleMapper) {
-    mServoStyle = Servo_DeclarationBlock_CreateEmpty().Consume();
-    ServoSpecifiedValues servo = ServoSpecifiedValues(aDoc, mServoStyle.get());
-    (*mRuleMapper)(this, &servo);
+    MappedDeclarations declarations(
+      aDoc, Servo_DeclarationBlock_CreateEmpty().Consume());
+    (*mRuleMapper)(this, declarations);
+    mServoStyle = declarations.TakeDeclarationBlock();
   }
 }
--- a/dom/html/HTMLBRElement.cpp
+++ b/dom/html/HTMLBRElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLBRElement.h"
 #include "mozilla/dom/HTMLBRElementBinding.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(BR)
 
 namespace mozilla {
@@ -48,24 +48,24 @@ HTMLBRElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     GenericSpecifiedValues* aData)
+                                     MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_clear)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_clear)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::clear);
     if (value && value->Type() == nsAttrValue::eEnum)
-      aData->SetKeywordValue(eCSSProperty_clear, value->GetEnumValue());
+      aDecls.SetKeywordValue(eCSSProperty_clear, value->GetEnumValue());
   }
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLBRElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::clear },
     { nullptr }
--- a/dom/html/HTMLBRElement.h
+++ b/dom/html/HTMLBRElement.h
@@ -43,16 +43,16 @@ public:
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   virtual ~HTMLBRElement();
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "HTMLBodyElement.h"
 #include "mozilla/dom/HTMLBodyElementBinding.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/TextEditor.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
@@ -69,17 +69,17 @@ HTMLBodyElement::ParseAttribute(int32_t 
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                       GenericSpecifiedValues* aData)
+                                       MappedDeclarations& aDecls)
 {
   // This is the one place where we try to set the same property
   // multiple times in presentation attributes. Servo does not support
   // querying if a property is set (because that is O(n) behavior
   // in ServoSpecifiedValues). Instead, we use the below values to keep
   // track of whether we have already set a property, and if so, what value
   // we set it to (which is used when handling margin
   // attributes from the containing frame element)
@@ -94,109 +94,109 @@ HTMLBodyElement::MapAttributesIntoRule(c
   const nsAttrValue* value;
   // if marginwidth/marginheight are set, reflect them as 'margin'
   value = aAttributes->GetAttr(nsGkAtoms::marginwidth);
   if (value && value->Type() == nsAttrValue::eInteger) {
     bodyMarginWidth = value->GetIntegerValue();
     if (bodyMarginWidth < 0) {
       bodyMarginWidth = 0;
     }
-    aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyMarginWidth);
-    aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyMarginWidth);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyMarginWidth);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyMarginWidth);
   }
 
   value = aAttributes->GetAttr(nsGkAtoms::marginheight);
   if (value && value->Type() == nsAttrValue::eInteger) {
     bodyMarginHeight = value->GetIntegerValue();
     if (bodyMarginHeight < 0) {
       bodyMarginHeight = 0;
     }
-    aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyMarginHeight);
-    aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyMarginHeight);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyMarginHeight);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyMarginHeight);
   }
 
     // topmargin (IE-attribute)
   if (bodyMarginHeight == -1) {
     value = aAttributes->GetAttr(nsGkAtoms::topmargin);
     if (value && value->Type() == nsAttrValue::eInteger) {
       bodyTopMargin = value->GetIntegerValue();
       if (bodyTopMargin < 0) {
         bodyTopMargin = 0;
       }
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyTopMargin);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)bodyTopMargin);
     }
   }
     // bottommargin (IE-attribute)
 
   if (bodyMarginHeight == -1) {
     value = aAttributes->GetAttr(nsGkAtoms::bottommargin);
     if (value && value->Type() == nsAttrValue::eInteger) {
       bodyBottomMargin = value->GetIntegerValue();
       if (bodyBottomMargin < 0) {
         bodyBottomMargin = 0;
       }
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyBottomMargin);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)bodyBottomMargin);
     }
   }
 
     // leftmargin (IE-attribute)
   if (bodyMarginWidth == -1) {
     value = aAttributes->GetAttr(nsGkAtoms::leftmargin);
     if (value && value->Type() == nsAttrValue::eInteger) {
       bodyLeftMargin = value->GetIntegerValue();
       if (bodyLeftMargin < 0) {
         bodyLeftMargin = 0;
       }
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyLeftMargin);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)bodyLeftMargin);
     }
   }
     // rightmargin (IE-attribute)
   if (bodyMarginWidth == -1) {
     value = aAttributes->GetAttr(nsGkAtoms::rightmargin);
     if (value && value->Type() == nsAttrValue::eInteger) {
       bodyRightMargin = value->GetIntegerValue();
       if (bodyRightMargin < 0) {
         bodyRightMargin = 0;
       }
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyRightMargin);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)bodyRightMargin);
     }
   }
 
   // if marginwidth or marginheight is set in the <frame> and not set in the <body>
   // reflect them as margin in the <body>
   if (bodyMarginWidth == -1 || bodyMarginHeight == -1) {
-    nsCOMPtr<nsIDocShell> docShell(aData->Document()->GetDocShell());
+    nsCOMPtr<nsIDocShell> docShell(aDecls.Document()->GetDocShell());
     if (docShell) {
       nscoord frameMarginWidth=-1;  // default value
       nscoord frameMarginHeight=-1; // default value
       docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set
       docShell->GetMarginHeight(&frameMarginHeight);
 
       if (bodyMarginWidth == -1 && frameMarginWidth >= 0) {
         if (bodyLeftMargin == -1) {
-          aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)frameMarginWidth);
+          aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)frameMarginWidth);
         }
         if (bodyRightMargin == -1) {
-          aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)frameMarginWidth);
+          aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)frameMarginWidth);
         }
       }
 
       if (bodyMarginHeight == -1 && frameMarginHeight >= 0) {
         if (bodyTopMargin == -1) {
-          aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)frameMarginHeight);
+          aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)frameMarginHeight);
         }
         if (bodyBottomMargin == -1) {
-          aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)frameMarginHeight);
+          aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)frameMarginHeight);
         }
       }
     }
   }
 
   // When display if first asked for, go ahead and get our colors set up.
-  if (nsHTMLStyleSheet* styleSheet = aData->Document()->GetAttributeStyleSheet()) {
+  if (nsHTMLStyleSheet* styleSheet = aDecls.Document()->GetAttributeStyleSheet()) {
     nscolor color;
     value = aAttributes->GetAttr(nsGkAtoms::link);
     if (value && value->GetColorValue(color)) {
       styleSheet->SetLinkColor(color);
     }
 
     value = aAttributes->GetAttr(nsGkAtoms::alink);
     if (value && value->GetColorValue(color)) {
@@ -204,27 +204,27 @@ HTMLBodyElement::MapAttributesIntoRule(c
     }
 
     value = aAttributes->GetAttr(nsGkAtoms::vlink);
     if (value && value->GetColorValue(color)) {
       styleSheet->SetVisitedLinkColor(color);
     }
   }
 
-  if (!aData->PropertyIsSet(eCSSProperty_color)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_color)) {
     // color: color
     nscolor color;
     value = aAttributes->GetAttr(nsGkAtoms::text);
     if (value && value->GetColorValue(color)) {
-      aData->SetColorValue(eCSSProperty_color, color);
+      aDecls.SetColorValue(eCSSProperty_color, color);
     }
   }
 
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 nsMapRuleToAttributesFunc
 HTMLBodyElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -149,15 +149,15 @@ public:
 
 protected:
   virtual ~HTMLBodyElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLBodyElement_h___ */
--- a/dom/html/HTMLDivElement.cpp
+++ b/dom/html/HTMLDivElement.cpp
@@ -56,29 +56,29 @@ HTMLDivElement::ParseAttribute(int32_t a
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLDivElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                      GenericSpecifiedValues* aData)
+                                      MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 static void
-MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, GenericSpecifiedValues* aData)
+MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBGColorInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapBGColorInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLDivElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   if (mNodeInfo->Equals(nsGkAtoms::div)) {
     static const MappedAttributeEntry* const map[] = {
       sDivAlignAttributeMap,
--- a/dom/html/HTMLDivElement.h
+++ b/dom/html/HTMLDivElement.h
@@ -41,15 +41,15 @@ public:
 
 protected:
   virtual ~HTMLDivElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLDivElement_h___ */
--- a/dom/html/HTMLEmbedElement.cpp
+++ b/dom/html/HTMLEmbedElement.cpp
@@ -233,38 +233,38 @@ HTMLEmbedElement::ParseAttribute(int32_t
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 static void
 MapAttributesIntoRuleBase(const nsMappedAttributes *aAttributes,
-                          GenericSpecifiedValues* aData)
+                          MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls);
 }
 
 static void
 MapAttributesIntoRuleExceptHidden(const nsMappedAttributes *aAttributes,
-                                  GenericSpecifiedValues* aData)
+                                  MappedDeclarations& aDecls)
 {
-  MapAttributesIntoRuleBase(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aData);
+  MapAttributesIntoRuleBase(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aDecls);
 }
 
 void
 HTMLEmbedElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
-  MapAttributesIntoRuleBase(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  MapAttributesIntoRuleBase(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLEmbedElement::IsAttributeMapped(const nsAtom *aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap,
     sImageMarginSizeAttributeMap,
--- a/dom/html/HTMLEmbedElement.h
+++ b/dom/html/HTMLEmbedElement.h
@@ -145,17 +145,17 @@ protected:
 private:
   ~HTMLEmbedElement();
 
   nsContentPolicyType GetContentPolicyType() const override;
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 
   /**
    * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    * It will not be called if the value is being unset.
    *
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
    * @param aNotify Whether we plan to notify document observers.
--- a/dom/html/HTMLFontElement.cpp
+++ b/dom/html/HTMLFontElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "HTMLFontElement.h"
 #include "mozilla/dom/HTMLFontElementBinding.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsMappedAttributes.h"
 #include "nsContentUtils.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Font)
 
 namespace mozilla {
 namespace dom {
@@ -50,52 +50,52 @@ HTMLFontElement::ParseAttribute(int32_t 
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLFontElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                       GenericSpecifiedValues* aData)
+                                       MappedDeclarations& aDecls)
 {
   // face: string list
-  if (!aData->PropertyIsSet(eCSSProperty_font_family)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_font_family)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::face);
     if (value && value->Type() == nsAttrValue::eString &&
         !value->IsEmptyString()) {
-      aData->SetFontFamily(value->GetStringValue());
+      aDecls.SetFontFamily(value->GetStringValue());
     }
   }
   // size: int
-  if (!aData->PropertyIsSet(eCSSProperty_font_size)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_font_size)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
     if (value && value->Type() == nsAttrValue::eInteger)
-      aData->SetKeywordValue(eCSSProperty_font_size, value->GetIntegerValue());
+      aDecls.SetKeywordValue(eCSSProperty_font_size, value->GetIntegerValue());
   }
-  if (!aData->PropertyIsSet(eCSSProperty_color)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_color)) {
     // color: color
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
     nscolor color;
     if (value && value->GetColorValue(color)) {
-      aData->SetColorValue(eCSSProperty_color, color);
+      aDecls.SetColorValue(eCSSProperty_color, color);
     }
   }
-  if (aData->Document()->GetCompatibilityMode() == eCompatibility_NavQuirks) {
+  if (aDecls.Document()->GetCompatibilityMode() == eCompatibility_NavQuirks) {
     // Make <a><font color="red">text</font></a> give the text a red underline
     // in quirks mode.  The NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL flag only
     // affects quirks mode rendering.
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
     nscolor color;
     if (value && value->GetColorValue(color)) {
-      aData->SetTextDecorationColorOverride();
+      aDecls.SetTextDecorationColorOverride();
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLFontElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::face },
     { &nsGkAtoms::size },
--- a/dom/html/HTMLFontElement.h
+++ b/dom/html/HTMLFontElement.h
@@ -57,15 +57,15 @@ public:
 
 protected:
   virtual ~HTMLFontElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLFontElement_h___ */
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -115,15 +115,15 @@ public:
 
 protected:
   virtual ~HTMLFrameElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLFrameElement_h
--- a/dom/html/HTMLHRElement.cpp
+++ b/dom/html/HTMLHRElement.cpp
@@ -56,17 +56,17 @@ HTMLHRElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     GenericSpecifiedValues* aData)
+                                     MappedDeclarations& aDecls)
 {
   bool noshade = false;
 
   const nsAttrValue* colorValue = aAttributes->GetAttr(nsGkAtoms::color);
   nscolor color;
   bool colorIsSet = colorValue && colorValue->GetColorValue(color);
 
   if (colorIsSet) {
@@ -76,42 +76,42 @@ HTMLHRElement::MapAttributesIntoRule(con
   }
 
   // align: enum
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
   if (value && value->Type() == nsAttrValue::eEnum) {
     // Map align attribute into auto side margins
     switch (value->GetEnumValue()) {
     case NS_STYLE_TEXT_ALIGN_LEFT:
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_left, 0.0f);
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_right);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, 0.0f);
+      aDecls.SetAutoValueIfUnset(eCSSProperty_margin_right);
       break;
     case NS_STYLE_TEXT_ALIGN_RIGHT:
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_left);
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_right, 0.0f);
+      aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, 0.0f);
       break;
     case NS_STYLE_TEXT_ALIGN_CENTER:
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_left);
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_right);
+      aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
+      aDecls.SetAutoValueIfUnset(eCSSProperty_margin_right);
       break;
     }
   }
-  if (!aData->PropertyIsSet(eCSSProperty_height)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
     // size: integer
     if (noshade) {
       // noshade case: size is set using the border
-      aData->SetAutoValue(eCSSProperty_height);
+      aDecls.SetAutoValue(eCSSProperty_height);
     } else {
       // normal case
       // the height includes the top and bottom borders that are initially 1px.
       // for size=1, html.css has a special case rule that makes this work by
       // removing all but the top border.
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
       if (value && value->Type() == nsAttrValue::eInteger) {
-        aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
+        aDecls.SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
       } // else use default value from html.css
     }
   }
 
   // if not noshade, border styles are dealt with by html.css
   if (noshade) {
     // size: integer
     // if a size is set, use half of it per side, otherwise, use 1px per side
@@ -125,53 +125,53 @@ HTMLHRElement::MapAttributesIntoRule(con
         // subpixel borders should be removed.
         // In the meantime, this makes http://www.microsoft.com/ look right.
         sizePerSide = 1.0f;
         allSides = false;
       }
     } else {
       sizePerSide = 1.0f; // default to a 2px high line
     }
-    aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, sizePerSide);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, sizePerSide);
     if (allSides) {
-      aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, sizePerSide);
-      aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, sizePerSide);
-      aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, sizePerSide);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, sizePerSide);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, sizePerSide);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, sizePerSide);
     }
 
-    if (!aData->PropertyIsSet(eCSSProperty_border_top_style))
-      aData->SetKeywordValue(eCSSProperty_border_top_style,
+    if (!aDecls.PropertyIsSet(eCSSProperty_border_top_style))
+      aDecls.SetKeywordValue(eCSSProperty_border_top_style,
                              NS_STYLE_BORDER_STYLE_SOLID);
     if (allSides) {
-      aData->SetKeywordValueIfUnset(eCSSProperty_border_right_style,
+      aDecls.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
                                     NS_STYLE_BORDER_STYLE_SOLID);
-      aData->SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
+      aDecls.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
                                     NS_STYLE_BORDER_STYLE_SOLID);
-      aData->SetKeywordValueIfUnset(eCSSProperty_border_left_style,
+      aDecls.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
                                     NS_STYLE_BORDER_STYLE_SOLID);
 
       // If it would be noticeable, set the border radius to
       // 10000px on all corners; this triggers the clamping to make
       // circular ends.  This assumes the <hr> isn't larger than
       // that in *both* dimensions.
       for (const nsCSSPropertyID* props =
             nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
            *props != eCSSProperty_UNKNOWN; ++props) {
-        aData->SetPixelValueIfUnset(*props, 10000.0f);
+        aDecls.SetPixelValueIfUnset(*props, 10000.0f);
       }
     }
   }
   // color: a color
   // (we got the color attribute earlier)
   if (colorIsSet) {
-    aData->SetColorValueIfUnset(eCSSProperty_color, color);
+    aDecls.SetColorValueIfUnset(eCSSProperty_color, color);
   }
 
-  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLHRElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::width },
--- a/dom/html/HTMLHRElement.h
+++ b/dom/html/HTMLHRElement.h
@@ -81,15 +81,15 @@ public:
 
 protected:
   virtual ~HTMLHRElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLHRElement_h
--- a/dom/html/HTMLHeadingElement.cpp
+++ b/dom/html/HTMLHeadingElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLHeadingElement.h"
 #include "mozilla/dom/HTMLHeadingElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 #include "mozAutoDocUpdate.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Heading)
 
 namespace mozilla {
@@ -42,20 +42,20 @@ HTMLHeadingElement::ParseAttribute(int32
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLHeadingElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                          GenericSpecifiedValues* aData)
+                                          MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLHeadingElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sDivAlignAttributeMap,
     sCommonAttributeMap
--- a/dom/html/HTMLHeadingElement.h
+++ b/dom/html/HTMLHeadingElement.h
@@ -42,15 +42,15 @@ public:
 
 protected:
   virtual ~HTMLHeadingElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLHeadingElement_h
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "mozilla/dom/HTMLIFrameElementBinding.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsMappedAttributes.h"
 #include "nsAttrValueInlines.h"
 #include "nsError.h"
 #include "nsStyleConsts.h"
 #include "nsContentUtils.h"
 #include "nsSandboxFlags.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(IFrame)
@@ -77,37 +77,37 @@ HTMLIFrameElement::ParseAttribute(int32_
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
                                                    aValue,
                                                    aMaybeScriptedPrincipal,
                                                    aResult);
 }
 
 void
 HTMLIFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                         GenericSpecifiedValues* aData)
+                                         MappedDeclarations& aDecls)
 {
   // 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 ||
         NS_STYLE_FRAME_NO == frameborder ||
         NS_STYLE_FRAME_OFF == frameborder) {
-      aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, 0.0f);
-      aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, 0.0f);
-      aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, 0.0f);
-      aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, 0.0f);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, 0.0f);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, 0.0f);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, 0.0f);
+      aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, 0.0f);
     }
   }
 
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLIFrameElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::height },
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -200,17 +200,17 @@ protected:
                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 
   static const DOMTokenListSupportedToken sSupportedSandboxTokens[];
 
   /**
    * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    * This function will be called by AfterSetAttr whether the attribute is being
    * set or unset.
    *
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -39,17 +39,17 @@
 #include "imgILoader.h"
 #include "imgINotificationObserver.h"
 #include "imgRequestProxy.h"
 
 #include "nsILoadGroup.h"
 
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 #include "nsLayoutUtils.h"
 
 using namespace mozilla::net;
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
 
@@ -243,23 +243,23 @@ HTMLImageElement::ParseAttribute(int32_t
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 nsChangeHint
 HTMLImageElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -402,17 +402,17 @@ protected:
 
   // Created when we're tracking responsive image state
   RefPtr<ResponsiveImageSelector> mResponsiveSelector;
 
 private:
   bool SourceElementMatches(Element* aSourceElement);
 
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
   /**
    * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    * It will not be called if the value is being unset.
    *
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
    * @param aValue the value it's being set to represented as either a string or
    *        a parsed nsAttrValue.
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -60,17 +60,17 @@
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsVariant.h"
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 
 #include <algorithm>
 
 // input type=radio
@@ -5576,29 +5576,29 @@ HTMLInputElement::ParseAttribute(int32_t
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLInputElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
   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, aDecls);
+    nsGenericHTMLFormElementWithState::MapImageMarginAttributeInto(aAttributes, aDecls);
+    nsGenericHTMLFormElementWithState::MapImageSizeAttributesInto(aAttributes, aDecls);
     // Images treat align as "float"
-    nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
-  }
-
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+    nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aDecls);
+  }
+
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 nsChangeHint
 HTMLInputElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                          int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -1662,17 +1662,17 @@ protected:
   bool                     mNumberControlSpinnerSpinsUp : 1;
   bool                     mPickerRunning : 1;
   bool                     mSelectionCached : 1;
   bool                     mIsPreviewEnabled : 1;
   bool                     mHasPatternAttribute : 1;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 
   /**
    * 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
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLLIElement.h"
 #include "mozilla/dom/HTMLLIElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(LI)
 
 namespace mozilla {
@@ -62,26 +62,26 @@ HTMLLIElement::ParseAttribute(int32_t aN
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLLIElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                     GenericSpecifiedValues* aData)
+                                     MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
     // type: enum
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
     if (value && value->Type() == nsAttrValue::eEnum)
-      aData->SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
+      aDecls.SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLLIElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::type },
     { nullptr },
--- a/dom/html/HTMLLIElement.h
+++ b/dom/html/HTMLLIElement.h
@@ -55,15 +55,15 @@ public:
 
 protected:
   virtual ~HTMLLIElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLLIElement_h
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -460,24 +460,24 @@ HTMLObjectElement::ParseAttribute(int32_
     }
   }
 
   return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
                                                   aValue, aMaybeScriptedPrincipal, aResult);
 }
 
 void
-HTMLObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                                         GenericSpecifiedValues *aData)
+HTMLObjectElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                         MappedDeclarations& aDecls)
 {
-  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLObjectElement::IsAttributeMapped(const nsAtom *aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sCommonAttributeMap,
     sImageMarginSizeAttributeMap,
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -270,17 +270,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,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 
   /**
    * This function is called by AfterSetAttr and OnAttrSetButNotChanged.
    * This function will be called by AfterSetAttr whether the attribute is being
    * set or unset.
    *
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
--- a/dom/html/HTMLOptionsCollection.cpp
+++ b/dom/html/HTMLOptionsCollection.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLOptionsCollection.h"
 
 #include "HTMLOptGroupElement.h"
 #include "mozAutoDocUpdate.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/HTMLOptionElement.h"
 #include "mozilla/dom/HTMLOptionsCollectionBinding.h"
 #include "mozilla/dom/HTMLSelectElement.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIComboboxControlFrame.h"
--- a/dom/html/HTMLParagraphElement.cpp
+++ b/dom/html/HTMLParagraphElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLParagraphElement.h"
 #include "mozilla/dom/HTMLParagraphElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Paragraph)
 
 namespace mozilla {
 namespace dom {
@@ -35,20 +35,20 @@ HTMLParagraphElement::ParseAttribute(int
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLParagraphElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                            GenericSpecifiedValues* aData)
+                                            MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLParagraphElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry* const map[] = {
     sDivAlignAttributeMap,
     sCommonAttributeMap,
--- a/dom/html/HTMLParagraphElement.h
+++ b/dom/html/HTMLParagraphElement.h
@@ -49,15 +49,15 @@ public:
 
 protected:
   virtual ~HTMLParagraphElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLParagraphElement_h
--- a/dom/html/HTMLPreElement.cpp
+++ b/dom/html/HTMLPreElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLPreElement.h"
 #include "mozilla/dom/HTMLPreElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Pre)
 
 namespace mozilla {
@@ -38,25 +38,25 @@ HTMLPreElement::ParseAttribute(int32_t a
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLPreElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                      GenericSpecifiedValues* aData)
+                                      MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
     // wrap: empty
     if (aAttributes->GetAttr(nsGkAtoms::wrap))
-      aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::PreWrap);
+      aDecls.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::PreWrap);
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLPreElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   if (!mNodeInfo->Equals(nsGkAtoms::pre)) {
     return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
   }
--- a/dom/html/HTMLPreElement.h
+++ b/dom/html/HTMLPreElement.h
@@ -48,15 +48,15 @@ public:
 
 protected:
   virtual ~HTMLPreElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLPreElement_h
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/HTMLOptGroupElement.h"
 #include "mozilla/dom/HTMLOptionElement.h"
 #include "mozilla/dom/HTMLSelectElementBinding.h"
 #include "mozilla/dom/UnionTypes.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentList.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIDocument.h"
 #include "nsIFormControlFrame.h"
 #include "nsIForm.h"
@@ -1268,20 +1268,20 @@ HTMLSelectElement::ParseAttribute(int32_
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLSelectElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                         GenericSpecifiedValues* aData)
+                                         MappedDeclarations& aDecls)
 {
-  nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 nsChangeHint
 HTMLSelectElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                           int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -608,15 +608,15 @@ protected:
 
   /**
    * The current displayed preview text.
   */
   nsString  mPreviewValue;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSelectElement_h
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -7,17 +7,17 @@
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/dom/HTMLBaseElementBinding.h"
 #include "mozilla/dom/HTMLDirectoryElementBinding.h"
 #include "mozilla/dom/HTMLHeadElementBinding.h"
 #include "mozilla/dom/HTMLHtmlElementBinding.h"
 #include "mozilla/dom/HTMLParamElementBinding.h"
 #include "mozilla/dom/HTMLQuoteElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 #include "nsContentUtils.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIURI.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Shared)
@@ -74,31 +74,31 @@ HTMLSharedElement::ParseAttribute(int32_
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 static void
 DirectoryMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                               GenericSpecifiedValues* aData)
+                               MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
     // type: enum
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
     if (value) {
       if (value->Type() == nsAttrValue::eEnum) {
-        aData->SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
+        aDecls.SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
       } else {
-        aData->SetKeywordValue(eCSSProperty_list_style_type, NS_STYLE_LIST_STYLE_DISC);
+        aDecls.SetKeywordValue(eCSSProperty_list_style_type, NS_STYLE_LIST_STYLE_DISC);
       }
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   if (mNodeInfo->Equals(nsGkAtoms::dir)) {
     static const MappedAttributeEntry attributes[] = {
       { &nsGkAtoms::type },
--- a/dom/html/HTMLSharedListElement.cpp
+++ b/dom/html/HTMLSharedListElement.cpp
@@ -4,17 +4,17 @@
  * 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/. */
 
 #include "mozilla/dom/HTMLSharedListElement.h"
 #include "mozilla/dom/HTMLDListElementBinding.h"
 #include "mozilla/dom/HTMLOListElementBinding.h"
 #include "mozilla/dom/HTMLUListElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsMappedAttributes.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(SharedList)
 
@@ -76,27 +76,27 @@ HTMLSharedListElement::ParseAttribute(in
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLSharedListElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                             GenericSpecifiedValues* aData)
+                                             MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_list_style_type)) {
     // type: enum
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
     if (value && value->Type() == nsAttrValue::eEnum) {
-      aData->SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
+      aDecls.SetKeywordValue(eCSSProperty_list_style_type, value->GetEnumValue());
     }
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedListElement::IsAttributeMapped(const nsAtom* 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
@@ -70,15 +70,15 @@ public:
 
 protected:
   virtual ~HTMLSharedListElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedListElement_h
--- a/dom/html/HTMLSpanElement.cpp
+++ b/dom/html/HTMLSpanElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLSpanElement.h"
 #include "mozilla/dom/HTMLSpanElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsAtom.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Span)
 
 namespace mozilla {
 namespace dom {
--- a/dom/html/HTMLTableCaptionElement.cpp
+++ b/dom/html/HTMLTableCaptionElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLTableCaptionElement.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsMappedAttributes.h"
 #include "mozilla/dom/HTMLTableCaptionElementBinding.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCaption)
 
 namespace mozilla {
 namespace dom {
@@ -48,25 +48,25 @@ HTMLTableCaptionElement::ParseAttribute(
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableCaptionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               GenericSpecifiedValues* aData)
+                                               MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_caption_side)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_caption_side)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
     if (value && value->Type() == nsAttrValue::eEnum)
-      aData->SetKeywordValue(eCSSProperty_caption_side, value->GetEnumValue());
+      aDecls.SetKeywordValue(eCSSProperty_caption_side, value->GetEnumValue());
   }
 
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCaptionElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { nullptr }
--- a/dom/html/HTMLTableCaptionElement.h
+++ b/dom/html/HTMLTableCaptionElement.h
@@ -43,15 +43,15 @@ public:
 
 protected:
   virtual ~HTMLTableCaptionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCaptionElement_h */
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLTableCellElement.h"
 #include "mozilla/dom/HTMLTableElement.h"
 #include "mozilla/dom/HTMLTableRowElement.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsMappedAttributes.h"
 #include "nsAttrValueInlines.h"
 #include "celldata.h"
 #include "mozilla/dom/HTMLTableCellElementBinding.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCell)
 
 namespace mozilla {
@@ -178,64 +178,64 @@ HTMLTableCellElement::ParseAttribute(int
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                            GenericSpecifiedValues* aData)
+                                            MappedDeclarations& aDecls)
 {
   // width: value
-  if (!aData->PropertyIsSet(eCSSProperty_width)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_width)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
     if (value && value->Type() == nsAttrValue::eInteger) {
       if (value->GetIntegerValue() > 0)
-        aData->SetPixelValue(eCSSProperty_width, (float)value->GetIntegerValue());
+        aDecls.SetPixelValue(eCSSProperty_width, (float)value->GetIntegerValue());
       // else 0 implies auto for compatibility.
     }
     else if (value && value->Type() == nsAttrValue::ePercent) {
       if (value->GetPercentValue() > 0.0f)
-        aData->SetPercentValue(eCSSProperty_width, value->GetPercentValue());
+        aDecls.SetPercentValue(eCSSProperty_width, value->GetPercentValue());
       // else 0 implies auto for compatibility
     }
   }
   // height: value
-  if (!aData->PropertyIsSet(eCSSProperty_height)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
     if (value && value->Type() == nsAttrValue::eInteger) {
       if (value->GetIntegerValue() > 0)
-        aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
+        aDecls.SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
       // else 0 implies auto for compatibility.
     }
     else if (value && value->Type() == nsAttrValue::ePercent) {
       if (value->GetPercentValue() > 0.0f)
-        aData->SetPercentValue(eCSSProperty_height, value->GetPercentValue());
+        aDecls.SetPercentValue(eCSSProperty_height, value->GetPercentValue());
       // else 0 implies auto for compatibility
     }
   }
-  if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
+  if (!aDecls.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->Document()->GetCompatibilityMode();
+      nsCompatibility mode = aDecls.Document()->GetCompatibilityMode();
       if (!value || value->Type() != nsAttrValue::eInteger ||
           value->GetIntegerValue() == 0 ||
           eCompatibility_NavQuirks != mode) {
-        aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Nowrap);
+        aDecls.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Nowrap);
       }
     }
   }
 
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableCellElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -156,15 +156,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,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCellElement_h */
--- a/dom/html/HTMLTableColElement.cpp
+++ b/dom/html/HTMLTableColElement.cpp
@@ -3,17 +3,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLTableColElement.h"
 #include "mozilla/dom/HTMLTableColElementBinding.h"
 #include "nsMappedAttributes.h"
 #include "nsAttrValueInlines.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(TableCol)
 
 namespace mozilla {
 namespace dom {
 
 // use the same protection as ancient code did
 // http://lxr.mozilla.org/classic/source/lib/layout/laytable.c#46
@@ -60,36 +60,36 @@ HTMLTableColElement::ParseAttribute(int3
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableColElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           GenericSpecifiedValues* aData)
+                                           MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty__x_span)) {
+  if (!aDecls.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) {
-        aData->SetIntValue(eCSSProperty__x_span, value->GetIntegerValue());
+        aDecls.SetIntValue(eCSSProperty__x_span, value->GetIntegerValue());
       }
     }
   }
 
-  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableColElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::align },
--- a/dom/html/HTMLTableColElement.h
+++ b/dom/html/HTMLTableColElement.h
@@ -84,15 +84,15 @@ public:
 
 protected:
   virtual ~HTMLTableColElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableColElement_h */
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -1,16 +1,16 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLTableElement.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsAttrValueInlines.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsMappedAttributes.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/HTMLTableElementBinding.h"
 #include "nsContentUtils.h"
 #include "jsfriendapi.h"
 
@@ -927,94 +927,94 @@ HTMLTableElement::ParseAttribute(int32_t
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 
 
 void
 HTMLTableElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
   // 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 ComputedStyle rather than checking
   // which *element* it's matching (style rules should not stop matching
   // when the display type is changed).
 
-  nsCompatibility mode = aData->Document()->GetCompatibilityMode();
+  nsCompatibility mode = aDecls.Document()->GetCompatibilityMode();
 
   // cellspacing
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::cellspacing);
   if (value && value->Type() == nsAttrValue::eInteger &&
-      !aData->PropertyIsSet(eCSSProperty_border_spacing)) {
-    aData->SetPixelValue(eCSSProperty_border_spacing, float(value->GetIntegerValue()));
+      !aDecls.PropertyIsSet(eCSSProperty_border_spacing)) {
+    aDecls.SetPixelValue(eCSSProperty_border_spacing, float(value->GetIntegerValue()));
   }
   // align; Check for enumerated type (it may be another type if
   // illegal)
   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) {
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_left);
-      aData->SetAutoValueIfUnset(eCSSProperty_margin_right);
+      aDecls.SetAutoValueIfUnset(eCSSProperty_margin_left);
+      aDecls.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) {
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)value->GetIntegerValue());
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)value->GetIntegerValue());
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left, (float)value->GetIntegerValue());
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right, (float)value->GetIntegerValue());
     }
 
     value = aAttributes->GetAttr(nsGkAtoms::vspace);
 
     if (value && value->Type() == nsAttrValue::eInteger) {
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)value->GetIntegerValue());
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)value->GetIntegerValue());
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top, (float)value->GetIntegerValue());
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)value->GetIntegerValue());
     }
   }
   // bordercolor
   value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
   nscolor color;
   if (value && value->GetColorValue(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);
+    aDecls.SetColorValueIfUnset(eCSSProperty_border_top_color, color);
+    aDecls.SetColorValueIfUnset(eCSSProperty_border_left_color, color);
+    aDecls.SetColorValueIfUnset(eCSSProperty_border_bottom_color, color);
+    aDecls.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
-    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);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)borderThickness);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)borderThickness);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)borderThickness);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)borderThickness);
   }
 
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::cellpadding },
     { &nsGkAtoms::cellspacing },
@@ -1042,28 +1042,28 @@ HTMLTableElement::IsAttributeMapped(cons
 nsMapRuleToAttributesFunc
 HTMLTableElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 static void
 MapInheritedTableAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aData)
+                                    MappedDeclarations& aDecls)
 {
   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.
     float pad = float(value->GetIntegerValue());
 
-    aData->SetPixelValueIfUnset(eCSSProperty_padding_top, pad);
-    aData->SetPixelValueIfUnset(eCSSProperty_padding_right, pad);
-    aData->SetPixelValueIfUnset(eCSSProperty_padding_bottom, pad);
-    aData->SetPixelValueIfUnset(eCSSProperty_padding_left, pad);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_padding_top, pad);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_padding_right, pad);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_padding_bottom, pad);
+    aDecls.SetPixelValueIfUnset(eCSSProperty_padding_left, pad);
   }
 }
 
 nsMappedAttributes*
 HTMLTableElement::GetAttributesMappedForCell()
 {
   return mTableInheritedAttributes;
 }
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -236,15 +236,15 @@ protected:
   RefPtr<nsContentList> mTBodies;
   RefPtr<TableRowsCollection> mRows;
   nsMappedAttributes *mTableInheritedAttributes;
   void BuildInheritedAttributes();
   void ReleaseInheritedAttributes();
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableElement_h */
--- a/dom/html/HTMLTableRowElement.cpp
+++ b/dom/html/HTMLTableRowElement.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLTableRowElement.h"
 #include "mozilla/dom/HTMLTableElement.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsMappedAttributes.h"
 #include "nsAttrValueInlines.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLTableRowElementBinding.h"
 #include "nsContentList.h"
 #include "nsContentUtils.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(TableRow)
@@ -255,23 +255,23 @@ HTMLTableRowElement::ParseAttribute(int3
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           GenericSpecifiedValues* aData)
+                                           MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableRowElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableRowElement.h
+++ b/dom/html/HTMLTableRowElement.h
@@ -98,15 +98,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,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/dom/html/HTMLTableSectionElement.cpp
+++ b/dom/html/HTMLTableSectionElement.cpp
@@ -1,16 +1,16 @@
 /* -*- 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/. */
 
 #include "mozilla/dom/HTMLTableSectionElement.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsMappedAttributes.h"
 #include "nsAttrValueInlines.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/HTMLTableSectionElementBinding.h"
 #include "nsContentUtils.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(TableSection)
 
@@ -158,28 +158,28 @@ HTMLTableSectionElement::ParseAttribute(
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableSectionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                               GenericSpecifiedValues* aData)
+                                               MappedDeclarations& aDecls)
 {
   // height: value
-  if (!aData->PropertyIsSet(eCSSProperty_height)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
     if (value && value->Type() == nsAttrValue::eInteger)
-      aData->SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
+      aDecls.SetPixelValue(eCSSProperty_height, (float)value->GetIntegerValue());
   }
-  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapVAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLTableSectionElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::align },
     { &nsGkAtoms::valign },
--- a/dom/html/HTMLTableSectionElement.h
+++ b/dom/html/HTMLTableSectionElement.h
@@ -80,15 +80,15 @@ protected:
   virtual ~HTMLTableSectionElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   RefPtr<nsContentList> mRows;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableSectionElement_h */
--- a/dom/html/HTMLTemplateElement.cpp
+++ b/dom/html/HTMLTemplateElement.cpp
@@ -2,17 +2,17 @@
 /* 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/. */
 
 #include "mozilla/dom/HTMLTemplateElement.h"
 #include "mozilla/dom/HTMLTemplateElementBinding.h"
 
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsAtom.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Template)
 
 namespace mozilla {
 namespace dom {
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -8,17 +8,17 @@
 
 #include "mozAutoDocUpdate.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/HTMLTextAreaElementBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/MouseEvents.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentCID.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsError.h"
 #include "nsFocusManager.h"
 #include "nsIComponentManager.h"
 #include "nsIConstraintValidation.h"
@@ -422,29 +422,29 @@ HTMLTextAreaElement::ParseAttribute(int3
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                           GenericSpecifiedValues* aData)
+                                           MappedDeclarations& aDecls)
 {
   // wrap=off
-  if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_white_space)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::wrap);
     if (value && value->Type() == nsAttrValue::eString &&
         value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
-      aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
+      aDecls.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
     }
   }
 
-  nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
-  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 nsChangeHint
 HTMLTextAreaElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                             int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -413,16 +413,16 @@ protected:
    * if we have no editor state.
    */
   void GetSelectionRange(uint32_t* aSelectionStart,
                          uint32_t* aSelectionEnd,
                          ErrorResult& aRv);
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -96,20 +96,20 @@ HTMLVideoElement::ParseAttribute(int32_t
    }
 
    return HTMLMediaElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                            aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLVideoElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
-  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
+  nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aDecls);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLVideoElement::IsAttributeMapped(const nsAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::width },
     { &nsGkAtoms::height },
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -161,17 +161,17 @@ protected:
   void UpdateScreenWakeLock();
 
   RefPtr<WakeLock> mScreenWakeLock;
 
   bool mIsOrientationLocked;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                                    GenericSpecifiedValues* aGenericData);
+                                    MappedDeclarations&);
 
   static bool IsVideoStatsEnabled();
   double TotalPlayTime() const;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/DeclarationBlock.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEditor.h"
 
 #include "nscore.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValueInlines.h"
 #include "nsCOMPtr.h"
@@ -1157,75 +1157,75 @@ nsGenericHTMLElement::ParseFrameborderVa
 bool
 nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
                                           nsAttrValue& aResult)
 {
   return aResult.ParseEnumValue(aString, kScrollingTable, false);
 }
 
 static inline void
-MapLangAttributeInto(const nsMappedAttributes* aAttributes, GenericSpecifiedValues* aData)
+MapLangAttributeInto(const nsMappedAttributes* aAttributes, MappedDeclarations& aDecls)
 {
   const nsAttrValue* langValue = aAttributes->GetAttr(nsGkAtoms::lang);
   if (!langValue) {
     return;
   }
   MOZ_ASSERT(langValue->Type() == nsAttrValue::eAtom);
-  aData->SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
+  aDecls.SetIdentAtomValueIfUnset(eCSSProperty__x_lang,
                                   langValue->GetAtomValue());
-  if (!aData->PropertyIsSet(eCSSProperty_text_emphasis_position)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_text_emphasis_position)) {
     const nsAtom* lang = langValue->GetAtomValue();
     if (nsStyleUtil::MatchesLanguagePrefix(lang, u"zh")) {
-      aData->SetKeywordValue(eCSSProperty_text_emphasis_position,
+      aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position,
                              NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT_ZH);
     } else if (nsStyleUtil::MatchesLanguagePrefix(lang, u"ja") ||
                nsStyleUtil::MatchesLanguagePrefix(lang, u"mn")) {
       // This branch is currently no part of the spec.
       // See bug 1040668 comment 69 and comment 75.
-      aData->SetKeywordValue(eCSSProperty_text_emphasis_position,
+      aDecls.SetKeywordValue(eCSSProperty_text_emphasis_position,
                              NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT);
     }
   }
 }
 
 /**
  * Handle attributes common to all html elements
  */
 void
 nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(const nsMappedAttributes* aAttributes,
-                                                          GenericSpecifiedValues* aData)
+                                                          MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty__moz_user_modify)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty__moz_user_modify)) {
     const nsAttrValue* value =
       aAttributes->GetAttr(nsGkAtoms::contenteditable);
     if (value) {
       if (value->Equals(nsGkAtoms::_empty, eCaseMatters) ||
           value->Equals(nsGkAtoms::_true, eIgnoreCase)) {
-        aData->SetKeywordValue(eCSSProperty__moz_user_modify,
+        aDecls.SetKeywordValue(eCSSProperty__moz_user_modify,
                                StyleUserModify::ReadWrite);
       }
       else if (value->Equals(nsGkAtoms::_false, eIgnoreCase)) {
-          aData->SetKeywordValue(eCSSProperty__moz_user_modify,
+          aDecls.SetKeywordValue(eCSSProperty__moz_user_modify,
                                  StyleUserModify::ReadOnly);
       }
     }
   }
 
-  MapLangAttributeInto(aAttributes, aData);
+  MapLangAttributeInto(aAttributes, aDecls);
 }
 
 void
 nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
-                                              GenericSpecifiedValues* aData)
+                                              MappedDeclarations& aDecls)
 {
-  MapCommonAttributesIntoExceptHidden(aAttributes, aData);
-
-  if (!aData->PropertyIsSet(eCSSProperty_display)) {
+  MapCommonAttributesIntoExceptHidden(aAttributes, aDecls);
+
+  if (!aDecls.PropertyIsSet(eCSSProperty_display)) {
     if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
-      aData->SetKeywordValue(eCSSProperty_display, StyleDisplay::None);
+      aDecls.SetKeywordValue(eCSSProperty_display, StyleDisplay::None);
     }
   }
 }
 
 /* static */ const nsGenericHTMLElement::MappedAttributeEntry
 nsGenericHTMLElement::sCommonAttributeMap[] = {
   { &nsGkAtoms::contenteditable },
   { &nsGkAtoms::lang },
@@ -1270,213 +1270,213 @@ nsGenericHTMLElement::sBackgroundAttribu
 /* static */ const Element::MappedAttributeEntry
 nsGenericHTMLElement::sBackgroundColorAttributeMap[] = {
   { &nsGkAtoms::bgcolor },
   { nullptr }
 };
 
 void
 nsGenericHTMLElement::MapImageAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                                 GenericSpecifiedValues* aData)
+                                                 MappedDeclarations& aDecls)
 {
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
   if (value && value->Type() == nsAttrValue::eEnum) {
     int32_t align = value->GetEnumValue();
-    if (!aData->PropertyIsSet(eCSSProperty_float)) {
+    if (!aDecls.PropertyIsSet(eCSSProperty_float)) {
       if (align == NS_STYLE_TEXT_ALIGN_LEFT) {
-        aData->SetKeywordValue(eCSSProperty_float, StyleFloat::Left);
+        aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Left);
       } else if (align == NS_STYLE_TEXT_ALIGN_RIGHT) {
-        aData->SetKeywordValue(eCSSProperty_float, StyleFloat::Right);
+        aDecls.SetKeywordValue(eCSSProperty_float, StyleFloat::Right);
       }
     }
-    if (!aData->PropertyIsSet(eCSSProperty_vertical_align)) {
+    if (!aDecls.PropertyIsSet(eCSSProperty_vertical_align)) {
       switch (align) {
       case NS_STYLE_TEXT_ALIGN_LEFT:
       case NS_STYLE_TEXT_ALIGN_RIGHT:
         break;
       default:
-        aData->SetKeywordValue(eCSSProperty_vertical_align, align);
+        aDecls.SetKeywordValue(eCSSProperty_vertical_align, align);
         break;
       }
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapDivAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                               GenericSpecifiedValues* aData)
+                                               MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_text_align)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_text_align)) {
     // align: enum
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
     if (value && value->Type() == nsAttrValue::eEnum)
-      aData->SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
+      aDecls.SetKeywordValue(eCSSProperty_text_align, value->GetEnumValue());
   }
 }
 
 void
 nsGenericHTMLElement::MapVAlignAttributeInto(const nsMappedAttributes* aAttributes,
-                                             GenericSpecifiedValues* aData)
+                                             MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_vertical_align)) {
+  if (!aDecls.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());
+      aDecls.SetKeywordValue(eCSSProperty_vertical_align, value->GetEnumValue());
   }
 }
 
 void
 nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAttributes,
-                                                  GenericSpecifiedValues* aData)
+                                                  MappedDeclarations& aDecls)
 {
   const nsAttrValue* value;
 
   // hspace: value
   value = aAttributes->GetAttr(nsGkAtoms::hspace);
   if (value) {
     if (value->Type() == nsAttrValue::eInteger) {
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_left,
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_left,
                                   (float)value->GetIntegerValue());
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_right,
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_right,
                                   (float)value->GetIntegerValue());
     } else if (value->Type() == nsAttrValue::ePercent) {
-      aData->SetPercentValueIfUnset(eCSSProperty_margin_left,
+      aDecls.SetPercentValueIfUnset(eCSSProperty_margin_left,
                                     value->GetPercentValue());
-      aData->SetPercentValueIfUnset(eCSSProperty_margin_right,
+      aDecls.SetPercentValueIfUnset(eCSSProperty_margin_right,
                                     value->GetPercentValue());
     }
   }
 
   // vspace: value
   value = aAttributes->GetAttr(nsGkAtoms::vspace);
   if (value) {
     if (value->Type() == nsAttrValue::eInteger) {
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_top,
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_top,
                                   (float)value->GetIntegerValue());
-      aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom,
+      aDecls.SetPixelValueIfUnset(eCSSProperty_margin_bottom,
                                   (float)value->GetIntegerValue());
     } else if (value->Type() == nsAttrValue::ePercent) {
-      aData->SetPercentValueIfUnset(eCSSProperty_margin_top,
+      aDecls.SetPercentValueIfUnset(eCSSProperty_margin_top,
                                     value->GetPercentValue());
-      aData->SetPercentValueIfUnset(eCSSProperty_margin_bottom,
+      aDecls.SetPercentValueIfUnset(eCSSProperty_margin_bottom,
                                     value->GetPercentValue());
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapWidthAttributeInto(const nsMappedAttributes* aAttributes,
-                                            GenericSpecifiedValues* aData)
+                                            MappedDeclarations& aDecls)
 {
   // width: value
-  if (!aData->PropertyIsSet(eCSSProperty_width)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_width)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
     if (value && value->Type() == nsAttrValue::eInteger) {
-      aData->SetPixelValue(eCSSProperty_width,
+      aDecls.SetPixelValue(eCSSProperty_width,
                            (float)value->GetIntegerValue());
     } else if (value && value->Type() == nsAttrValue::ePercent) {
-      aData->SetPercentValue(eCSSProperty_width,
+      aDecls.SetPercentValue(eCSSProperty_width,
                              value->GetPercentValue());
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapHeightAttributeInto(const nsMappedAttributes* aAttributes,
-                                             GenericSpecifiedValues* aData)
+                                             MappedDeclarations& aDecls)
 {
   // height: value
-  if (!aData->PropertyIsSet(eCSSProperty_height)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_height)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
     if (value && value->Type() == nsAttrValue::eInteger) {
-      aData->SetPixelValue(eCSSProperty_height,
+      aDecls.SetPixelValue(eCSSProperty_height,
                            (float)value->GetIntegerValue());
     } else if (value && value->Type() == nsAttrValue::ePercent) {
-      aData->SetPercentValue(eCSSProperty_height,
+      aDecls.SetPercentValue(eCSSProperty_height,
                              value->GetPercentValue());
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
-                                                 GenericSpecifiedValues* aData)
+                                                 MappedDeclarations& aDecls)
 {
-  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
-  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
+  nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aDecls);
+  nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aDecls);
 }
 
 void
 nsGenericHTMLElement::MapImageBorderAttributeInto(const nsMappedAttributes* aAttributes,
-                                                  GenericSpecifiedValues* aData)
+                                                  MappedDeclarations& aDecls)
 {
   // border: pixels
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::border);
   if (!value)
     return;
 
   nscoord val = 0;
   if (value->Type() == nsAttrValue::eInteger)
     val = value->GetIntegerValue();
 
-  aData->SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val);
-  aData->SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val);
-  aData->SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val);
-  aData->SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val);
-
-  aData->SetKeywordValueIfUnset(eCSSProperty_border_top_style,
+  aDecls.SetPixelValueIfUnset(eCSSProperty_border_top_width, (float)val);
+  aDecls.SetPixelValueIfUnset(eCSSProperty_border_right_width, (float)val);
+  aDecls.SetPixelValueIfUnset(eCSSProperty_border_bottom_width, (float)val);
+  aDecls.SetPixelValueIfUnset(eCSSProperty_border_left_width, (float)val);
+
+  aDecls.SetKeywordValueIfUnset(eCSSProperty_border_top_style,
                                 NS_STYLE_BORDER_STYLE_SOLID);
-  aData->SetKeywordValueIfUnset(eCSSProperty_border_right_style,
+  aDecls.SetKeywordValueIfUnset(eCSSProperty_border_right_style,
                                 NS_STYLE_BORDER_STYLE_SOLID);
-  aData->SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
+  aDecls.SetKeywordValueIfUnset(eCSSProperty_border_bottom_style,
                                 NS_STYLE_BORDER_STYLE_SOLID);
-  aData->SetKeywordValueIfUnset(eCSSProperty_border_left_style,
+  aDecls.SetKeywordValueIfUnset(eCSSProperty_border_left_style,
                                 NS_STYLE_BORDER_STYLE_SOLID);
 
-  aData->SetCurrentColorIfUnset(eCSSProperty_border_top_color);
-  aData->SetCurrentColorIfUnset(eCSSProperty_border_right_color);
-  aData->SetCurrentColorIfUnset(eCSSProperty_border_bottom_color);
-  aData->SetCurrentColorIfUnset(eCSSProperty_border_left_color);
+  aDecls.SetCurrentColorIfUnset(eCSSProperty_border_top_color);
+  aDecls.SetCurrentColorIfUnset(eCSSProperty_border_right_color);
+  aDecls.SetCurrentColorIfUnset(eCSSProperty_border_bottom_color);
+  aDecls.SetCurrentColorIfUnset(eCSSProperty_border_left_color);
 }
 
 void
 nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
-                                        GenericSpecifiedValues* aData)
+                                        MappedDeclarations& aDecls)
 {
 
-  if (!aData->PropertyIsSet(eCSSProperty_background_image)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_background_image)) {
     // background
     nsAttrValue* value =
       const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
     if (value) {
-      aData->SetBackgroundImage(*value);
+      aDecls.SetBackgroundImage(*value);
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
-                                     GenericSpecifiedValues* aData)
+                                     MappedDeclarations& aDecls)
 {
-  if (!aData->PropertyIsSet(eCSSProperty_background_color)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_background_color)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
     nscolor color;
     if (value && value->GetColorValue(color)) {
-      aData->SetColorValue(eCSSProperty_background_color, color);
+      aDecls.SetColorValue(eCSSProperty_background_color, color);
     }
   }
 }
 
 void
 nsGenericHTMLElement::MapBackgroundAttributesInto(const nsMappedAttributes* aAttributes,
-                                                  GenericSpecifiedValues* aData)
+                                                  MappedDeclarations& aDecls)
 {
-  MapBackgroundInto(aAttributes, aData);
-  MapBGColorInto(aAttributes, aData);
+  MapBackgroundInto(aAttributes, aDecls);
+  MapBGColorInto(aAttributes, aDecls);
 }
 
 //----------------------------------------------------------------------
 
 int32_t
 nsGenericHTMLElement::GetIntAttr(nsAtom* aAttr, int32_t aDefault) const
 {
   const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -445,26 +445,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,
-                                      mozilla::GenericSpecifiedValues* aGenericData);
+                                      mozilla::MappedDeclarations&);
   /**
    * 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,
-                                                  mozilla::GenericSpecifiedValues* aGenericData);
+                                                  mozilla::MappedDeclarations&);
 
   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[];
@@ -472,126 +472,126 @@ 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,
-                                         mozilla::GenericSpecifiedValues* aGenericData);
+                                         mozilla::MappedDeclarations&);
 
   /**
    * 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,
-                                       mozilla::GenericSpecifiedValues* aGenericData);
+                                       mozilla::MappedDeclarations&);
 
   /**
    * 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,
-                                     mozilla::GenericSpecifiedValues* aGenericData);
+                                     mozilla::MappedDeclarations&);
 
   /**
    * 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,
-                                          mozilla::GenericSpecifiedValues* aGenericData);
+                                          mozilla::MappedDeclarations&);
   /**
    * 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,
-                                          mozilla::GenericSpecifiedValues* aGenericData);
+                                          mozilla::MappedDeclarations&);
   /**
    * 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,
-                                         mozilla::GenericSpecifiedValues* aGenericData);
+                                         mozilla::MappedDeclarations&);
 
   /**
    * 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,
-                                    mozilla::GenericSpecifiedValues* aGenericData);
+                                    mozilla::MappedDeclarations&);
   /**
    * 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,
-                                     mozilla::GenericSpecifiedValues* aGenericData);
+                                     mozilla::MappedDeclarations&);
   /**
    * 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,
-                                mozilla::GenericSpecifiedValues* aGenericData);
+                                mozilla::MappedDeclarations&);
   /**
    * 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,
-                             mozilla::GenericSpecifiedValues* aGenericData);
+                             mozilla::MappedDeclarations&);
   /**
    * 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,
-                                          mozilla::GenericSpecifiedValues* aGenericData);
+                                          mozilla::MappedDeclarations&);
   /**
    * 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,
-                                        mozilla::GenericSpecifiedValues* aGenericData);
+                                        mozilla::MappedDeclarations&);
   /**
    * 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
@@ -21,17 +21,17 @@
 #include "nsPresContext.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIScriptError.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
 
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
-#include "mozilla/GenericSpecifiedValuesInlines.h"
+#include "mozilla/MappedDeclarations.h"
 #include "mozilla/dom/ElementBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 // nsISupports methods:
 
@@ -479,43 +479,43 @@ nsMathMLElement::ParseNumericValue(const
   }
 
   aCSSValue.SetFloatValue(floatValue, cssUnit);
   return true;
 }
 
 void
 nsMathMLElement::MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
-                                         GenericSpecifiedValues* aData)
+                                         MappedDeclarations& aDecls)
 {
   // scriptsizemultiplier
   //
   // "Specifies the multiplier to be used to adjust font size due to changes
   // in scriptlevel.
   //
   // values: number
   // default: 0.71
   //
   const nsAttrValue* value =
     aAttributes->GetAttr(nsGkAtoms::scriptsizemultiplier_);
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty__moz_script_size_multiplier)) {
+      !aDecls.PropertyIsSet(eCSSProperty__moz_script_size_multiplier)) {
     nsAutoString str(value->GetStringValue());
     str.CompressWhitespace();
     // MathML numbers can't have leading '+'
     if (str.Length() > 0 && str.CharAt(0) != '+') {
       nsresult errorCode;
       float floatValue = str.ToFloat(&errorCode);
       // Negative scriptsizemultipliers are not parsed
       if (NS_SUCCEEDED(errorCode) && floatValue >= 0.0f) {
-        aData->SetNumberValue(eCSSProperty__moz_script_size_multiplier, floatValue);
+        aDecls.SetNumberValue(eCSSProperty__moz_script_size_multiplier, floatValue);
       } else {
         ReportParseErrorNoTag(str,
                               nsGkAtoms::scriptsizemultiplier_,
-                              aData->Document());
+                              aDecls.Document());
       }
     }
   }
 
   // scriptminsize
   //
   // "Specifies the minimum font size allowed due to changes in scriptlevel.
   // Note that this does not limit the font size due to changes to mathsize."
@@ -523,65 +523,65 @@ nsMathMLElement::MapMathMLAttributesInto
   // values: length
   // default: 8pt
   //
   // We don't allow negative values.
   // Unitless and percent values give a multiple of the default value.
   //
   value = aAttributes->GetAttr(nsGkAtoms::scriptminsize_);
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty__moz_script_min_size)) {
+      !aDecls.PropertyIsSet(eCSSProperty__moz_script_min_size)) {
     nsCSSValue scriptMinSize;
     ParseNumericValue(value->GetStringValue(), scriptMinSize,
                       PARSE_ALLOW_UNITLESS | CONVERT_UNITLESS_TO_PERCENT,
-                      aData->Document());
+                      aDecls.Document());
 
     if (scriptMinSize.GetUnit() == eCSSUnit_Percent) {
       scriptMinSize.SetFloatValue(8.0 * scriptMinSize.GetPercentValue(),
                                   eCSSUnit_Point);
     }
     if (scriptMinSize.GetUnit() != eCSSUnit_Null) {
-      aData->SetLengthValue(eCSSProperty__moz_script_min_size, scriptMinSize);
+      aDecls.SetLengthValue(eCSSProperty__moz_script_min_size, scriptMinSize);
     }
   }
 
   // scriptlevel
   //
   // "Changes the scriptlevel in effect for the children. When the value is
   // given without a sign, it sets scriptlevel to the specified value; when a
   // sign is given, it increments ("+") or decrements ("-") the current
   // value. (Note that large decrements can result in negative values of
   // scriptlevel, but these values are considered legal.)"
   //
   // values: ( "+" | "-" )? unsigned-integer
   // default: inherited
   //
   value = aAttributes->GetAttr(nsGkAtoms::scriptlevel_);
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty__moz_script_level)) {
+      !aDecls.PropertyIsSet(eCSSProperty__moz_script_level)) {
     nsAutoString str(value->GetStringValue());
     str.CompressWhitespace();
     if (str.Length() > 0) {
       nsresult errorCode;
       int32_t intValue = str.ToInteger(&errorCode);
       if (NS_SUCCEEDED(errorCode)) {
         // This is kind of cheesy ... if the scriptlevel has a sign,
         // then it's a relative value and we store the nsCSSValue as an
         // Integer to indicate that. Otherwise we store it as a Number
         // to indicate that the scriptlevel is absolute.
         char16_t ch = str.CharAt(0);
         if (ch == '+' || ch == '-') {
-          aData->SetIntValue(eCSSProperty__moz_script_level, intValue);
+          aDecls.SetIntValue(eCSSProperty__moz_script_level, intValue);
         } else {
-          aData->SetNumberValue(eCSSProperty__moz_script_level, intValue);
+          aDecls.SetNumberValue(eCSSProperty__moz_script_level, intValue);
         }
       } else {
         ReportParseErrorNoTag(str,
                               nsGkAtoms::scriptlevel_,
-                              aData->Document());
+                              aDecls.Document());
       }
     }
   }
 
   // mathsize
   //
   // "Specifies the size to display the token content. The values 'small' and
   // 'big' choose a size smaller or larger than the current font size, but
@@ -605,91 +605,91 @@ nsMathMLElement::MapMathMLAttributesInto
   bool parseSizeKeywords = true;
   value = aAttributes->GetAttr(nsGkAtoms::mathsize_);
   if (!value) {
     parseSizeKeywords = false;
     value = aAttributes->GetAttr(nsGkAtoms::fontsize_);
     if (value) {
       WarnDeprecated(nsGkAtoms::fontsize_->GetUTF16String(),
                      nsGkAtoms::mathsize_->GetUTF16String(),
-                     aData->Document());
+                     aDecls.Document());
     }
   }
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty_font_size)) {
+      !aDecls.PropertyIsSet(eCSSProperty_font_size)) {
     nsAutoString str(value->GetStringValue());
     nsCSSValue fontSize;
     if (!ParseNumericValue(str, fontSize, PARSE_SUPPRESS_WARNINGS |
                            PARSE_ALLOW_UNITLESS | CONVERT_UNITLESS_TO_PERCENT,
                            nullptr)
         && parseSizeKeywords) {
       static const char sizes[3][7] = { "small", "normal", "big" };
       static const int32_t values[MOZ_ARRAY_LENGTH(sizes)] = {
         NS_STYLE_FONT_SIZE_SMALL, NS_STYLE_FONT_SIZE_MEDIUM,
         NS_STYLE_FONT_SIZE_LARGE
       };
       str.CompressWhitespace();
       for (uint32_t i = 0; i < ArrayLength(sizes); ++i) {
         if (str.EqualsASCII(sizes[i])) {
-          aData->SetKeywordValue(eCSSProperty_font_size, values[i]);
+          aDecls.SetKeywordValue(eCSSProperty_font_size, values[i]);
           break;
         }
       }
     } else if (fontSize.GetUnit() == eCSSUnit_Percent) {
-      aData->SetPercentValue(eCSSProperty_font_size,
+      aDecls.SetPercentValue(eCSSProperty_font_size,
                              fontSize.GetPercentValue());
     } else if (fontSize.GetUnit() != eCSSUnit_Null) {
-      aData->SetLengthValue(eCSSProperty_font_size, fontSize);
+      aDecls.SetLengthValue(eCSSProperty_font_size, fontSize);
     }
   }
 
   // fontfamily
   //
   // "Should be the name of a font that may be available to a MathML renderer,
   // or a CSS font specification; See Section 6.5 Using CSS with MathML and
   // CSS for more information. Deprecated in favor of mathvariant."
   //
   // values: string
   //
   value = aAttributes->GetAttr(nsGkAtoms::fontfamily_);
   if (value) {
     WarnDeprecated(nsGkAtoms::fontfamily_->GetUTF16String(),
                    nsGkAtoms::mathvariant_->GetUTF16String(),
-                   aData->Document());
+                   aDecls.Document());
   }
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty_font_family)) {
-    aData->SetFontFamily(value->GetStringValue());
+      !aDecls.PropertyIsSet(eCSSProperty_font_family)) {
+    aDecls.SetFontFamily(value->GetStringValue());
   }
 
   // fontstyle
   //
   // "Specified the font style to use for the token. Deprecated in favor of
   //  mathvariant."
   //
   // values: "normal" | "italic"
   // default:	normal (except on <mi>)
   //
   // Note that the font-style property is reset in layout/style/ when
   // -moz-math-variant is specified.
   value = aAttributes->GetAttr(nsGkAtoms::fontstyle_);
   if (value) {
     WarnDeprecated(nsGkAtoms::fontstyle_->GetUTF16String(),
                    nsGkAtoms::mathvariant_->GetUTF16String(),
-                   aData->Document());
+                   aDecls.Document());
     if (value->Type() == nsAttrValue::eString &&
-        !aData->PropertyIsSet(eCSSProperty_font_style)) {
+        !aDecls.PropertyIsSet(eCSSProperty_font_style)) {
       nsAutoString str(value->GetStringValue());
       str.CompressWhitespace();
       // FIXME(emilio): This should use FontSlantStyle or what not. Or even
       // better, it looks deprecated since forever, we should just kill it.
       if (str.EqualsASCII("normal")) {
-        aData->SetKeywordValue(eCSSProperty_font_style, NS_FONT_STYLE_NORMAL);
+        aDecls.SetKeywordValue(eCSSProperty_font_style, NS_FONT_STYLE_NORMAL);
       } else if (str.EqualsASCII("italic")) {
-        aData->SetKeywordValue(eCSSProperty_font_style, NS_FONT_STYLE_ITALIC);
+        aDecls.SetKeywordValue(eCSSProperty_font_style, NS_FONT_STYLE_ITALIC);
       }
     }
   }
 
   // fontweight
   //
   // "Specified the font weight for the token. Deprecated in favor of
   // mathvariant."
@@ -698,26 +698,26 @@ nsMathMLElement::MapMathMLAttributesInto
   // default: normal
   //
   // Note that the font-weight property is reset in layout/style/ when
   // -moz-math-variant is specified.
   value = aAttributes->GetAttr(nsGkAtoms::fontweight_);
   if (value) {
     WarnDeprecated(nsGkAtoms::fontweight_->GetUTF16String(),
                    nsGkAtoms::mathvariant_->GetUTF16String(),
-                   aData->Document());
+                   aDecls.Document());
     if (value->Type() == nsAttrValue::eString &&
-        !aData->PropertyIsSet(eCSSProperty_font_weight)) {
+        !aDecls.PropertyIsSet(eCSSProperty_font_weight)) {
       nsAutoString str(value->GetStringValue());
       str.CompressWhitespace();
       if (str.EqualsASCII("normal")) {
-        aData->SetKeywordValue(eCSSProperty_font_weight,
+        aDecls.SetKeywordValue(eCSSProperty_font_weight,
                                FontWeight::Normal().ToFloat());
       } else if (str.EqualsASCII("bold")) {
-        aData->SetKeywordValue(eCSSProperty_font_weight,
+        aDecls.SetKeywordValue(eCSSProperty_font_weight,
                                FontWeight::Bold().ToFloat());
       }
     }
   }
 
   // mathvariant
   //
   // "Specifies the logical class of the token. Note that this class is more
@@ -726,17 +726,17 @@ nsMathMLElement::MapMathMLAttributesInto
   // values: "normal" | "bold" | "italic" | "bold-italic" | "double-struck" |
   // "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" |
   // "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" |
   // "monospace" | "initial" | "tailed" | "looped" | "stretched"
   // default: normal (except on <mi>)
   //
   value = aAttributes->GetAttr(nsGkAtoms::mathvariant_);
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty__moz_math_variant)) {
+      !aDecls.PropertyIsSet(eCSSProperty__moz_math_variant)) {
     nsAutoString str(value->GetStringValue());
     str.CompressWhitespace();
     static const char sizes[19][23] = {
       "normal", "bold", "italic", "bold-italic", "script", "bold-script",
       "fraktur", "double-struck", "bold-fraktur", "sans-serif",
       "bold-sans-serif", "sans-serif-italic", "sans-serif-bold-italic",
       "monospace", "initial", "tailed", "looped", "stretched"
     };
@@ -750,17 +750,17 @@ nsMathMLElement::MapMathMLAttributesInto
       NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC,
       NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC,
       NS_MATHML_MATHVARIANT_MONOSPACE, NS_MATHML_MATHVARIANT_INITIAL,
       NS_MATHML_MATHVARIANT_TAILED, NS_MATHML_MATHVARIANT_LOOPED,
       NS_MATHML_MATHVARIANT_STRETCHED
     };
     for (uint32_t i = 0; i < ArrayLength(sizes); ++i) {
       if (str.EqualsASCII(sizes[i])) {
-        aData->SetKeywordValue(eCSSProperty__moz_math_variant, values[i]);
+        aDecls.SetKeywordValue(eCSSProperty__moz_math_variant, values[i]);
         break;
       }
     }
   }
 
   // mathbackground
   //
   // "Specifies the background color to be used to fill in the bounding box of
@@ -780,23 +780,23 @@ nsMathMLElement::MapMathMLAttributesInto
   // default: "transparent"
   //
   value = aAttributes->GetAttr(nsGkAtoms::mathbackground_);
   if (!value) {
     value = aAttributes->GetAttr(nsGkAtoms::background);
     if (value) {
       WarnDeprecated(nsGkAtoms::background->GetUTF16String(),
                      nsGkAtoms::mathbackground_->GetUTF16String(),
-                     aData->Document());
+                     aDecls.Document());
     }
   }
   if (value) {
     nscolor color;
     if (value->GetColorValue(color)) {
-      aData->SetColorValueIfUnset(eCSSProperty_background_color, color);
+      aDecls.SetColorValueIfUnset(eCSSProperty_background_color, color);
     }
   }
 
   // mathcolor
   //
   // "Specifies the foreground color to use when drawing the components of this
   // element, such as the content for token elements or any lines, surds, or
   // other decorations. It also establishes the default mathcolor used for
@@ -813,47 +813,47 @@ nsMathMLElement::MapMathMLAttributesInto
   // default: inherited
   //
   value = aAttributes->GetAttr(nsGkAtoms::mathcolor_);
   if (!value) {
     value = aAttributes->GetAttr(nsGkAtoms::color);
     if (value) {
       WarnDeprecated(nsGkAtoms::color->GetUTF16String(),
                      nsGkAtoms::mathcolor_->GetUTF16String(),
-                     aData->Document());
+                     aDecls.Document());
     }
   }
   nscolor color;
   if (value && value->GetColorValue(color)) {
-    aData->SetColorValueIfUnset(eCSSProperty_color, color);
+    aDecls.SetColorValueIfUnset(eCSSProperty_color, color);
   }
 
   // width
   //
   // "Specifies the desired width of the entire table and is intended for
   // visual user agents. When the value is a percentage value, the value is
   // relative to the horizontal space a MathML renderer has available for the
   // math element. When the value is "auto", the MathML renderer should
   // calculate the table width from its contents using whatever layout
   // algorithm it chooses. "
   //
   // values: "auto" | length
   // default: auto
   //
-  if (!aData->PropertyIsSet(eCSSProperty_width)) {
+  if (!aDecls.PropertyIsSet(eCSSProperty_width)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
     nsCSSValue width;
     // This does not handle auto and unitless values
     if (value && value->Type() == nsAttrValue::eString) {
-      ParseNumericValue(value->GetStringValue(), width, 0, aData->Document());
+      ParseNumericValue(value->GetStringValue(), width, 0, aDecls.Document());
       if (width.GetUnit() == eCSSUnit_Percent) {
-        aData->SetPercentValue(eCSSProperty_width,
+        aDecls.SetPercentValue(eCSSProperty_width,
                                width.GetPercentValue());
       } else if (width.GetUnit() != eCSSUnit_Null) {
-        aData->SetLengthValue(eCSSProperty_width, width);
+        aDecls.SetLengthValue(eCSSProperty_width, width);
       }
     }
   }
 
   // dir
   //
   // Overall Directionality of Mathematics Formulas:
   // "The overall directionality for a formula, basically the direction of the
@@ -870,25 +870,25 @@ nsMathMLElement::MapMathMLAttributesInto
   // see Section 3.1.5.1 Overall Directionality of Mathematics Formulas for
   // further discussion. It has no effect on mspace."
   //
   // values: "ltr" | "rtl"
   // default: inherited
   //
   value = aAttributes->GetAttr(nsGkAtoms::dir);
   if (value && value->Type() == nsAttrValue::eString &&
-      !aData->PropertyIsSet(eCSSProperty_direction)) {
+      !aDecls.PropertyIsSet(eCSSProperty_direction)) {
     nsAutoString str(value->GetStringValue());
     static const char dirs[][4] = { "ltr", "rtl" };
     static const int32_t dirValues[MOZ_ARRAY_LENGTH(dirs)] = {
       NS_STYLE_DIRECTION_LTR, NS_STYLE_DIRECTION_RTL
     };
     for (uint32_t i = 0; i < ArrayLength(dirs); ++i) {
       if (str.EqualsASCII(dirs[i])) {
-        aData->SetKeywordValue(eCSSProperty_direction, dirValues[i]);
+        aDecls.SetKeywordValue(eCSSProperty_direction, dirValues[i]);
         break;
       }
     }
   }
 }
 
 void
 nsMathMLElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -61,17 +61,17 @@ public:
                                    uint32_t        aFlags);
 
   static bool ParseNumericValue(const nsString& aString,
                                 nsCSSValue&     aCSSValue,
                                 uint32_t        aFlags,
                                 nsIDocument*    aDocument);
 
   static void MapMathMLAttributesInto(const nsMappedAttributes* aAttributes,
-                                      mozilla::GenericSpecifiedValues* aGenericData);
+                                      mozilla::MappedDeclarations&);
 
   void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      mozilla::EventChainPostVisitor& aVisitor) override;
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                  bool aPreallocateChildren) const override;
   virtual mozilla::EventStates IntrinsicState() const override;
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
deleted file mode 100644
--- a/layout/style/GenericSpecifiedValues.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- 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 "mozilla/ServoUtils.h"
-#include "mozilla/FontPropertyTypes.h"
-#include "nsCSSPropertyID.h"
-#include "nsCSSValue.h"
-#include "nsColor.h"
-
-class nsAttrValue;
-
-namespace mozilla {
-
-class ServoSpecifiedValues;
-
-// 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
-{
-protected:
-  explicit GenericSpecifiedValues(nsIDocument* aDoc)
-    : mDocument(aDoc)
-  {}
-
-public:
-  MOZ_DECL_STYLO_METHODS(nsRuleData, ServoSpecifiedValues)
-
-  nsIDocument* Document()
-  {
-    return mDocument;
-  }
-
-  // Check if we already contain a certain longhand
-  inline bool PropertyIsSet(nsCSSPropertyID aId);
-
-  // Set a property to an identifier (string)
-  inline void SetIdentStringValue(nsCSSPropertyID aId, const nsString& aValue);
-  inline void SetIdentStringValueIfUnset(nsCSSPropertyID aId,
-                                         const nsString& aValue);
-
-  inline void SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue);
-  inline void SetIdentAtomValueIfUnset(nsCSSPropertyID aId, nsAtom* aValue);
-
-  // Set a property to a keyword (usually NS_STYLE_* or StyleFoo::*)
-  inline void SetKeywordValue(nsCSSPropertyID aId, int32_t aValue);
-  inline void SetKeywordValueIfUnset(nsCSSPropertyID aId, int32_t aValue);
-
-  template<typename T,
-           typename = typename std::enable_if<std::is_enum<T>::value>::type>
-  void SetKeywordValue(nsCSSPropertyID aId, T aValue)
-  {
-    static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
-                  "aValue must be an enum that fits within 32 bits");
-    SetKeywordValue(aId, static_cast<int32_t>(aValue));
-  }
-  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
-  inline void SetIntValue(nsCSSPropertyID aId, int32_t aValue);
-  // Set a property to a pixel value
-  inline void SetPixelValue(nsCSSPropertyID aId, float aValue);
-  inline void SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue);
-
-  inline void SetLengthValue(nsCSSPropertyID aId, nsCSSValue aValue);
-
-  // Set a property to a number value
-  inline void SetNumberValue(nsCSSPropertyID aId, float aValue);
-
-  // Set a property to a percent value
-  inline void SetPercentValue(nsCSSPropertyID aId, float aValue);
-  inline void SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue);
-
-  // Set a property to `auto`
-  inline void SetAutoValue(nsCSSPropertyID aId);
-  inline void SetAutoValueIfUnset(nsCSSPropertyID aId);
-
-  // Set a property to `currentcolor`
-  inline void SetCurrentColor(nsCSSPropertyID aId);
-  inline void SetCurrentColorIfUnset(nsCSSPropertyID aId);
-
-  // Set a property to an RGBA nscolor value
-  inline void SetColorValue(nsCSSPropertyID aId, nscolor aValue);
-  inline void SetColorValueIfUnset(nsCSSPropertyID aId, nscolor aValue);
-
-  // Set font-family to a string
-  inline void SetFontFamily(const nsString& aValue);
-  // Add a quirks-mode override to the decoration color of elements nested in <a>
-  inline void SetTextDecorationColorOverride();
-  inline void SetBackgroundImage(nsAttrValue& value);
-
-  nsIDocument* const mDocument;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_GenericSpecifiedValues_h
deleted file mode 100644
--- a/layout/style/GenericSpecifiedValuesInlines.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* -*- 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/. */
-
-/*
- * Inlined methods for GenericSpecifiedValues. Will just redirect to
- * nsRuleData methods when compiled without stylo, but will do
- * virtual dispatch (by checking which kind of container it is)
- * in stylo mode.
- */
-
-#ifndef mozilla_GenericSpecifiedValuesInlines_h
-#define mozilla_GenericSpecifiedValuesInlines_h
-
-#include "mozilla/GenericSpecifiedValues.h"
-#include "mozilla/ServoSpecifiedValues.h"
-
-namespace mozilla {
-
-MOZ_DEFINE_STYLO_METHODS(GenericSpecifiedValues,
-                         nsRuleData,
-                         ServoSpecifiedValues)
-
-bool
-GenericSpecifiedValues::PropertyIsSet(nsCSSPropertyID aId)
-{
-  MOZ_STYLO_FORWARD(PropertyIsSet, (aId))
-}
-
-void
-GenericSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
-                                            const nsString& aValue)
-{
-  MOZ_STYLO_FORWARD(SetIdentStringValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetIdentStringValueIfUnset(nsCSSPropertyID aId,
-                                                   const nsString& aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetIdentStringValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue)
-{
-  MOZ_STYLO_FORWARD(SetIdentAtomValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetIdentAtomValueIfUnset(nsCSSPropertyID aId,
-                                                 nsAtom* aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetIdentAtomValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
-{
-
-  return AsServo()->SetKeywordValue(aId, aValue);
-}
-
-void
-GenericSpecifiedValues::SetKeywordValueIfUnset(nsCSSPropertyID aId,
-                                               int32_t aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetKeywordValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetIntValue(nsCSSPropertyID aId, int32_t aValue)
-{
-  MOZ_STYLO_FORWARD(SetIntValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetPixelValue(nsCSSPropertyID aId, float aValue)
-{
-  MOZ_STYLO_FORWARD(SetPixelValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetPixelValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetLengthValue(nsCSSPropertyID aId, nsCSSValue aValue)
-{
-  MOZ_STYLO_FORWARD(SetLengthValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetNumberValue(nsCSSPropertyID aId, float aValue)
-{
-  MOZ_STYLO_FORWARD(SetNumberValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetPercentValue(nsCSSPropertyID aId, float aValue)
-{
-  MOZ_STYLO_FORWARD(SetPercentValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetPercentValueIfUnset(nsCSSPropertyID aId,
-                                               float aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetPercentValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetAutoValue(nsCSSPropertyID aId)
-{
-  MOZ_STYLO_FORWARD(SetAutoValue, (aId))
-}
-
-void
-GenericSpecifiedValues::SetAutoValueIfUnset(nsCSSPropertyID aId)
-{
-  if (!PropertyIsSet(aId)) {
-    SetAutoValue(aId);
-  }
-}
-
-void
-GenericSpecifiedValues::SetCurrentColor(nsCSSPropertyID aId)
-{
-  MOZ_STYLO_FORWARD(SetCurrentColor, (aId))
-}
-
-void
-GenericSpecifiedValues::SetCurrentColorIfUnset(nsCSSPropertyID aId)
-{
-  if (!PropertyIsSet(aId)) {
-    SetCurrentColor(aId);
-  }
-}
-
-void
-GenericSpecifiedValues::SetColorValue(nsCSSPropertyID aId, nscolor aValue)
-{
-  MOZ_STYLO_FORWARD(SetColorValue, (aId, aValue))
-}
-
-void
-GenericSpecifiedValues::SetColorValueIfUnset(nsCSSPropertyID aId,
-                                             nscolor aValue)
-{
-  if (!PropertyIsSet(aId)) {
-    SetColorValue(aId, aValue);
-  }
-}
-
-void
-GenericSpecifiedValues::SetFontFamily(const nsString& aValue)
-{
-  MOZ_STYLO_FORWARD(SetFontFamily, (aValue))
-}
-
-void
-GenericSpecifiedValues::SetTextDecorationColorOverride()
-{
-  MOZ_STYLO_FORWARD(SetTextDecorationColorOverride, ())
-}
-
-void
-GenericSpecifiedValues::SetBackgroundImage(nsAttrValue& aValue)
-{
-  MOZ_STYLO_FORWARD(SetBackgroundImage, (aValue))
-}
-
-} // namespace mozilla
-
-#endif // mozilla_GenericSpecifiedValuesInlines_h
new file mode 100644
--- /dev/null
+++ b/layout/style/MappedDeclarations.cpp
@@ -0,0 +1,41 @@
+/* -*- 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/. */
+
+#include "mozillla/MappedDeclarations.h"
+
+namespace mozilla {
+
+void
+MappedDeclarations::SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue)
+{
+  Servo_DeclarationBlock_SetIdentStringValue(mDecl, aId, aValue);
+  if (aId == eCSSProperty__x_lang) {
+    // This forces the lang prefs result to be cached so that we can access them
+    // off main thread during traversal.
+    //
+    // FIXME(emilio): Can we move mapped attribute declarations across
+    // documents? Isn't this wrong in that case? This is pretty out of place
+    // anyway.
+    if (nsPresContext* pc = mDocument->GetPresContext()) {
+      pc->ForceCacheLang(aValue);
+    }
+  }
+}
+
+void
+MappedDeclarations::SetBackgroundImage(const nsAttrValue& aValue)
+{
+  if (aValue.Type() != nsAttrValue::eURL) {
+    return;
+  }
+  // FIXME(emilio): Going through URL parsing again seems slightly wasteful.
+  nsAutoString str;
+  aValue.ToString(str);
+  Servo_DeclarationBlock_SetBackgroundImage(
+    mDecl, str, mDocument->DefaultStyleAttrURLData());
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/style/MappedDeclarations.h
@@ -0,0 +1,217 @@
+/* -*- 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/. */
+
+/* Representation of a declaration block used for attribute mapping */
+
+#ifndef mozilla_MappedDeclarations_h
+#define mozilla_MappedDeclarations_h
+
+#include "mozilla/FontPropertyTypes.h"
+#include "mozilla/ServoBindingTypes.h"
+#include "mozilla/ServoBindings.h"
+#include "nsCSSPropertyID.h"
+#include "nsCSSValue.h"
+#include "nsColor.h"
+
+class nsAttrValue;
+
+namespace mozilla {
+
+// This provides a convenient interface for attribute mappers
+// (MapAttributesIntoRule) to modify the presentation attribute declaration
+// block for a given element.
+class MappedDeclarations final
+{
+public:
+  explicit MappedDeclarations(nsIDocument* aDoc,
+                              already_AddRefed<RawServoDeclarationBlock> aDecls)
+    : mDocument(aDoc)
+    , mDecl(aDecls)
+  {
+    MOZ_ASSERT(mDecl);
+  }
+
+  ~MappedDeclarations()
+  {
+    MOZ_ASSERT(!mDecl, "Forgot to take the block?");
+  }
+
+  nsIDocument* Document()
+  {
+    return mDocument;
+  }
+
+  already_AddRefed<RawServoDeclarationBlock> TakeDeclarationBlock()
+  {
+    MOZ_ASSERT(mDecl);
+    return mDecl.forget();
+  }
+
+  // Check if we already contain a certain longhand
+  bool PropertyIsSet(nsCSSPropertyID aId) const
+  {
+    return Servo_DeclarationBlock_PropertyIsSet(mDecl, aId);
+  }
+
+  // Set a property to an identifier (string)
+  void SetIdentStringValue(nsCSSPropertyID aId, const nsString& aValue)
+  {
+    RefPtr<nsAtom> atom = NS_AtomizeMainThread(aValue);
+    SetIdentAtomValue(aId, atom);
+  }
+
+  void SetIdentStringValueIfUnset(nsCSSPropertyID aId, const nsString& aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetIdentStringValue(aId, aValue);
+    }
+  }
+
+  void SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue);
+
+  void SetIdentAtomValueIfUnset(nsCSSPropertyID aId, nsAtom* aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetIdentAtomValue(aId, aValue);
+    }
+  }
+
+  // Set a property to a keyword (usually NS_STYLE_* or StyleFoo::*)
+  void SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
+  {
+    Servo_DeclarationBlock_SetKeywordValue(mDecl, aId, aValue);
+  }
+
+  void SetKeywordValueIfUnset(nsCSSPropertyID aId, int32_t aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetKeywordValue(aId, aValue);
+    }
+  }
+
+  template<typename T,
+           typename = typename std::enable_if<std::is_enum<T>::value>::type>
+  void SetKeywordValue(nsCSSPropertyID aId, T aValue)
+  {
+    static_assert(mozilla::EnumTypeFitsWithin<T, int32_t>::value,
+                  "aValue must be an enum that fits within 32 bits");
+    SetKeywordValue(aId, static_cast<int32_t>(aValue));
+  }
+  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
+  void SetIntValue(nsCSSPropertyID aId, int32_t aValue)
+  {
+    Servo_DeclarationBlock_SetIntValue(mDecl, aId, aValue);
+  }
+
+  // Set a property to a pixel value
+  void SetPixelValue(nsCSSPropertyID aId, float aValue)
+  {
+    Servo_DeclarationBlock_SetPixelValue(mDecl, aId, aValue);
+  }
+
+  void SetPixelValueIfUnset(nsCSSPropertyID aId, float aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetPixelValue(aId, aValue);
+    }
+  }
+
+  void SetLengthValue(nsCSSPropertyID aId, const nsCSSValue& aValue)
+  {
+    MOZ_ASSERT(aValue.IsLengthUnit());
+    Servo_DeclarationBlock_SetLengthValue(
+      mDecl, aId, aValue.GetFloatValue(), aValue.GetUnit());
+  }
+
+  // Set a property to a number value
+  void SetNumberValue(nsCSSPropertyID aId, float aValue)
+  {
+    Servo_DeclarationBlock_SetNumberValue(mDecl, aId, aValue);
+  }
+
+  // Set a property to a percent value
+  void SetPercentValue(nsCSSPropertyID aId, float aValue)
+  {
+    Servo_DeclarationBlock_SetPercentValue(mDecl, aId, aValue);
+  }
+
+  void SetPercentValueIfUnset(nsCSSPropertyID aId, float aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetPercentValue(aId, aValue);
+    }
+  }
+
+  // Set a property to `auto`
+  void SetAutoValue(nsCSSPropertyID aId)
+  {
+    Servo_DeclarationBlock_SetAutoValue(mDecl, aId);
+  }
+
+  void SetAutoValueIfUnset(nsCSSPropertyID aId)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetAutoValue(aId);
+    }
+  }
+
+  // Set a property to `currentcolor`
+  void SetCurrentColor(nsCSSPropertyID aId)
+  {
+    Servo_DeclarationBlock_SetCurrentColor(mDecl, aId);
+  }
+
+  void SetCurrentColorIfUnset(nsCSSPropertyID aId)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetCurrentColor(aId);
+    }
+  }
+
+  // Set a property to an RGBA nscolor value
+  void SetColorValue(nsCSSPropertyID aId, nscolor aValue)
+  {
+    Servo_DeclarationBlock_SetColorValue(mDecl, aId, aValue);
+  }
+
+  void SetColorValueIfUnset(nsCSSPropertyID aId, nscolor aValue)
+  {
+    if (!PropertyIsSet(aId)) {
+      SetColorValue(aId, aValue);
+    }
+  }
+
+  // Set font-family to a string
+  void SetFontFamily(const nsString& aValue)
+  {
+    Servo_DeclarationBlock_SetFontFamily(mDecl, aValue);
+  }
+
+  // Add a quirks-mode override to the decoration color of elements nested in <a>
+  void SetTextDecorationColorOverride()
+  {
+    Servo_DeclarationBlock_SetTextDecorationColorOverride(mDecl);
+  }
+
+  void SetBackgroundImage(const nsAttrValue& value);
+
+private:
+  nsIDocument* const mDocument;
+  RefPtr<RawServoDeclarationBlock> mDecl;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_MappedDeclarations_h
deleted file mode 100644
--- a/layout/style/ServoSpecifiedValues.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -*- 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/. */
-
-#include "mozilla/ServoBindings.h"
-#include "mozilla/ServoSpecifiedValues.h"
-
-using namespace mozilla;
-
-bool
-ServoSpecifiedValues::PropertyIsSet(nsCSSPropertyID aId)
-{
-  return Servo_DeclarationBlock_PropertyIsSet(mDecl, aId);
-}
-
-void
-ServoSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
-                                          const nsString& aValue)
-{
-  RefPtr<nsAtom> atom = NS_Atomize(aValue);
-  SetIdentAtomValue(aId, atom);
-}
-
-void
-ServoSpecifiedValues::SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue)
-{
-  Servo_DeclarationBlock_SetIdentStringValue(mDecl, aId, aValue);
-  if (aId == eCSSProperty__x_lang) {
-    // This forces the lang prefs result to be cached so that we can access them
-    // off main thread during traversal.
-    //
-    // FIXME(emilio): Can we move mapped attribute declarations across
-    // documents? Isn't this wrong in that case? This is pretty out of place
-    // anyway.
-    if (nsPresContext* pc = mDocument->GetPresContext()) {
-      pc->ForceCacheLang(aValue);
-    }
-  }
-}
-
-void
-ServoSpecifiedValues::SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
-{
-  Servo_DeclarationBlock_SetKeywordValue(mDecl, aId, aValue);
-}
-
-void
-ServoSpecifiedValues::SetIntValue(nsCSSPropertyID aId, int32_t aValue)
-{
-  Servo_DeclarationBlock_SetIntValue(mDecl, aId, aValue);
-}
-
-void
-ServoSpecifiedValues::SetPixelValue(nsCSSPropertyID aId, float aValue)
-{
-  Servo_DeclarationBlock_SetPixelValue(mDecl, aId, aValue);
-}
-
-void
-ServoSpecifiedValues::SetLengthValue(nsCSSPropertyID aId, nsCSSValue aValue)
-{
-  MOZ_ASSERT(aValue.IsLengthUnit());
-  Servo_DeclarationBlock_SetLengthValue(
-    mDecl, aId, aValue.GetFloatValue(), aValue.GetUnit());
-}
-
-void
-ServoSpecifiedValues::SetNumberValue(nsCSSPropertyID aId, float aValue)
-{
-  Servo_DeclarationBlock_SetNumberValue(mDecl, aId, aValue);
-}
-
-void
-ServoSpecifiedValues::SetPercentValue(nsCSSPropertyID aId, float aValue)
-{
-  Servo_DeclarationBlock_SetPercentValue(mDecl, aId, aValue);
-}
-
-void
-ServoSpecifiedValues::SetAutoValue(nsCSSPropertyID aId)
-{
-  Servo_DeclarationBlock_SetAutoValue(mDecl, aId);
-}
-
-void
-ServoSpecifiedValues::SetCurrentColor(nsCSSPropertyID aId)
-{
-  Servo_DeclarationBlock_SetCurrentColor(mDecl, aId);
-}
-
-void
-ServoSpecifiedValues::SetColorValue(nsCSSPropertyID aId, nscolor aColor)
-{
-  Servo_DeclarationBlock_SetColorValue(mDecl, aId, aColor);
-}
-
-void
-ServoSpecifiedValues::SetFontFamily(const nsString& aValue)
-{
-  Servo_DeclarationBlock_SetFontFamily(mDecl, aValue);
-}
-
-void
-ServoSpecifiedValues::SetTextDecorationColorOverride()
-{
-  Servo_DeclarationBlock_SetTextDecorationColorOverride(mDecl);
-}
-
-void
-ServoSpecifiedValues::SetBackgroundImage(nsAttrValue& aValue)
-{
-  if (aValue.Type() != nsAttrValue::eURL) {
-    return;
-  }
-  nsAutoString str;
-  aValue.ToString(str);
-  Servo_DeclarationBlock_SetBackgroundImage(
-    mDecl, str, mDocument->DefaultStyleAttrURLData());
-}
deleted file mode 100644
--- a/layout/style/ServoSpecifiedValues.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- 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/. */
-
-/*
- * Servo-backed specified value store, to be used when mapping presentation
- * attributes
- */
-
-#ifndef mozilla_ServoSpecifiedValues_h
-#define mozilla_ServoSpecifiedValues_h
-
-#include "mozilla/GenericSpecifiedValues.h"
-#include "mozilla/ServoBindingTypes.h"
-
-namespace mozilla {
-
-class ServoSpecifiedValues final : public GenericSpecifiedValues
-{
-public:
-  ServoSpecifiedValues(nsIDocument* aDocument, RawServoDeclarationBlock* aDecl)
-    : GenericSpecifiedValues(aDocument)
-    , mDecl(aDecl)
-  {}
-
-  // GenericSpecifiedValues overrides
-  bool PropertyIsSet(nsCSSPropertyID aId);
-
-  void SetIdentStringValue(nsCSSPropertyID aId, const nsString& aValue);
-
-  void SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue);
-
-  void SetKeywordValue(nsCSSPropertyID aId, int32_t aValue);
-
-  void SetIntValue(nsCSSPropertyID aId, int32_t aValue);
-
-  void SetPixelValue(nsCSSPropertyID aId, float aValue);
-
-  void SetLengthValue(nsCSSPropertyID aId, nsCSSValue aValue);
-
-  void SetNumberValue(nsCSSPropertyID aId, float aValue);
-
-  void SetPercentValue(nsCSSPropertyID aId, float aValue);
-
-  void SetAutoValue(nsCSSPropertyID aId);
-
-  void SetCurrentColor(nsCSSPropertyID aId);
-
-  void SetColorValue(nsCSSPropertyID aId, nscolor aValue);
-
-  void SetFontFamily(const nsString& aValue);
-  void SetTextDecorationColorOverride();
-  void SetBackgroundImage(nsAttrValue& aValue);
-
-private:
-  RefPtr<RawServoDeclarationBlock> mDecl;
-};
-
-} // namespace mozilla
-
-#endif // mozilla_ServoSpecifiedValues_h
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -64,33 +64,31 @@ EXPORTS.mozilla += [
     'BindingStyleRule.h',
     'CachedInheritingStyles.h',
     'ComputedStyle.h',
     'ComputedStyleInlines.h',
     'CSSEnabledState.h',
     'CSSPropFlags.h',
     'DeclarationBlock.h',
     'DocumentStyleRootIterator.h',
-    'GenericSpecifiedValues.h',
-    'GenericSpecifiedValuesInlines.h',
     'LayerAnimationInfo.h',
+    'MappedDeclarations.h',
     'MediaFeatureChange.h',
     'PostTraversalTask.h',
     'PreloadedStyleSheet.h',
     'ServoArcTypeList.h',
     'ServoBindingList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
     'ServoComputedData.h',
     'ServoComputedDataInlines.h',
     'ServoCSSParser.h',
     'ServoCSSRuleList.h',
     'ServoElementSnapshot.h',
     'ServoElementSnapshotTable.h',
-    'ServoSpecifiedValues.h',
     'ServoStyleSet.h',
     'ServoStyleSetInlines.h',
     'ServoTraversalStatistics.h',
     'ServoTypes.h',
     'ServoUtils.h',
     'SheetType.h',
     'StyleAnimationValue.h',
     'StyleComplexColor.h',
@@ -160,16 +158,17 @@ UNIFIED_SOURCES += [
     'ErrorReporter.cpp',
     'FontFace.cpp',
     'FontFaceSet.cpp',
     'FontFaceSetIterator.cpp',
     'GroupRule.cpp',
     'ImageLoader.cpp',
     'LayerAnimationInfo.cpp',
     'Loader.cpp',
+    'MappedDeclarations.cpp',
     'MediaList.cpp',
     'MediaQueryList.cpp',
     'nsAnimationManager.cpp',
     'nsComputedDOMStyle.cpp',
     'nsCSSKeywords.cpp',
     'nsCSSProps.cpp',
     'nsCSSValue.cpp',
     'nsDOMCSSAttrDeclaration.cpp',
@@ -191,17 +190,16 @@ UNIFIED_SOURCES += [
     'nsTransitionManager.cpp',
     'PostTraversalTask.cpp',
     'PreloadedStyleSheet.cpp',
     'Rule.cpp',
     'ServoBindings.cpp',
     'ServoCSSParser.cpp',
     'ServoCSSRuleList.cpp',
     'ServoElementSnapshot.cpp',
-    'ServoSpecifiedValues.cpp',
     'ServoStyleSet.cpp',
     'StreamLoader.cpp',
     'StyleAnimationValue.cpp',
     'StyleComplexColor.cpp',
     'StyleSheet.cpp',
     'URLExtraData.cpp',
 ]