Bug 1428339: Make attribute mapping work without a pres context. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 05 Jan 2018 13:47:04 +0100
changeset 452687 9ff344df5f646380d30ea5b41e8bcfd5d2c7a27c
parent 452686 395fc0edae580ac7f72a8b9fe53414454360509b
child 452688 bf43b5b793d6cfd4fd09e34150575959a3ef4980
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1428339
milestone59.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 1428339: Make attribute mapping work without a pres context. r=heycam MozReview-Commit-ID: FisYWoArX0N
dom/base/nsMappedAttributes.cpp
dom/base/nsMappedAttributes.h
dom/html/HTMLBodyElement.cpp
dom/html/HTMLFontElement.cpp
dom/html/HTMLHRElement.cpp
dom/html/HTMLTableCellElement.cpp
dom/html/HTMLTableElement.cpp
dom/html/nsGenericHTMLElement.cpp
dom/mathml/nsMathMLElement.cpp
layout/style/GenericSpecifiedValues.h
layout/style/GenericSpecifiedValuesInlines.h
layout/style/ServoSpecifiedValues.cpp
layout/style/ServoSpecifiedValues.h
layout/style/ServoStyleSet.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
layout/style/nsRuleData.cpp
layout/style/nsRuleData.h
layout/style/nsRuleNode.cpp
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -355,19 +355,19 @@ nsMappedAttributes::SizeOfIncludingThis(
   size_t n = aMallocSizeOf(this);
   for (uint16_t i = 0; i < mAttrCount; ++i) {
     n += Attrs()[i].mValue.SizeOfExcludingThis(aMallocSizeOf);
   }
   return n;
 }
 
 void
-nsMappedAttributes::LazilyResolveServoDeclaration(nsPresContext* aContext)
+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(aContext, mServoStyle.get());
+    ServoSpecifiedValues servo = ServoSpecifiedValues(aDoc, mServoStyle.get());
     (*mRuleMapper)(this, &servo);
   }
 }
--- a/dom/base/nsMappedAttributes.h
+++ b/dom/base/nsMappedAttributes.h
@@ -70,17 +70,17 @@ public:
   // Remove the attr at position aPos.  The value of the attr is placed in
   // aValue; any value that was already in aValue is destroyed.
   void RemoveAttrAt(uint32_t aPos, nsAttrValue& aValue);
   const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
   int32_t IndexOfAttr(nsAtom* aLocalName) const;
 
   // Apply the contained mapper to the contained set of servo rules,
   // unless the servo rules have already been initialized.
-  void LazilyResolveServoDeclaration(nsPresContext* aPresContext);
+  void LazilyResolveServoDeclaration(nsIDocument* aDocument);
 
   // Obtain the contained servo declaration block
   // May return null if called before the inner block
   // has been (lazily) resolved
   const RefPtr<RawServoDeclarationBlock>& GetServoStyle() const
   {
     return mServoStyle;
   }
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -162,17 +162,17 @@ HTMLBodyElement::MapAttributesIntoRule(c
         }
         aData->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->mPresContext->GetDocShell());
+      nsCOMPtr<nsIDocShell> docShell(aData->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) {
@@ -192,51 +192,45 @@ HTMLBodyElement::MapAttributesIntoRule(c
           }
         }
       }
     }
   }
 
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
     // When display if first asked for, go ahead and get our colors set up.
