Bug 1341647 - stylo: Move HTMLBodyElement::WalkContentStyleRules to the mapped attr functionality; r=bz
authorManish Goregaokar <manishearth@gmail.com>
Wed, 29 Mar 2017 12:10:00 -0700
changeset 350805 e212c8b1248b0311eb971db03e45d2eb0e064e5f
parent 350804 3343fa2a55d708dfdd6c1377aebb8f065084ae63
child 350806 a9f9515d8bca8243e9a22a43f40e422aa75733e5
push id88717
push userarchaeopteryx@coole-files.de
push dateSat, 01 Apr 2017 11:12:29 +0000
treeherdermozilla-inbound@655d6c600048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1341647
milestone55.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 1341647 - stylo: Move HTMLBodyElement::WalkContentStyleRules to the mapped attr functionality; r=bz MozReview-Commit-ID: 90qDHl0Ane4
dom/base/Element.h
dom/base/nsAttrAndChildArray.cpp
dom/base/nsAttrAndChildArray.h
dom/base/nsFrameLoader.cpp
dom/base/nsMappedAttributes.cpp
dom/base/nsMappedAttributes.h
dom/html/HTMLBodyElement.cpp
dom/html/HTMLBodyElement.h
dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html
dom/html/reftests/body-frame-margin-remove-other-pres-hint.html
dom/html/reftests/body-topmargin-dynamic.html
dom/html/reftests/body-topmargin-ref.html
dom/html/reftests/reftest-stylo.list
dom/html/reftests/reftest.list
dom/plugins/test/reftest/reftest-stylo.list
layout/base/ServoRestyleManager.cpp
layout/reftests/bugs/reftest-stylo.list
layout/reftests/css-mediaqueries/reftest-stylo.list
layout/reftests/floats/reftest-stylo.list
layout/reftests/position-sticky/reftest-stylo.list
layout/reftests/svg/reftest-stylo.list
layout/style/test/stylo-failures.md
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -282,16 +282,20 @@ public:
    */
   DeclarationBlock* GetInlineStyleDeclaration() const;
 
   /**
    * Get the mapped attributes, if any, for this element.
    */
   const nsMappedAttributes* GetMappedAttributes() const;
 
+  void ClearMappedServoStyle() {
+    mAttrsAndChildren.ClearMappedServoStyle();
+  }
+
   /**
    * Set the inline style declaration for this element. This will send
    * an appropriate AttributeChanged notification if aNotify is true.
    */
   virtual nsresult SetInlineStyleDeclaration(DeclarationBlock* aDeclaration,
                                              const nsAString* aSerialized,
                                              bool aNotify);
 
--- a/dom/base/nsAttrAndChildArray.cpp
+++ b/dom/base/nsAttrAndChildArray.cpp
@@ -716,30 +716,46 @@ nsAttrAndChildArray::NonMappedAttrCount(
 }
 
 uint32_t
 nsAttrAndChildArray::MappedAttrCount() const
 {
   return mImpl && mImpl->mMappedAttrs ? (uint32_t)mImpl->mMappedAttrs->Count() : 0;
 }
 
+nsresult
+nsAttrAndChildArray::ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument)
+{
+  nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
+  RefPtr<nsMappedAttributes> mapped = GetModifiableMapped(aContent, sheet, false, 0);
+  return MakeMappedUnique(mapped);
+}
+
+void
+nsAttrAndChildArray::ClearMappedServoStyle() {
+  if (mImpl && mImpl->mMappedAttrs) {
+    mImpl->mMappedAttrs->ClearServoStyle();
+  }
+}
+
 nsMappedAttributes*
 nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
                                          nsHTMLStyleSheet* aSheet,
-                                         bool aWillAddAttr)
+                                         bool aWillAddAttr,
+                                         int32_t aAttrCount)
 {
   if (mImpl && mImpl->mMappedAttrs) {
     return mImpl->mMappedAttrs->Clone(aWillAddAttr);
   }
 
   MOZ_ASSERT(aContent, "Trying to create modifiable without content");
 
   nsMapRuleToAttributesFunc mapRuleFunc =
     aContent->GetAttributeMappingFunction();
-  return new nsMappedAttributes(aSheet, mapRuleFunc);
+  return new (aAttrCount) nsMappedAttributes(aSheet, mapRuleFunc);
 }
 
 nsresult
 nsAttrAndChildArray::MakeMappedUnique(nsMappedAttributes* aAttributes)
 {
   NS_ASSERTION(aAttributes, "missing attributes");
 
   if (!mImpl && !GrowBy(1)) {
--- a/dom/base/nsAttrAndChildArray.h
+++ b/dom/base/nsAttrAndChildArray.h
@@ -131,30 +131,38 @@ public:
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   bool HasMappedAttrs() const
   {
     return MappedAttrCount();
   }
   const nsMappedAttributes* GetMapped() const;
 
+  // Force this to have mapped attributes, even if those attributes are empty.
+  nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
+
+  // Clear the servo declaration block on the mapped attributes, if any
+  // Will assert off main thread
+  void ClearMappedServoStyle();
+
 private:
   nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
   nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
 
   void Clear();
 
   uint32_t NonMappedAttrCount() const;
   uint32_t MappedAttrCount() const;
 
   // Returns a non-null zero-refcount object.
   nsMappedAttributes*
   GetModifiableMapped(nsMappedAttributeElement* aContent,
                       nsHTMLStyleSheet* aSheet,
-                      bool aWillAddAttr);
+                      bool aWillAddAttr,
+                      int32_t aAttrCount = 1);
   nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
 
   uint32_t AttrSlotsSize() const
   {
     return AttrSlotCount() * ATTRSIZE;
   }
 
   uint32_t AttrSlotCount() const
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -50,16 +50,17 @@
 #include "nsIEditor.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsISHistory.h"
 #include "NullPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsGlobalWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
+#include "nsMappedAttributes.h"
 #include "nsView.h"
 #include "GroupedSHistory.h"
 #include "PartialSHistory.h"
 
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
@@ -1198,21 +1199,37 @@ nsFrameLoader::MarginsChanged(uint32_t a
   // margins.
   if (!mDocShell)
     return;
 
   // Set the margins
   mDocShell->SetMarginWidth(aMarginWidth);
   mDocShell->SetMarginHeight(aMarginHeight);
 
+  // There's a cached property declaration block
+  // that needs to be updated
+  if (nsIDocument* doc = mDocShell->GetDocument()) {
+    // We don't need to do anything for Gecko here because
+    // we plan to RebuildAllStyleData anyway.
+    if (doc->GetStyleBackendType() == StyleBackendType::Servo) {
+      for (nsINode* cur = doc; cur; cur = cur->GetNextNode()) {
+        if (cur->IsHTMLElement(nsGkAtoms::body)) {
+          static_cast<HTMLBodyElement*>(cur)->ClearMappedServoStyle();
+        }
+      }
+    }
+  }
+
   // Trigger a restyle if there's a prescontext
   // FIXME: This could do something much less expensive.
   RefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (presContext)
+    // rebuild, because now the same nsMappedAttributes* will produce
+    // a different style
     presContext->RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
 }
 
 bool
 nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
                                nsSubDocumentFrame *aFrame)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
--- a/dom/base/nsMappedAttributes.cpp
+++ b/dom/base/nsMappedAttributes.cpp
@@ -65,37 +65,42 @@ nsMappedAttributes::Clone(bool aWillAddA
   uint32_t extra = aWillAddAttr ? 1 : 0;
 
   // This will call the overridden operator new
   return new (mAttrCount + extra) nsMappedAttributes(*this);
 }
 
 void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW
 {
-  NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested");
+
+  size_t size = aSize + aAttrCount * sizeof(InternalAttr);
 
   // aSize will include the mAttrs buffer so subtract that.
-  void* newAttrs = ::operator new(aSize - sizeof(void*[1]) +
-                                  aAttrCount * sizeof(InternalAttr));
+  // We don't want to under-allocate, however, so do not subtract
+  // if we have zero attributes. The zero attribute case only happens
+  // for <body>'s mapped attributes
+  if (aAttrCount != 0) {
+    size -= sizeof(void*[1]);
+  }
+
+  void* newAttrs = ::operator new(size);
 
 #ifdef DEBUG
   static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
 #endif
-
   return newAttrs;
 }
 
 NS_IMPL_ISUPPORTS(nsMappedAttributes,
                   nsIStyleRule)
 
 void
 nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue)
 {
   NS_PRECONDITION(aAttrName, "null name");
-
   uint32_t i;
   for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
     if (Attrs()[i].mName.Equals(aAttrName)) {
       Attrs()[i].mValue.Reset();
       Attrs()[i].mValue.SwapValueWith(aValue);
       return;
     }
   }
--- a/dom/base/nsMappedAttributes.h
+++ b/dom/base/nsMappedAttributes.h
@@ -79,16 +79,21 @@ public:
   // 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;
   }
 