-    nsIPresShell *presShell = aData->PresContext()->GetPresShell();
-    if (presShell) {
-      nsIDocument *doc = presShell->GetDocument();
-      if (doc) {
-        nsHTMLStyleSheet* styleSheet = doc->GetAttributeStyleSheet();
-        if (styleSheet) {
-          const nsAttrValue* value;
-          nscolor color;
-          value = aAttributes->GetAttr(nsGkAtoms::link);
-          if (value && value->GetColorValue(color)) {
-            styleSheet->SetLinkColor(color);
-          }
+    if (nsHTMLStyleSheet* styleSheet = aData->Document()->GetAttributeStyleSheet()) {
+      const nsAttrValue* value;
+      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)) {
-            styleSheet->SetActiveLinkColor(color);
-          }
+      value = aAttributes->GetAttr(nsGkAtoms::alink);
+      if (value && value->GetColorValue(color)) {
+        styleSheet->SetActiveLinkColor(color);
+      }
 
-          value = aAttributes->GetAttr(nsGkAtoms::vlink);
-          if (value && value->GetColorValue(color)) {
-            styleSheet->SetVisitedLinkColor(color);
-          }
-        }
+      value = aAttributes->GetAttr(nsGkAtoms::vlink);
+      if (value && value->GetColorValue(color)) {
+        styleSheet->SetVisitedLinkColor(color);
       }
     }
   }
 
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
     if (!aData->PropertyIsSet(eCSSProperty_color) &&
-        aData->PresContext()->UseDocumentColors()) {
+        !aData->ShouldIgnoreColors()) {
       // color: color
       nscolor color;
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::text);
-      if (value && value->GetColorValue(color))
+      if (value && value->GetColorValue(color)) {
         aData->SetColorValue(eCSSProperty_color, color);
+      }
     }
   }
 
   nsGenericHTMLElement::MapBackgroundAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsMapRuleToAttributesFunc
--- a/dom/html/HTMLFontElement.cpp
+++ b/dom/html/HTMLFontElement.cpp
@@ -71,27 +71,27 @@ HTMLFontElement::MapAttributesIntoRule(c
     if (!aData->PropertyIsSet(eCSSProperty_font_size)) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::size);
       if (value && value->Type() == nsAttrValue::eInteger)
         aData->SetKeywordValue(eCSSProperty_font_size, value->GetIntegerValue());
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
     if (!aData->PropertyIsSet(eCSSProperty_color) &&
-        aData->PresContext()->UseDocumentColors()) {
+        !aData->ShouldIgnoreColors()) {
       // color: color
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::color);
       nscolor color;
       if (value && value->GetColorValue(color)) {
         aData->SetColorValue(eCSSProperty_color, color);
       }
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(TextReset)) &&
-      aData->PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
+      aData->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();
     }
--- a/dom/html/HTMLHRElement.cpp
+++ b/dom/html/HTMLHRElement.cpp
@@ -164,18 +164,17 @@ HTMLHRElement::MapAttributesIntoRule(con
            *props != eCSSProperty_UNKNOWN; ++props) {
         aData->SetPixelValueIfUnset(*props, 10000.0f);
       }
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Color))) {
     // color: a color
     // (we got the color attribute earlier)
-    if (colorIsSet &&
-        aData->PresContext()->UseDocumentColors()) {
+    if (colorIsSet && !aData->ShouldIgnoreColors()) {
       aData->SetColorValueIfUnset(eCSSProperty_color, color);
     }
   }
 
   nsGenericHTMLElement::MapWidthAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -232,17 +232,17 @@ HTMLTableCellElement::MapAttributesIntoR
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
     if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
       // nowrap: enum
       if (aAttributes->GetAttr(nsGkAtoms::nowrap)) {
         // See if our width is not a nonzero integer width.
         const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
-        nsCompatibility mode = aData->PresContext()->CompatibilityMode();
+        nsCompatibility mode = aData->Document()->GetCompatibilityMode();
         if (!value || value->Type() != nsAttrValue::eInteger ||
             value->GetIntegerValue() == 0 ||
             eCompatibility_NavQuirks != mode) {
           aData->SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Nowrap);
         }
       }
     }
   }
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -947,18 +947,17 @@ HTMLTableElement::MapAttributesIntoRule(
   // table cells.  (nsHTMLTableCellElement overrides
   // WalkContentStyleRules so that this happens.)  This violates the
   // nsIStyleRule contract, since it's the same style rule object doing
   // the mapping in two different ways.  It's also incorrect since it's
   // testing the display type of the style context rather than checking
   // which *element* it's matching (style rules should not stop matching
   // when the display type is changed).
 
-  nsPresContext* presContext = aData->PresContext();
-  nsCompatibility mode = presContext->CompatibilityMode();
+  nsCompatibility mode = aData->Document()->GetCompatibilityMode();
 
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(TableBorder))) {
     // 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()));
     }