+  void ClearServoStyle() {
+    MOZ_ASSERT(NS_IsMainThread());
+    mServoStyle = nullptr;
+  }
+
   // nsIStyleRule
   virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
   virtual bool MightMapInheritedStyleData() override;
   virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
                                              nsCSSValue* aValue) override;
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
 #endif
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -22,190 +22,18 @@
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Body)
 
 namespace mozilla {
 namespace dom {
 
 //----------------------------------------------------------------------
 
-BodyRule::BodyRule(HTMLBodyElement* aPart)
-  : mPart(aPart)
-{
-}
-
-BodyRule::~BodyRule()
-{
-}
-
-NS_IMPL_ISUPPORTS(BodyRule, nsIStyleRule)
-
-/* virtual */ void
-BodyRule::MapRuleInfoInto(nsRuleData* aData)
-{
-  if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) || !mPart)
-    return; // We only care about margins.
-
-  int32_t bodyMarginWidth  = -1;
-  int32_t bodyMarginHeight = -1;
-  int32_t bodyTopMargin = -1;
-  int32_t bodyBottomMargin = -1;
-  int32_t bodyLeftMargin = -1;
-  int32_t bodyRightMargin = -1;
-
-  // check the mode (fortunately, the ruleData has a presContext for us to use!)
-  NS_ASSERTION(aData->mPresContext, "null presContext in ruleNode was unexpected");
-  nsCompatibility mode = aData->mPresContext->CompatibilityMode();
-
-
-  const nsAttrValue* value;
-  if (mPart->GetAttrCount() > 0) {
-    // if marginwidth/marginheight are set, reflect them as 'margin'
-    value = mPart->GetParsedAttr(nsGkAtoms::marginwidth);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyMarginWidth = value->GetIntegerValue();
-      if (bodyMarginWidth < 0) bodyMarginWidth = 0;
-      nsCSSValue* marginLeft = aData->ValueForMarginLeft();
-      if (marginLeft->GetUnit() == eCSSUnit_Null)
-        marginLeft->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
-      nsCSSValue* marginRight = aData->ValueForMarginRight();
-      if (marginRight->GetUnit() == eCSSUnit_Null)
-        marginRight->SetFloatValue((float)bodyMarginWidth, eCSSUnit_Pixel);
-    }
-
-    value = mPart->GetParsedAttr(nsGkAtoms::marginheight);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyMarginHeight = value->GetIntegerValue();
-      if (bodyMarginHeight < 0) bodyMarginHeight = 0;
-      nsCSSValue* marginTop = aData->ValueForMarginTop();
-      if (marginTop->GetUnit() == eCSSUnit_Null)
-        marginTop->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
-      nsCSSValue* marginBottom = aData->ValueForMarginBottom();
-      if (marginBottom->GetUnit() == eCSSUnit_Null)
-        marginBottom->SetFloatValue((float)bodyMarginHeight, eCSSUnit_Pixel);
-    }
-
-      // topmargin (IE-attribute)
-    value = mPart->GetParsedAttr(nsGkAtoms::topmargin);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyTopMargin = value->GetIntegerValue();
-      if (bodyTopMargin < 0) bodyTopMargin = 0;
-      nsCSSValue* marginTop = aData->ValueForMarginTop();
-      if (marginTop->GetUnit() == eCSSUnit_Null)
-        marginTop->SetFloatValue((float)bodyTopMargin, eCSSUnit_Pixel);
-    }
-
-      // bottommargin (IE-attribute)
-    value = mPart->GetParsedAttr(nsGkAtoms::bottommargin);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyBottomMargin = value->GetIntegerValue();
-      if (bodyBottomMargin < 0) bodyBottomMargin = 0;
-      nsCSSValue* marginBottom = aData->ValueForMarginBottom();
-      if (marginBottom->GetUnit() == eCSSUnit_Null)
-        marginBottom->SetFloatValue((float)bodyBottomMargin, eCSSUnit_Pixel);
-    }
-
-      // leftmargin (IE-attribute)
-    value = mPart->GetParsedAttr(nsGkAtoms::leftmargin);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyLeftMargin = value->GetIntegerValue();
-      if (bodyLeftMargin < 0) bodyLeftMargin = 0;
-      nsCSSValue* marginLeft = aData->ValueForMarginLeft();
-      if (marginLeft->GetUnit() == eCSSUnit_Null)
-        marginLeft->SetFloatValue((float)bodyLeftMargin, eCSSUnit_Pixel);
-    }
-
-      // rightmargin (IE-attribute)
-    value = mPart->GetParsedAttr(nsGkAtoms::rightmargin);
-    if (value && value->Type() == nsAttrValue::eInteger) {
-      bodyRightMargin = value->GetIntegerValue();
-      if (bodyRightMargin < 0) bodyRightMargin = 0;
-      nsCSSValue* marginRight = aData->ValueForMarginRight();
-      if (marginRight->GetUnit() == eCSSUnit_Null)
-        marginRight->SetFloatValue((float)bodyRightMargin, eCSSUnit_Pixel);
-    }
-
-  }
-
-  // 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());
-    if (docShell) {
-      nscoord frameMarginWidth=-1;  // default value
-      nscoord frameMarginHeight=-1; // default value
-      docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set
-      docShell->GetMarginHeight(&frameMarginHeight);
-      if ((frameMarginWidth >= 0) && (bodyMarginWidth == -1)) { // set in <frame> & not in <body>
-        if (eCompatibility_NavQuirks == mode) {
-          if ((bodyMarginHeight == -1) && (0 > frameMarginHeight)) // nav quirk
-            frameMarginHeight = 0;
-        }
-      }
-      if ((frameMarginHeight >= 0) && (bodyMarginHeight == -1)) { // set in <frame> & not in <body>
-        if (eCompatibility_NavQuirks == mode) {
-          if ((bodyMarginWidth == -1) && (0 > frameMarginWidth)) // nav quirk
-            frameMarginWidth = 0;
-        }
-      }
-
-      if ((bodyMarginWidth == -1) && (frameMarginWidth >= 0)) {
-        nsCSSValue* marginLeft = aData->ValueForMarginLeft();
-        if (marginLeft->GetUnit() == eCSSUnit_Null)
-          marginLeft->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
-        nsCSSValue* marginRight = aData->ValueForMarginRight();
-        if (marginRight->GetUnit() == eCSSUnit_Null)
-          marginRight->SetFloatValue((float)frameMarginWidth, eCSSUnit_Pixel);
-      }
-
-      if ((bodyMarginHeight == -1) && (frameMarginHeight >= 0)) {
-        nsCSSValue* marginTop = aData->ValueForMarginTop();
-        if (marginTop->GetUnit() == eCSSUnit_Null)
-          marginTop->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
-        nsCSSValue* marginBottom = aData->ValueForMarginBottom();
-        if (marginBottom->GetUnit() == eCSSUnit_Null)
-          marginBottom->SetFloatValue((float)frameMarginHeight, eCSSUnit_Pixel);
-      }
-    }
-  }
-}
-
-/* virtual */ bool
-BodyRule::MightMapInheritedStyleData()
-{
-  return false;
-}
-
-/* virtual */ bool
-BodyRule::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
-                                        nsCSSValue* aValue)
-{
-  MOZ_ASSERT(false, "GetDiscretelyAnimatedCSSValue is not implemented yet");
-  return false;
-}
-
-#ifdef DEBUG
-/* virtual */ void
-BodyRule::List(FILE* out, int32_t aIndent) const
-{
-  nsAutoCString indent;
-  for (int32_t index = aIndent; --index >= 0; ) {
-    indent.AppendLiteral("  ");
-  }
-  fprintf_stderr(out, "%s[body rule] {}\n", indent.get());
-}
-#endif
-
-//----------------------------------------------------------------------
-
 HTMLBodyElement::~HTMLBodyElement()
 {
-  if (mContentStyleRule) {
-    mContentStyleRule->mPart = nullptr;
-  }
 }
 
 JSObject*
 HTMLBodyElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLBodyElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