@@ -994,18 +993,17 @@ HTMLTableElement::MapAttributesIntoRule(
         aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)value->GetIntegerValue());
       }
     }
   }
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))) {
     // bordercolor
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bordercolor);
     nscolor color;
-    if (value && presContext->UseDocumentColors() &&
-        value->GetColorValue(color)) {
+    if (value && !aData->ShouldIgnoreColors() && 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);
     }
 
     // border
     const nsAttrValue* borderValue = aAttributes->GetAttr(nsGkAtoms::border);
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1539,17 +1539,17 @@ void
 nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
 
   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
     return;
 
   if (!aData->PropertyIsSet(eCSSProperty_background_image) &&
-      aData->PresContext()->UseDocumentColors()) {
+      !aData->ShouldIgnoreColors()) {
     // background
     nsAttrValue* value =
       const_cast<nsAttrValue*>(aAttributes->GetAttr(nsGkAtoms::background));
     if (value) {
       aData->SetBackgroundImage(*value);
     }
   }
 }
@@ -1557,17 +1557,17 @@ nsGenericHTMLElement::MapBackgroundInto(
 void
 nsGenericHTMLElement::MapBGColorInto(const nsMappedAttributes* aAttributes,
                                      GenericSpecifiedValues* aData)
 {
   if (!aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Background)))
     return;
 
   if (!aData->PropertyIsSet(eCSSProperty_background_color) &&
-      aData->PresContext()->UseDocumentColors()) {
+      !aData->ShouldIgnoreColors()) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::bgcolor);
     nscolor color;
     if (value && value->GetColorValue(color)) {
       aData->SetColorValue(eCSSProperty_background_color, color);
     }
   }
 }
 
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -523,17 +523,17 @@ nsMathMLElement::MapMathMLAttributesInto
         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);
         } else {
           ReportParseErrorNoTag(str,
                                 nsGkAtoms::scriptsizemultiplier_,
-                                aData->mPresContext->Document());
+                                aData->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."
@@ -545,17 +545,17 @@ nsMathMLElement::MapMathMLAttributesInto
     // 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)) {
       nsCSSValue scriptMinSize;
       ParseNumericValue(value->GetStringValue(), scriptMinSize,
                         PARSE_ALLOW_UNITLESS | CONVERT_UNITLESS_TO_PERCENT,
-                        aData->mPresContext->Document());
+                        aData->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);
       }
@@ -589,17 +589,17 @@ nsMathMLElement::MapMathMLAttributesInto
           if (ch == '+' || ch == '-') {
             aData->SetIntValue(eCSSProperty__moz_script_level, intValue);
           } else {
             aData->SetNumberValue(eCSSProperty__moz_script_level, intValue);
           }
         } else {
           ReportParseErrorNoTag(str,
                                 nsGkAtoms::scriptlevel_,
-                                aData->mPresContext->Document());
+                                aData->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
@@ -623,17 +623,17 @@ 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->mPresContext->Document());
+                       aData->Document());
       }
     }
     if (value && value->Type() == nsAttrValue::eString &&
         !aData->PropertyIsSet(eCSSProperty_font_size)) {
       nsAutoString str(value->GetStringValue());
       nsCSSValue fontSize;
       if (!ParseNumericValue(str, fontSize, PARSE_SUPPRESS_WARNINGS |
                              PARSE_ALLOW_UNITLESS | CONVERT_UNITLESS_TO_PERCENT,
@@ -666,17 +666,17 @@ nsMathMLElement::MapMathMLAttributesInto
     // 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->mPresContext->Document());
+                     aData->Document());
     }
     if (value && value->Type() == nsAttrValue::eString &&
         !aData->PropertyIsSet(eCSSProperty_font_family)) {
       aData->SetFontFamily(value->GetStringValue());
     }
 
     // fontstyle
     //
@@ -687,17 +687,17 @@ nsMathMLElement::MapMathMLAttributesInto
     // 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->mPresContext->Document());
+                       aData->Document());
       if (value->Type() == nsAttrValue::eString &&
           !aData->PropertyIsSet(eCSSProperty_font_style)) {
         nsAutoString str(value->GetStringValue());
         str.CompressWhitespace();
         if (str.EqualsASCII("normal")) {
           aData->SetKeywordValue(eCSSProperty_font_style,
                                  NS_STYLE_FONT_STYLE_NORMAL);
         } else if (str.EqualsASCII("italic")) {
@@ -716,17 +716,17 @@ 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->mPresContext->Document());
+                       aData->Document());
       if (value->Type() == nsAttrValue::eString &&
           !aData->PropertyIsSet(eCSSProperty_font_weight)) {
         nsAutoString str(value->GetStringValue());
         str.CompressWhitespace();
         if (str.EqualsASCII("normal")) {
           aData->SetKeywordValue(eCSSProperty_font_weight,
                                  NS_STYLE_FONT_WEIGHT_NORMAL);
         } else if (str.EqualsASCII("bold")) {
@@ -801,17 +801,17 @@ nsMathMLElement::MapMathMLAttributesInto
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Background)) {
     const nsAttrValue* value =
       aAttributes->GetAttr(nsGkAtoms::mathbackground_);
     if (!value) {
       value = aAttributes->GetAttr(nsGkAtoms::background);
       if (value) {
         WarnDeprecated(nsGkAtoms::background->GetUTF16String(),
                        nsGkAtoms::mathbackground_->GetUTF16String(),
-                       aData->mPresContext->Document());
+                       aData->Document());
       }
     }
     if (value) {
       nscolor color;
       if (value->GetColorValue(color)) {
         aData->SetColorValueIfUnset(eCSSProperty_background_color, color);
       }
     }
@@ -836,17 +836,17 @@ nsMathMLElement::MapMathMLAttributesInto
   //
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Color)) {
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::mathcolor_);
     if (!value) {
       value = aAttributes->GetAttr(nsGkAtoms::color);
       if (value) {
         WarnDeprecated(nsGkAtoms::color->GetUTF16String(),
                        nsGkAtoms::mathcolor_->GetUTF16String(),
-                       aData->mPresContext->Document());
+                       aData->Document());
       }
     }
     nscolor color;
     if (value && value->GetColorValue(color)) {
       aData->SetColorValueIfUnset(eCSSProperty_color, color);
     }
   }
 
@@ -863,18 +863,17 @@ nsMathMLElement::MapMathMLAttributesInto
     // values: "auto" | length
     // default: auto
     //
     if (!aData->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->mPresContext->Document());
+        ParseNumericValue(value->GetStringValue(), width, 0, aData->Document());
         if (width.GetUnit() == eCSSUnit_Percent) {
           aData->SetPercentValue(eCSSProperty_width,
                                  width.GetPercentValue());
         } else if (width.GetUnit() != eCSSUnit_Null) {
           aData->SetLengthValue(eCSSProperty_width, width);
         }
       }
     }
--- a/layout/style/GenericSpecifiedValues.h
+++ b/layout/style/GenericSpecifiedValues.h
@@ -11,53 +11,60 @@
  */
 
 #ifndef mozilla_GenericSpecifiedValues_h
 #define mozilla_GenericSpecifiedValues_h
 
 #include "mozilla/ServoUtils.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
-#include "nsPresContext.h"
+#include "StyleBackendType.h"
 
+class nsAttrValue;
 struct nsRuleData;
 
 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.
+// 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(StyleBackendType aType,
-                                  nsPresContext* aPresContext,
-                                  uint32_t aSIDs)
+  explicit GenericSpecifiedValues(StyleBackendType aType, nsIDocument* aDoc, uint32_t aSIDs)
     : mType(aType)