@@ -343,30 +171,155 @@ HTMLBodyElement::ParseAttribute(int32_t 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 void
-HTMLBodyElement::UnbindFromTree(bool aDeep, bool aNullParent)
-{
-  if (mContentStyleRule) {
-    mContentStyleRule->mPart = nullptr;
-    mContentStyleRule = nullptr;
-  }
-
-  nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);  
-}
-
-void
 HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                        GenericSpecifiedValues* aData)
 {
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
+
+    // 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)
+
+    int32_t bodyMarginWidth  = -1;
+    int32_t bodyMarginHeight = -1;
+    int32_t bodyTopMargin = -1;
+    int32_t bodyBottomMargin = -1;
+    int32_t bodyLeftMargin = -1;
+    int32_t bodyRightMargin = -1;
+
+    // check the mode (fortunately, the GenericSpecifiedValues has a presContext for us to use!)
+    NS_ASSERTION(aData->mPresContext, "null presContext in MapAttributesIntoRule was unexpected");
+    nsCompatibility mode = aData->mPresContext->CompatibilityMode();
+
+
+    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);
+    }
+
+    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);
+    }
+
+      // 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);
+      }
+    }
+      // 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);
+      }
+    }
+
+      // 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);
+      }
+    }
+      // 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);
+      }
+    }
+
+    // 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());
+      if (docShell) {
+        nscoord frameMarginWidth=-1;  // default value
+        nscoord frameMarginHeight=-1; // default value
+        docShell->GetMarginWidth(&frameMarginWidth); // -1 indicates not set
+        docShell->GetMarginHeight(&frameMarginHeight);
+        if (frameMarginWidth >= 0 && bodyMarginWidth == -1) { // set in <frame> & not in <body>
+          if (eCompatibility_NavQuirks == mode) {
+            if (bodyMarginHeight == -1 && 0 > frameMarginHeight) { // nav quirk
+              frameMarginHeight = 0;
+            }
+          }
+        }
+        if (frameMarginHeight >= 0 && bodyMarginHeight == -1) { // set in <frame> & not in <body>
+          if (eCompatibility_NavQuirks == mode) {
+            if (bodyMarginWidth == -1 && 0 > frameMarginWidth) { // nav quirk
+              frameMarginWidth = 0;
+            }
+          }
+        }
+
+        if (bodyMarginWidth == -1 && frameMarginWidth >= 0) {
+          if (bodyLeftMargin == -1) {
+            aData->SetPixelValueIfUnset(eCSSProperty_margin_left, (float)frameMarginWidth);
+          }
+          if (bodyRightMargin == -1) {
+            aData->SetPixelValueIfUnset(eCSSProperty_margin_right, (float)frameMarginWidth);
+          }
+        }
+
+        if (bodyMarginHeight == -1 && frameMarginHeight >= 0) {
+          if (bodyTopMargin == -1) {
+            aData->SetPixelValueIfUnset(eCSSProperty_margin_top, (float)frameMarginHeight);
+          }
+          if (bodyBottomMargin == -1) {
+            aData->SetPixelValueIfUnset(eCSSProperty_margin_bottom, (float)frameMarginHeight);
+          }
+        }
+      }
+    }
+  }
+
   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) {
@@ -407,46 +360,30 @@ HTMLBodyElement::MapAttributesIntoRule(c
 }
 
 nsMapRuleToAttributesFunc
 HTMLBodyElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
-NS_IMETHODIMP
-HTMLBodyElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
-{
-  nsGenericHTMLElement::WalkContentStyleRules(aRuleWalker);
-
-  if (!mContentStyleRule && IsInUncomposedDoc()) {
-    // XXXbz should this use OwnerDoc() or GetComposedDoc()?
-    // sXBL/XBL2 issue!
-    mContentStyleRule = new BodyRule(this);
-  }
-  if (aRuleWalker && mContentStyleRule) {
-    aRuleWalker->Forward(mContentStyleRule);
-  }
-  return NS_OK;
-}
-
 NS_IMETHODIMP_(bool)
 HTMLBodyElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
   static const MappedAttributeEntry attributes[] = {
     { &nsGkAtoms::link },
     { &nsGkAtoms::vlink },
     { &nsGkAtoms::alink },
     { &nsGkAtoms::text },
-    // These aren't mapped through attribute mapping, but they are
-    // mapped through a style rule, so it is attribute dependent style.
-    // XXXldb But we don't actually replace the body rule when we have
-    // dynamic changes...
     { &nsGkAtoms::marginwidth },
     { &nsGkAtoms::marginheight },
+    { &nsGkAtoms::topmargin },
+    { &nsGkAtoms::rightmargin },
+    { &nsGkAtoms::bottommargin },
+    { &nsGkAtoms::leftmargin },
     { nullptr },
   };
 
   static const MappedAttributeEntry* const map[] = {
     attributes,
     sCommonAttributeMap,
     sBackgroundAttributeMap,
   };
@@ -485,16 +422,46 @@ HTMLBodyElement::GetAssociatedEditor()
 bool
 HTMLBodyElement::IsEventAttributeName(nsIAtom *aName)
 {
   return nsContentUtils::IsEventAttributeName(aName,
                                               EventNameType_HTML |
                                               EventNameType_HTMLBodyOrFramesetOnly);
 }
 
+nsresult
+HTMLBodyElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                            nsIContent* aBindingParent,
+                            bool aCompileEventHandlers)
+{
+  nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
+                                                 aBindingParent,
+                                                 aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return mAttrsAndChildren.ForceMapped(this, OwnerDoc());
+}
+
+nsresult
+HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                              const nsAttrValue* aValue,
+                              bool aNotify)
+{
+  nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
+                                                   aName, aValue, aNotify);
+  NS_ENSURE_SUCCESS(rv, rv);
+  // if the last mapped attribute was removed, don't clear the
+  // nsMappedAttributes, our style can still depend on the containing frame element
+  if (!aValue && IsAttributeMapped(aName)) {
+    nsresult rv = mAttrsAndChildren.ForceMapped(this, OwnerDoc());
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
 #define EVENT(name_, id_, type_, struct_) /* nothing; handled by the superclass */
 // nsGenericHTMLElement::GetOnError returns
 // already_AddRefed<EventHandlerNonNull> while other getters return
 // EventHandlerNonNull*, so allow passing in the type to use here.
 #define WINDOW_EVENT_HELPER(name_, type_)                                      \
   type_*                                                                       \
   HTMLBodyElement::GetOn##name_()                                              \
   {                                                                            \
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -10,38 +10,16 @@
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLBodyElement.h"
 #include "nsIStyleRule.h"
 
 namespace mozilla {
 namespace dom {
 
 class OnBeforeUnloadEventHandlerNonNull;
-class HTMLBodyElement;
-
-class BodyRule: public nsIStyleRule
-{
-  virtual ~BodyRule();
-
-public:
-  explicit BodyRule(HTMLBodyElement* aPart);
-
-  NS_DECL_ISUPPORTS
-
-  // nsIStyleRule interface
-  virtual void MapRuleInfoInto(nsRuleData* aRuleData) override;
-  virtual bool MightMapInheritedStyleData() override;
-  virtual bool GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
-                                             nsCSSValue* aValue) override;
-#ifdef DEBUG
-  virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
-#endif
-
-  HTMLBodyElement*  mPart;  // not ref-counted, cleared by content 
-};
 
 class HTMLBodyElement final : public nsGenericHTMLElement,
                               public nsIDOMHTMLBodyElement
 {
 public:
   using Element::GetText;
   using Element::SetText;
 
@@ -120,33 +98,38 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::background, aBackground, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult) override;
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
-  NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
   virtual already_AddRefed<nsIEditor> GetAssociatedEditor() override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
 
   virtual bool IsEventAttributeName(nsIAtom* aName) override;
 
+
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              bool aCompileEventHandlers) override;
+  /**
+   * Called when an attribute has just been changed
+   */
+  virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                const nsAttrValue* aValue, bool aNotify) override;
+
 protected:
   virtual ~HTMLBodyElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  RefPtr<BodyRule> mContentStyleRule;
-
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+    <title></title>
+</head>
+<body>
+<script type="text/javascript">
+    function loadFrame() {
+        document.documentElement.className = "";
+    }
+</script>
+<iframe id=frame onload="loadFrame()" src="data:text/html,<body><span lang='en'>text</span></body>" marginwidth="100px" marginheight="100px" width=300px height=300px></iframe>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/body-frame-margin-remove-other-pres-hint.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+    <title></title>
+</head>
+<body>
+<script type="text/javascript">
+    function loadFrame() {
+        let frame = document.getElementById('frame');
+        frame.contentDocument.body.removeAttribute('lang');
+        document.documentElement.className = "";
+    }
+</script>
+<iframe id=frame onload="loadFrame()" src="data:text/html,<body lang='en'>text</body>" marginwidth="100px" marginheight="100px"  width=300px height=300px></iframe>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/body-topmargin-dynamic.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+this text should have a margin of 100px on the top and left
+<p style="direction: rtl">this text should have a margin of 100px on the right</p>
+<script type="text/javascript">
+    document.body.setAttribute("topmargin", "100px");
+    document.body.setAttribute("leftmargin", "100px");
+    document.body.setAttribute("rightmargin", "100px");
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/html/reftests/body-topmargin-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body topmargin="100px" leftmargin="100px" rightmargin="100px">
+this text should have a margin of 100px on the top and left
+<p style="direction: rtl">this text should have a margin of 100px on the right</p>
+</body>
+</html>
--- a/dom/html/reftests/reftest-stylo.list
+++ b/dom/html/reftests/reftest-stylo.list
@@ -30,25 +30,25 @@ fails == 596455-2b.html 596455-2b.html
 == 741776-1.vtt 741776-1.vtt
 
 == bug448564-1_malformed.html bug448564-1_malformed.html
 == bug448564-1_malformed.html bug448564-1_malformed.html
 
 == bug448564-4a.html bug448564-4a.html
 == bug502168-1_malformed.html bug502168-1_malformed.html
 
-fails == responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html
+== responsive-image-load-shortcircuit.html responsive-image-load-shortcircuit.html
 == image-load-shortcircuit-1.html image-load-shortcircuit-1.html
 == image-load-shortcircuit-2.html image-load-shortcircuit-2.html
 
 # Test that image documents taken into account CSS properties like
 # image-orientation when determining the size of the image.
 # (Fuzzy necessary due to pixel-wise comparison of different JPEGs.
 # The vast majority of the fuzziness comes from Linux and WinXP.)
-fails == bug917595-iframe-1.html bug917595-iframe-1.html # Bug 1341647
+== bug917595-iframe-1.html bug917595-iframe-1.html
 fails == bug917595-exif-rotated.jpg bug917595-exif-rotated.jpg
 
 # Test support for SVG-as-image in <picture> elements.
 == bug1106522-1.html bug1106522-1.html
 == bug1106522-2.html bug1106522-2.html
 
 == href-attr-change-restyles.html href-attr-change-restyles.html
 == figure.html figure.html
@@ -58,8 +58,15 @@ fails == bug917595-exif-rotated.jpg bug9
 == table-border-2.html table-border-2.html
 
 # Test imageset is using permissions.default.image
 pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
 pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-with-srcset.html
 
 # Test video with rotation information can be rotated.
 == bug1228601-video-rotation-90.html bug1228601-video-rotation-90.html
+
+# Test that dynamically setting body margin attributes updates style appropriately
+== body-topmargin-dynamic.html body-topmargin-dynamic.html
+
+# Test that dynamically removing a nonmargin mapped attribute does not
+# destroy margins inherited from the frame.
+== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint.html
--- a/dom/html/reftests/reftest.list
+++ b/dom/html/reftests/reftest.list
@@ -58,8 +58,15 @@ fuzzy(3,640) == bug917595-exif-rotated.j
 != table-border-2.html table-border-2-notref.html
 
 # Test imageset is using permissions.default.image
 pref(permissions.default.image,1) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html
 pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784-no-srcset.html
 
 # Test video with rotation information can be rotated.
 == bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html
+
+# Test that dynamically setting body margin attributes updates style appropriately
+== body-topmargin-dynamic.html body-topmargin-ref.html
+
+# Test that dynamically removing a nonmargin mapped attribute does not
+# destroy margins inherited from the frame.
+== body-frame-margin-remove-other-pres-hint.html body-frame-margin-remove-other-pres-hint-ref.html
--- a/dom/plugins/test/reftest/reftest-stylo.list
+++ b/dom/plugins/test/reftest/reftest-stylo.list
@@ -11,17 +11,17 @@ fails == plugin-sanity.html plugin-sanit
 == border-padding-3.html border-padding-3.html
 # The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
 random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(stylo) == pluginproblemui-direction-1.html pluginproblemui-direction-1.html
 random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(stylo) == pluginproblemui-direction-2.html pluginproblemui-direction-2.html
 == plugin-canvas-alpha-zindex.html plugin-canvas-alpha-zindex.html
 fails == plugin-transform-alpha-zindex.html plugin-transform-alpha-zindex.html
 == plugin-busy-alpha-zindex.html plugin-busy-alpha-zindex.html
 == plugin-background.html plugin-background.html
-fails == plugin-background-1-step.html plugin-background-1-step.html # bug 1348723
-fails == plugin-background-2-step.html plugin-background-2-step.html # bug 1348723
-fails == plugin-background-5-step.html plugin-background-5-step.html # bug 1348723
-fails == plugin-background-10-step.html plugin-background-10-step.html # bug 1348723
+== plugin-background-1-step.html plugin-background-1-step.html # bug 1348723
+== plugin-background-2-step.html plugin-background-2-step.html # bug 1348723
+== plugin-background-5-step.html plugin-background-5-step.html # bug 1348723
+== plugin-background-10-step.html plugin-background-10-step.html # bug 1348723
 == plugin-transform-1.html plugin-transform-1.html
 fails == plugin-transform-2.html plugin-transform-2.html
-fails == shrink-1.html shrink-1.html
+== shrink-1.html shrink-1.html
 == update-1.html update-1.html
 skip-if(!haveTestPlugin) == windowless-layers.html windowless-layers.html
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -528,16 +528,19 @@ ServoRestyleManager::AttributeChanged(El
   if (aAttribute == nsGkAtoms::style) {
     PostRestyleEvent(aElement, eRestyle_StyleAttribute, nsChangeHint(0));
   }
   // <td> is affected by the cellpadding on its ancestor table,
   // so we should restyle the whole subtree
   if (aAttribute == nsGkAtoms::cellpadding && aElement->IsHTMLElement(nsGkAtoms::table)) {
     PostRestyleEvent(aElement, eRestyle_Subtree, nsChangeHint(0));
   }
+  if (aElement->IsAttributeMapped(aAttribute)) {
+    Servo_NoteExplicitHints(aElement, eRestyle_Self, nsChangeHint(0));
+  }
 }
 
 nsresult
 ServoRestyleManager::ReparentStyleContext(nsIFrame* aFrame)
 {
   NS_WARNING("stylo: ServoRestyleManager::ReparentStyleContext not implemented");
   return NS_OK;
 }
--- a/layout/reftests/bugs/reftest-stylo.list
+++ b/layout/reftests/bugs/reftest-stylo.list
@@ -277,17 +277,17 @@ fails == 243519-7.html 243519-7.html
 == 249141.xul 249141.xul
 == 249982-1.html 249982-1.html
 == 252920-1.html 252920-1.html
 == 253701-1.html 253701-1.html
 == 255820-1.html 255820-1.html
 == 260406-1.html 260406-1.html
 == 261826-1.xul 261826-1.xul
 == 262151-1.html 262151-1.html
-fails == 262998-1.html 262998-1.html
+== 262998-1.html 262998-1.html
 == 267353-1.html 267353-1.html
 == 269908-1.html 269908-1.html
 == 269908-2.html 269908-2.html
 == 269908-3.html 269908-3.html
 == 269908-4.html 269908-4.html
 == 269908-5.html 269908-5.html
 == 271747-1a.html 271747-1a.html
 == 271747-1b.html 271747-1b.html
@@ -866,20 +866,20 @@ fails == 402940-2.html 402940-2.html
 fails == 402940-3.html 402940-3.html
 == 402950-1.html 402950-1.html
 == 403129-1.html 403129-1.html
 == 403129-2.html 403129-2.html
 == 403129-3.html 403129-3.html
 == 403129-4.html 403129-4.html
 fails random == 403134-1.html 403134-1.html
 == 403181-1.xml 403181-1.xml
-fails == 403249-1a.html 403249-1a.html
-fails == 403249-1b.html 403249-1b.html
-fails == 403249-2a.html 403249-2a.html
-fails == 403249-2b.html 403249-2b.html
+== 403249-1a.html 403249-1a.html
+== 403249-1b.html 403249-1b.html
+== 403249-2a.html 403249-2a.html
+== 403249-2b.html 403249-2b.html
 == 403328-1.html 403328-1.html
 == 403426-1.html 403426-1.html
 == 403455-1.html 403455-1.html
 == 403505-1.xml 403505-1.xml
 fails == 403519-1.html 403519-1.html
 == 403519-2.html 403519-2.html
 == 403656-1.html 403656-1.html
 == 403656-2.html 403656-2.html
@@ -894,18 +894,18 @@ fails == 403962-1.xhtml 403962-1.xhtml #
 == 404030-1-notref2.html 404030-1-notref2.html
 fails == 404123-1.html 404123-1.html
 fails == 404123-2.html 404123-2.html
 == 404123-3.html 404123-3.html
 # may fail "randomly" on OS X, doesn't seem to be rendering usefully anyhow - bug 602469
 random-if(cocoaWidget) HTTP(..) == 404149-1.xul 404149-1.xul
 == 404180-1.html 404180-1.html
 == 404301-1.html 404301-1.html
-fails == 404309-1a.html 404309-1a.html
-fails == 404309-1b.html 404309-1b.html
+== 404309-1a.html 404309-1a.html
+== 404309-1b.html 404309-1b.html
 # Disabled due to compartments for now.
 == data:application/xml,<foo/> data:application/xml,<foo/>
 fails == 404553-1.html 404553-1.html
 == 404666-1.html 404666-1.html
 == 404666-2.html 404666-2.html
 == 405186-1.xhtml 405186-1.xhtml
 == 405305-1.html 405305-1.html
 == 405380-1.html 405380-1.html
@@ -1150,17 +1150,17 @@ fuzzy-if(skiaContent,1,3280) == 438987-2
 == about:blank about:blank
 == 439004-1.html 439004-1.html
 == 439639-1.html 439639-1.html
 == 439910.html 439910.html
 fails == 440112.html 440112.html
 fails == 440149-1.html 440149-1.html
 == 441259-1.html 441259-1.html
 == 441259-2.html 441259-2.html
-fails == 442542-1.html 442542-1.html
+== 442542-1.html 442542-1.html
 fails == 444015-1.html 444015-1.html
 == 444375-1.html 444375-1.html
 fails == 444928-1.html 444928-1.html
 == 444928-2.html 444928-2.html
 == 444928-3.html 444928-3.html
 fails random == 445004-1.html 445004-1.html
 == 445142-1a.html 445142-1a.html
 == 445142-1b.html 445142-1b.html
@@ -1351,18 +1351,18 @@ fails == 485275-1.html 485275-1.html
 == 488649-1.html 488649-1.html
 == 488685-1.html 488685-1.html
 == 488692-1.html 488692-1.html
 == 489868-1.svg 489868-1.svg
 == 490173-1.html 490173-1.html
 == 490173-2.html 490173-2.html
 == 490176-1.html 490176-1.html
 == 490177-1.svg 490177-1.svg
-fails == 490182-1a.html 490182-1a.html
-fails == 490182-1b.html 490182-1b.html
+== 490182-1a.html 490182-1a.html
+== 490182-1b.html 490182-1b.html
 pref(browser.display.focus_ring_width,1) == 491180-1.html 491180-1.html
 pref(browser.display.focus_ring_width,1) == 491180-2.html 491180-2.html
 == 491323-1.xul 491323-1.xul
 == 492239-1.xul 492239-1.xul
 == 492661-1.html 492661-1.html
 fails == 493968-1.html 493968-1.html
 == 494667-1.html 494667-1.html
 == 494667-2.html 494667-2.html
--- a/layout/reftests/css-mediaqueries/reftest-stylo.list
+++ b/layout/reftests/css-mediaqueries/reftest-stylo.list
@@ -11,10 +11,10 @@ fails == mq_print_orientation.xhtml mq_p
 == mq_print_maxheight.xhtml mq_print_maxheight.xhtml
 == mq_print_maxwidth.xhtml mq_print_maxwidth.xhtml
 
 == mq_print_maxwidth_updown.xhtml mq_print_maxwidth_updown.xhtml
 == mq_print_maxheight_updown.xhtml mq_print_maxheight_updown.xhtml
 == mq_print_minheight_updown.xhtml mq_print_minheight_updown.xhtml
 == mq_print_minwidth_updown.xhtml mq_print_minwidth_updown.xhtml
 
-fails == scoped-mq-update.html scoped-mq-update.html
+== scoped-mq-update.html scoped-mq-update.html
 fails == system-metrics-1.html system-metrics-1.html
--- a/layout/reftests/floats/reftest-stylo.list
+++ b/layout/reftests/floats/reftest-stylo.list
@@ -15,17 +15,17 @@ fails == float-outside-block-push.html f
 == 345369-2.html 345369-2.html
 == 345369-3.html 345369-3.html
 == 345369-4.html 345369-4.html
 == 345369-5.html 345369-5.html
 == 429974-1.html 429974-1.html
 == 478834-1.html 478834-1.html
 == 546048-1.html 546048-1.html
 == 775350-1.html 775350-1.html
-fails == 1114329.html 1114329.html
+== 1114329.html 1114329.html
 == 1236745-1.html 1236745-1.html
 fails == 1260031-1.html?display:table 1260031-1.html?display:table
 fails == 1260031-1.html?display:table-cell 1260031-1.html?display:table-cell
 fails == 1260031-1.html?overflow:hidden 1260031-1.html?overflow:hidden
 == 1291110-1.html 1291110-1.html
 == 1291110-2.html 1291110-2.html
 == float-in-rtl-1a.html float-in-rtl-1a.html
 == float-in-rtl-1b.html float-in-rtl-1b.html
--- a/layout/reftests/position-sticky/reftest-stylo.list
+++ b/layout/reftests/position-sticky/reftest-stylo.list
@@ -43,10 +43,10 @@ fails == scrollframe-auto-1.html scrollf
 == inline-3.html inline-3.html
 skip-if(!asyncPan) == inline-4.html inline-4.html
 == column-contain-1a.html column-contain-1a.html
 == column-contain-1b.html column-contain-1b.html
 == column-contain-2.html column-contain-2.html
 == block-in-inline-1.html block-in-inline-1.html
 == block-in-inline-2.html block-in-inline-2.html
 == block-in-inline-3.html block-in-inline-3.html
-fails == block-in-inline-continuations.html block-in-inline-continuations.html
+== block-in-inline-continuations.html block-in-inline-continuations.html
 == inner-table-1.html inner-table-1.html
--- a/layout/reftests/svg/reftest-stylo.list
+++ b/layout/reftests/svg/reftest-stylo.list
@@ -297,19 +297,19 @@ skip-if(d2d) fuzzy-if(cocoaWidget,1,9997
 == opacity-and-pattern-01.svg opacity-and-pattern-01.svg
 fuzzy-if(skiaContent,1,10000) == opacity-and-transform-01.svg opacity-and-transform-01.svg
 fuzzy-if(Android,8,200) == outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01.svg
 fails == outline.html outline.html
 == overflow-on-outer-svg-01.svg overflow-on-outer-svg-01.svg
 == overflow-on-outer-svg-02a.xhtml overflow-on-outer-svg-02a.xhtml
 == overflow-on-outer-svg-02b.xhtml overflow-on-outer-svg-02b.xhtml
 == overflow-on-outer-svg-02c.xhtml overflow-on-outer-svg-02c.xhtml
-fails == overflow-on-outer-svg-02d.xhtml overflow-on-outer-svg-02d.xhtml
+== overflow-on-outer-svg-02d.xhtml overflow-on-outer-svg-02d.xhtml
 == overflow-on-outer-svg-03a.xhtml overflow-on-outer-svg-03a.xhtml
-fails == overflow-on-outer-svg-03b.xhtml overflow-on-outer-svg-03b.xhtml
+== overflow-on-outer-svg-03b.xhtml overflow-on-outer-svg-03b.xhtml
 pref(svg.paint-order.enabled,true) == paint-order-01.svg paint-order-01.svg
 pref(svg.paint-order.enabled,true) == paint-order-02.svg paint-order-02.svg
 pref(svg.paint-order.enabled,true) == paint-order-03.svg paint-order-03.svg
 fuzzy(23,60) fails-if(d2d) == path-01.svg path-01.svg
 == path-02.svg path-02.svg
 == path-03.svg path-03.svg
 == path-04.svg path-04.svg
 == path-05.svg path-05.svg
--- a/layout/style/test/stylo-failures.md
+++ b/layout/style/test/stylo-failures.md
@@ -25,17 +25,16 @@ In which
 Any line which doesn't follow the format above would be ignored like comment.
 
 To use this file, you need to add `--failure-pattern-file=stylo-failures.md`
 to mochitest command.
 
 ## Failures
 
 * Media query support:
-  * test_bug1089417.html [1]
   * test_bug418986-2.html: matchMedia support [3]
   * test_bug453896_deck.html: &lt;style media&gt; support [8]
   * test_media_queries.html [657]
   * test_media_queries_dynamic.html [11]
   * test_media_queries_dynamic_xbl.html [2]
   * test_webkit_device_pixel_ratio.html: -webkit-device-pixel-ratio [3]
   * browser_bug453896.js [8]
   * test_display_mode.html [7]