-    , mPresContext(aPresContext)
+    , mDocument(aDoc)
     , mSIDs(aSIDs)
   {}
 
 public:
   MOZ_DECL_STYLO_METHODS(nsRuleData, ServoSpecifiedValues)
 
+  nsIDocument* Document()
+  {
+    return mDocument;
+  }
+
+  // Whether we should ignore document colors.
+  inline bool ShouldIgnoreColors() const;
+
   // Check if we already contain a certain longhand
   inline bool PropertyIsSet(nsCSSPropertyID aId);
+
   // Check if we are able to hold longhands from a given
   // style struct. Pass the result of NS_STYLE_INHERIT_BIT to this
   // function. Can accept multiple inherit bits or'd together.
   inline bool ShouldComputeStyleStruct(uint64_t aInheritBits)
   {
     return aInheritBits & mSIDs;
   }
 
-  inline nsPresContext* PresContext() { return mPresContext; }
-
   // 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);
 
@@ -111,15 +118,15 @@ public:
 
   // 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);
 
   const mozilla::StyleBackendType mType;
-  nsPresContext* const mPresContext;
+  nsIDocument* const mDocument;
   const uint32_t mSIDs;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_GenericSpecifiedValues_h
--- a/layout/style/GenericSpecifiedValuesInlines.h
+++ b/layout/style/GenericSpecifiedValuesInlines.h
@@ -20,16 +20,29 @@
 
 namespace mozilla {
 
 MOZ_DEFINE_STYLO_METHODS(GenericSpecifiedValues,
                          nsRuleData,
                          ServoSpecifiedValues)
 
 bool
+GenericSpecifiedValues::ShouldIgnoreColors() const
+{
+  if (IsServo()) {
+    // Servo handles this during cascading.
+    //
+    // FIXME(emilio): We should eventually move it to the document though.
+    return false;
+  }
+
+  return !AsGecko()->mPresContext->UseDocumentColors();
+}
+
+bool
 GenericSpecifiedValues::PropertyIsSet(nsCSSPropertyID aId)
 {
   MOZ_STYLO_FORWARD(PropertyIsSet, (aId))
 }
 
 void
 GenericSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
                                             const nsString& aValue)
--- a/layout/style/ServoSpecifiedValues.cpp
+++ b/layout/style/ServoSpecifiedValues.cpp
@@ -2,35 +2,18 @@
 /* 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"
 
-namespace {
-
-#define STYLE_STRUCT(name, checkdata_cb) | NS_STYLE_INHERIT_BIT(name)
-const uint64_t ALL_SIDS = 0
-#include "nsStyleStructList.h"
-  ;
-#undef STYLE_STRUCT
-
-} // anonymous namespace
-
 using namespace mozilla;
 
-ServoSpecifiedValues::ServoSpecifiedValues(nsPresContext* aContext,
-                                           RawServoDeclarationBlock* aDecl)
-
-  : GenericSpecifiedValues(StyleBackendType::Servo, aContext, ALL_SIDS)
-  , mDecl(aDecl)
-{}
-
 bool
 ServoSpecifiedValues::PropertyIsSet(nsCSSPropertyID aId)
 {
   return Servo_DeclarationBlock_PropertyIsSet(mDecl, aId);
 }
 
 void
 ServoSpecifiedValues::SetIdentStringValue(nsCSSPropertyID aId,
@@ -40,19 +23,27 @@ ServoSpecifiedValues::SetIdentStringValu
   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
-    mPresContext->ForceCacheLang(aValue);
+    // 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 (nsIPresShell* shell = mDocument->GetShell()) {
+      if (nsPresContext* pc = shell->GetPresContext()) {
+        pc->ForceCacheLang(aValue);
+      }
+    }
   }
 }
 
 void
 ServoSpecifiedValues::SetKeywordValue(nsCSSPropertyID aId, int32_t aValue)
 {
   Servo_DeclarationBlock_SetKeywordValue(mDecl, aId, aValue);
 }
@@ -124,10 +115,10 @@ ServoSpecifiedValues::SetBackgroundImage
 {
   if (aValue.Type() != nsAttrValue::eURL &&
       aValue.Type() != nsAttrValue::eImage) {
     return;
   }
   nsAutoString str;
   aValue.ToString(str);
   Servo_DeclarationBlock_SetBackgroundImage(
-    mDecl, str, mPresContext->Document()->DefaultStyleAttrURLData());
+    mDecl, str, mDocument->DefaultStyleAttrURLData());
 }
--- a/layout/style/ServoSpecifiedValues.h
+++ b/layout/style/ServoSpecifiedValues.h
@@ -15,18 +15,20 @@
 #include "mozilla/GenericSpecifiedValues.h"
 #include "mozilla/ServoBindingTypes.h"
 
 namespace mozilla {
 
 class ServoSpecifiedValues final : public GenericSpecifiedValues
 {
 public:
-  ServoSpecifiedValues(nsPresContext* aContext,
-                       RawServoDeclarationBlock* aDecl);
+  ServoSpecifiedValues(nsIDocument* aDocument, RawServoDeclarationBlock* aDecl)
+    : GenericSpecifiedValues(StyleBackendType::Servo, aDocument, NS_STYLE_INHERIT_MASK)
+    , mDecl(aDecl)
+  {}
 
   // GenericSpecifiedValues overrides
   bool PropertyIsSet(nsCSSPropertyID aId);
 
   void SetIdentStringValue(nsCSSPropertyID aId, const nsString& aValue);
 
   void SetIdentAtomValue(nsCSSPropertyID aId, nsAtom* aValue);
 
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -348,17 +348,17 @@ ServoStyleSet::Snapshots()
 {
   return mPresContext->RestyleManager()->AsServo()->Snapshots();
 }
 
 void
 ServoStyleSet::ResolveMappedAttrDeclarationBlocks()
 {
   if (nsHTMLStyleSheet* sheet = mPresContext->Document()->GetAttributeStyleSheet()) {
-    sheet->CalculateMappedServoDeclarations(mPresContext);
+    sheet->CalculateMappedServoDeclarations();
   }
 
   mPresContext->Document()->ResolveScheduledSVGPresAttrs();
 }
 
 void
 ServoStyleSet::PreTraverseSync()
 {
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -562,28 +562,25 @@ nsHTMLStyleSheet::DropMappedAttributes(n
 #endif
 
   mMappedAttrTable.Remove(aMapped);
 
   NS_ASSERTION(entryCount == mMappedAttrTable.EntryCount(), "not removed");
 }
 
 void
-nsHTMLStyleSheet::CalculateMappedServoDeclarations(nsPresContext* aPresContext)
+nsHTMLStyleSheet::CalculateMappedServoDeclarations()
 {
-  MOZ_ASSERT(!mDocument->GetShell() ||
-             mDocument->GetShell()->GetPresContext() == aPresContext);
-
   for (auto iter = mMappedAttrTable.Iter(); !iter.Done(); iter.Next()) {
     MappedAttrTableEntry* attr = static_cast<MappedAttrTableEntry*>(iter.Get());
     if (attr->mAttributes->GetServoStyle()) {
       // Only handle cases which haven't been filled in already
       continue;
     }
-    attr->mAttributes->LazilyResolveServoDeclaration(aPresContext);
+    attr->mAttributes->LazilyResolveServoDeclaration(mDocument);
   }
 }
 
 nsIStyleRule*
 nsHTMLStyleSheet::LangRuleFor(const nsAtom* aLanguage)
 {
   auto entry =
     static_cast<LangRuleTableEntry*>(mLangRuleTable.Add(aLanguage, fallible));
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -72,17 +72,17 @@ public:
 
   // Mapped Attribute management methods
   already_AddRefed<nsMappedAttributes>
     UniqueMappedAttributes(nsMappedAttributes* aMapped);
   void DropMappedAttributes(nsMappedAttributes* aMapped);
   // For each mapped presentation attribute in the cache, resolve
   // the attached ServoDeclarationBlock by running the mapping
   // and converting the ruledata to Servo specified values.
-  void CalculateMappedServoDeclarations(nsPresContext* aPresContext);
+  void CalculateMappedServoDeclarations();
 
   nsIStyleRule* LangRuleFor(const nsAtom* aLanguage);
 
 private:
   nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) = delete;
   nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) = delete;
 
   ~nsHTMLStyleSheet() {}
--- a/layout/style/nsRuleData.cpp
+++ b/layout/style/nsRuleData.cpp
@@ -3,16 +3,18 @@
 /* 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 "nsRuleData.h"
 
 #include "nsAttrValueInlines.h"
 #include "nsCSSParser.h"
+#include "nsPresContext.h"
+#include "mozilla/GeckoStyleContext.h"
 #include "mozilla/Poison.h"
 #include <stdint.h>
 
 using namespace mozilla;
 
 inline size_t
 nsRuleData::GetPoisonOffset()
 {
@@ -26,20 +28,20 @@ nsRuleData::GetPoisonOffset()
   static_assert(size_t(-1) > size_t(0), "expect size_t to be unsigned");
   uintptr_t framePoisonValue = mozPoisonValue();
   return size_t(framePoisonValue - uintptr_t(mValueStorage)) /
          sizeof(nsCSSValue);
 }
 
 nsRuleData::nsRuleData(uint32_t aSIDs,
                        nsCSSValue* aValueStorage,
-                       nsPresContext* aContext,
                        GeckoStyleContext* aStyleContext)
-  : GenericSpecifiedValues(StyleBackendType::Gecko, aContext, aSIDs)
+  : GenericSpecifiedValues(StyleBackendType::Gecko, aStyleContext->PresContext()->Document(), aSIDs)
   , mStyleContext(aStyleContext)
+  , mPresContext(aStyleContext->PresContext())
   , mValueStorage(aValueStorage)
 {
 #ifndef MOZ_VALGRIND
   size_t framePoisonOffset = GetPoisonOffset();
   for (size_t i = 0; i < nsStyleStructID_Length; ++i) {
     mValueOffsets[i] = framePoisonOffset;
   }
 #endif
@@ -66,17 +68,17 @@ nsRuleData::SetTextDecorationColorOverri
 
 void
 nsRuleData::SetBackgroundImage(nsAttrValue& aValue)
 {
   nsCSSValue* backImage = ValueForBackgroundImage();
   // If the value is an image, or it is a URL and we attempted a load,
   // put it in the style tree.
   if (aValue.Type() == nsAttrValue::eURL) {
-    aValue.LoadImage(mPresContext->Document());
+    aValue.LoadImage(mDocument);
   }
   if (aValue.Type() == nsAttrValue::eImage) {
     nsCSSValueList* list = backImage->SetListValue();
     list->mValue.SetImageValue(aValue.GetImageValue());
   }
 }
 
 #ifdef DEBUG
--- a/layout/style/nsRuleData.h
+++ b/layout/style/nsRuleData.h
@@ -31,16 +31,17 @@ class GeckoStyleContext;
 typedef void (*nsPostResolveFunc)(void* aStyleStruct, nsRuleData* aData);
 
 struct nsRuleData final : mozilla::GenericSpecifiedValues
 {
   mozilla::RuleNodeCacheConditions mConditions;
   bool mIsImportantRule;
   mozilla::SheetType mLevel;
   mozilla::GeckoStyleContext* const mStyleContext;
+  nsPresContext* const mPresContext;
 
   // We store nsCSSValues needed to compute the data for one or more
   // style structs (specified by the bitfield mSIDs).  These are stored
   // in a single array allocation (which our caller allocates; see
   // AutoCSSValueArray)   The offset of each property |prop| in
   // mValueStorage is the sum of
   // mValueOffsets[nsCSSProps::kSIDTable[prop]] and
   // nsCSSProps::PropertyIndexInStruct(prop).  The only place we gather
@@ -50,17 +51,16 @@ struct nsRuleData final : mozilla::Gener
   // mValueOffsets for the one struct in mSIDs is zero.
   nsCSSValue* const mValueStorage; // our user owns this array
   size_t mValueOffsets[nsStyleStructID_Length];
 
   nsAutoPtr<mozilla::CSSVariableDeclarations> mVariables;
 
   nsRuleData(uint32_t aSIDs,
              nsCSSValue* aValueStorage,
-             nsPresContext* aContext,
              mozilla::GeckoStyleContext* aStyleContext);
 
 #ifdef DEBUG
   ~nsRuleData();
 #else
   ~nsRuleData() {}
 #endif
 
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2469,17 +2469,17 @@ nsRuleNode::WalkRuleTree(const nsStyleSt
   // use placement new[] on the result of alloca() to allocate a
   // variable-sized stack array, including execution of constructors,
   // and use an RAII class to run the destructors too.
   size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
   AutoCSSValueArray dataArray(dataStorage, nprops);
 
   nsRuleData ruleData(nsCachedStyleData::GetBitForSID(aSID),
-                      dataArray.get(), mPresContext, aContext);
+                      dataArray.get(), aContext);
   ruleData.mValueOffsets[aSID] = 0;
 
   // We start at the most specific rule in the tree.
   void* startStruct = nullptr;
 
   nsRuleNode* ruleNode = this;
   nsRuleNode* highestNode = nullptr; // The highest node in the rule tree
                                     // that has the same properties
@@ -4079,18 +4079,17 @@ nsRuleNode::SetGenericFont(nsPresContext
   // and use an RAII class to run the destructors too.
   size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font);
   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
 
   for (int32_t i = contextPath.Length() - 1; i >= 0; --i) {
     GeckoStyleContext* context = contextPath[i];
     AutoCSSValueArray dataArray(dataStorage, nprops);
 
-    nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(),
-                        aPresContext, context);
+    nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(), context);
     ruleData.mValueOffsets[eStyleStruct_Font] = 0;
 
     // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
     // Note that we *do* need to do this for our own data, since what is
     // in |fontData| in ComputeFontData is only for the rules below
     // aStartStruct.
     for (nsRuleNode* ruleNode = context->RuleNode(); ruleNode;
          ruleNode = ruleNode->GetParent()) {
@@ -10188,18 +10187,17 @@ nsRuleNode::HasAuthorSpecifiedRules(Geck
     paddingOffset = nprops;
     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding);
   }
 
   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
   AutoCSSValueArray dataArray(dataStorage, nprops);
 
   /* We're relying on the use of |styleContext| not mutating it! */
-  nsRuleData ruleData(inheritBits, dataArray.get(),
-                      styleContext->PresContext(), styleContext);
+  nsRuleData ruleData(inheritBits, dataArray.get(), styleContext);
 
   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
     ruleData.mValueOffsets[eStyleStruct_Background] = backgroundOffset;
   }
 
   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
     ruleData.mValueOffsets[eStyleStruct_Border] = borderOffset;
   }
@@ -10382,18 +10380,17 @@ nsRuleNode::ComputePropertiesOverridingA
       nprops += nsCSSProps::PropertyCountInStruct(sid);
     }
   }
 
   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
   AutoCSSValueArray dataArray(dataStorage, nprops);
 
   // We're relying on the use of |aStyleContext| not mutating it!
-  nsRuleData ruleData(structBits, dataArray.get(),
-                      aStyleContext->PresContext(), aStyleContext);
+  nsRuleData ruleData(structBits, dataArray.get(), aStyleContext);
   for (nsStyleStructID sid = nsStyleStructID(0);
        sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
     if (structBits & nsCachedStyleData::GetBitForSID(sid)) {
       ruleData.mValueOffsets[sid] = offsets[sid];
     }
   }
 
   /*