Bug 1347411 part 2. Fix stylo to properly update styles for the various frames that use FCDATA_WITH_WRAPPING_BLOCK to wrap an anonymous block around their kids. r?heycam draft
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 15 Mar 2017 11:48:29 -0400
changeset 499347 958d0030a496b56c4a6199648b11ed1a278a36bd
parent 499346 26ea9a4d09f743ef7a347aed86d2e12ba336718a
child 499348 fca89ef3814a785b2e60b64dc4efc7914e8da8fe
push id49371
push userbzbarsky@mozilla.com
push dateWed, 15 Mar 2017 16:46:41 +0000
reviewersheycam
bugs1347411
milestone55.0a1
Bug 1347411 part 2. Fix stylo to properly update styles for the various frames that use FCDATA_WITH_WRAPPING_BLOCK to wrap an anonymous block around their kids. r?heycam This handles ::-moz-button-content, ::-moz-html-canvas-content, ::-moz-svg-text, ::-moz-svg-foreign-content. MozReview-Commit-ID: 3xk7214X2uR
layout/base/nsCSSFrameConstructor.cpp
layout/forms/nsHTMLButtonControlFrame.cpp
layout/forms/nsHTMLButtonControlFrame.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsHTMLCanvasFrame.h
layout/reftests/canvas/reftest-stylo.list
layout/reftests/canvas/reftest.list
layout/reftests/canvas/text-indent-1-ref.html
layout/reftests/canvas/text-indent-1a.html
layout/reftests/canvas/text-indent-1b.html
layout/reftests/forms/button/dynamic-text-indent-ref.html
layout/reftests/forms/button/dynamic-text-indent.html
layout/reftests/forms/button/reftest-stylo.list
layout/reftests/forms/button/reftest.list
layout/reftests/svg/foreignObject-dynamic-line-height-01-ref.html
layout/reftests/svg/foreignObject-dynamic-line-height-01.html
layout/reftests/svg/reftest-stylo.list
layout/reftests/svg/reftest.list
layout/reftests/svg/text-stroke-scaling-02-ref.html
layout/reftests/svg/text-stroke-scaling-02a.html
layout/reftests/svg/text-stroke-scaling-02b.html
layout/svg/SVGTextFrame.cpp
layout/svg/SVGTextFrame.h
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGForeignObjectFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3995,16 +3995,18 @@ nsCSSFrameConstructor::ConstructFrameFro
       } else {
         innerFrame = NS_NewBlockFormattingContext(mPresShell, outerSC);
         InitAndRestoreFrame(aState, content, container, innerFrame);
         outerFrame = innerFrame;
       }
 
       SetInitialSingleChild(container, outerFrame);
 
+      container->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
+
       // Now figure out whether newFrame or outerFrame should be the
       // absolute container.
       auto outerDisplay = outerSC->StyleDisplay();
       if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
         maybeAbsoluteContainingBlockDisplay = outerDisplay;
         maybeAbsoluteContainingBlock = outerFrame;
         maybeAbsoluteContainingBlockStyleFrame = outerFrame;
         innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -395,16 +395,29 @@ nsHTMLButtonControlFrame::GetAdditionalS
 
 void
 nsHTMLButtonControlFrame::SetAdditionalStyleContext(int32_t aIndex, 
                                                     nsStyleContext* aStyleContext)
 {
   mRenderer.SetStyleContext(aIndex, aStyleContext);
 }
 
+void
+nsHTMLButtonControlFrame::DoUpdateStyleOfOwnedAnonBoxes(
+  ServoStyleSet& aStyleSet,
+  nsStyleChangeList& aChangeList,
+  nsChangeHint aHintForThisFrame)
+{
+  MOZ_ASSERT(mFrames.FirstChild(), "Must have our button-content anon box");
+  MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
+             "Must only have our button-content anon box");
+  UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
+                            aStyleSet, aChangeList, aHintForThisFrame);
+}
+
 #ifdef DEBUG
 void
 nsHTMLButtonControlFrame::AppendFrames(ChildListID     aListID,
                                        nsFrameList&    aFrameList)
 {
   MOZ_CRASH("unsupported operation");
 }
 
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -92,16 +92,22 @@ public:
   }
 
   virtual bool IsFrameOfType(uint32_t aFlags) const override
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
+  /**
+   * Update the style of our ::-moz-button-content anonymous box.
+   */
+  void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+                                     nsStyleChangeList& aChangeList,
+                                     nsChangeHint aHintForThisFrame) override;
 protected:
   virtual bool IsInput() { return false; }
 
   // Indicates whether we should clip our children's painting to our
   // border-box (either because of "overflow" or because of legacy reasons
   // about how <input>-flavored buttons work).
   bool ShouldClipPaintingToBorderBox();
 
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -414,16 +414,28 @@ nsHTMLCanvasFrame::GetContinuationOffset
       offset += rect.height;
     }
     offset -= mBorderPadding.GetPhysicalMargin(GetWritingMode()).top;
     offset = std::max(0, offset);
   }
   return offset;
 }
 
+void
+nsHTMLCanvasFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
+                                                 nsStyleChangeList& aChangeList,
+                                                 nsChangeHint aHintForThisFrame)
+{
+  MOZ_ASSERT(mFrames.FirstChild(), "Must have our canvas content anon box");
+  MOZ_ASSERT(!mFrames.FirstChild()->GetNextSibling(),
+             "Must only have our canvas content anon box");
+  UpdateStyleOfChildAnonBox(mFrames.FirstChild(),
+                            aStyleSet, aChangeList, aHintForThisFrame);
+}
+
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsHTMLCanvasFrame::AccessibleType()
 {
   return a11y::eHTMLCanvasType;
 }
 #endif
 
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -94,16 +94,22 @@ public:
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   // Inserted child content gets its frames parented by our child block
   virtual nsContainerFrame* GetContentInsertionFrame() override {
     return PrincipalChildList().FirstChild()->GetContentInsertionFrame();
   }
 
+  /**
+   * Update the style of our ::-moz-html-canvas-content anonymous box.
+   */
+  void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+                                     nsStyleChangeList& aChangeList,
+                                     nsChangeHint aHintForThisFrame) override;
 protected:
   virtual ~nsHTMLCanvasFrame();
 
   nscoord GetContinuationOffset(nscoord* aWidth = 0) const;
 
   mozilla::LogicalMargin mBorderPadding;
 };
 
--- a/layout/reftests/canvas/reftest-stylo.list
+++ b/layout/reftests/canvas/reftest-stylo.list
@@ -107,8 +107,11 @@ fails asserts-if(stylo,1) == 1107096-inv
 == 1201272-1.html 1201272-1.html
 == 1224976-1.html 1224976-1.html
 == 1238795-1.html 1238795-1.html
 == 1303534-1.html 1303534-1.html
 
 fails asserts-if(stylo,1) == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1.html # bug 1324700
 fails asserts-if(stylo,1) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2.html # bug 1324700
 fails asserts-if(stylo,1) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1.html # bug 1324700
+
+skip-if(stylo) == text-indent-1a.html text-indent-1a.html # Bug 1347410
+fails == text-indent-1b.html text-indent-1b.html # Bug 1347410
--- a/layout/reftests/canvas/reftest.list
+++ b/layout/reftests/canvas/reftest.list
@@ -103,8 +103,11 @@ fuzzy-if(d2d,12,21) fuzzy-if(skiaContent
 == 1201272-1.html 1201272-1-ref.html
 == 1224976-1.html 1224976-1-ref.html
 == 1238795-1.html 1238795-1-ref.html
 == 1303534-1.html 1303534-1-ref.html
 
 == 1304353-text-global-alpha-1.html 1304353-text-global-alpha-1-ref.html
 fuzzy-if(winWidget,1,14) == 1304353-text-global-alpha-2.html 1304353-text-global-alpha-2-ref.html
 fuzzy-if(winWidget,94,1575) fuzzy-if(cocoaWidget,1,24) == 1304353-text-global-composite-op-1.html 1304353-text-global-composite-op-1-ref.html
+
+== text-indent-1a.html text-indent-1-ref.html
+== text-indent-1b.html text-indent-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<iframe sandbox
+        style="width: 400px"
+        srcdoc="<div style='text-indent: 50vw'>Text</div>"></iframe>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1a.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<iframe sandbox
+        style="width: 400px"
+        srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/canvas/text-indent-1b.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <iframe sandbox
+          style="width: 200px"
+          srcdoc="<canvas style='text-indent: 50vw; display: block'>Text</canvas>"></iframe>
+  <script>
+    onload = function() {
+      var i = document.querySelector("iframe");
+      window.w = i.offsetWidth;
+      i.style.width = "400px";
+      document.documentElement.className = "";
+    }
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/dynamic-text-indent-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+  <button style="text-indent: 50px">Some text</button>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/dynamic-text-indent.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <button>Some text</button>
+  <script>
+    onload = function() {
+      var obj = document.querySelector("button");
+      window.w = obj.getBoundingClientRect().width;
+      obj.style.textIndent = "50px";
+      document.documentElement.className = "";
+    }
+  </script>
+</html>
--- a/layout/reftests/forms/button/reftest-stylo.list
+++ b/layout/reftests/forms/button/reftest-stylo.list
@@ -35,8 +35,10 @@ fails == disabled-6.html disabled-6.html
 == width-auto-size-em-ltr.html width-auto-size-em-ltr.html
 == width-auto-size-ltr.html width-auto-size-ltr.html
 fails == width-exact-fit-ltr.html width-exact-fit-ltr.html # Bug 1341086
 == width-auto-size-em-rtl.html width-auto-size-em-rtl.html
 == width-auto-size-rtl.html width-auto-size-rtl.html
 fails == width-exact-fit-rtl.html width-exact-fit-rtl.html # Bug 1341086
 fails == display-grid-flex-columnset.html display-grid-flex-columnset.html
 == 1317351.html 1317351.html
+
+fails == dynamic-text-indent.html dynamic-text-indent.html # Bug 1341086
--- a/layout/reftests/forms/button/reftest.list
+++ b/layout/reftests/forms/button/reftest.list
@@ -34,8 +34,10 @@ fails-if(Android) == disabled-1.html dis
 == width-auto-size-em-ltr.html width-auto-size-em-ltr-ref.html
 == width-auto-size-ltr.html width-auto-size-ltr-ref.html
 == width-exact-fit-ltr.html width-auto-size-ltr-ref.html
 == width-auto-size-em-rtl.html width-auto-size-em-rtl-ref.html
 == width-auto-size-rtl.html width-auto-size-rtl-ref.html
 == width-exact-fit-rtl.html width-auto-size-rtl-ref.html
 == display-grid-flex-columnset.html display-grid-flex-columnset-ref.html
 == 1317351.html 1317351-ref.html
+
+== dynamic-text-indent.html dynamic-text-indent-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/foreignObject-dynamic-line-height-01-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+  <svg>
+    <foreignObject width="100" height="100" style="line-height: 3">
+      This is long text that wraps.
+    </foreignObject>
+  </svg>
+</htmml>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/foreignObject-dynamic-line-height-01.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <svg>
+    <foreignObject width="100" height="100">
+      This is long text that wraps.
+    </foreignObject>
+  </svg>
+  <script>
+    onload = function() {
+      var obj = document.querySelector("foreignObject");
+      window.w = obj.getBoundingClientRect().width;
+      obj.style.lineHeight = 3;
+      document.documentElement.className = "";
+    }
+  </script>
+</htmml>
--- a/layout/reftests/svg/reftest-stylo.list
+++ b/layout/reftests/svg/reftest-stylo.list
@@ -180,16 +180,17 @@ fuzzy-if(skiaContent,1,800000) == filter
 == foreignObject-start-hidden-01.svg foreignObject-start-hidden-01.svg
 == foreignObject-start-hidden-02.svg foreignObject-start-hidden-02.svg
 == foreignObject-style-change-01.svg foreignObject-style-change-01.svg
 == foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01.html
 == foreignObject-fixedpos-01.html foreignObject-fixedpos-01.html
 == foreignObject-fixedpos-02.html foreignObject-fixedpos-02.html
 == foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-fixedpos-01.html
 == foreignObject-vertical-01.svg foreignObject-vertical-01.svg
+== foreignObject-dynamic-line-height-01.html foreignObject-dynamic-line-height-01.html
 == g-transform-01.svg g-transform-01.svg
 == getElementById-a-element-01.svg getElementById-a-element-01.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01a.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg gradient-live-01b.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01c.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01d.svg
 == gradient-transform-01.svg gradient-transform-01.svg
 == import-svg-01.html import-svg-01.html
@@ -340,16 +341,18 @@ fuzzy-if(OSX==1007,6,2) fuzzy-if(OSX==10
 == text-layout-05.svg text-layout-05.svg
 fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layout-06.svg
 == text-layout-07.svg text-layout-07.svg
 == text-layout-08.svg text-layout-08.svg
 == text-scale-01.svg text-scale-01.svg
 fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02.svg
 HTTP(..) == text-scale-03.svg text-scale-03.svg
 == text-stroke-scaling-01.svg text-stroke-scaling-01.svg
+== text-stroke-scaling-02a.html text-stroke-scaling-02a.html
+== text-stroke-scaling-02b.html text-stroke-scaling-02b.html
 == stroke-dasharray-01.svg stroke-dasharray-01.svg
 fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg stroke-dasharray-02.svg
 fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg stroke-dasharray-03.svg
 == stroke-dasharray-and-pathLength-01.svg stroke-dasharray-and-pathLength-01.svg
 == stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01.svg
 == stroke-dashoffset-01.svg stroke-dashoffset-01.svg
 == stroke-dashoffset-and-pathLength-01.svg stroke-dashoffset-and-pathLength-01.svg
 == stroke-linecap-round-w-zero-length-segs-01.svg stroke-linecap-round-w-zero-length-segs-01.svg
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -179,16 +179,17 @@ fuzzy-if(skiaContent,1,800000) == filter
 == foreignObject-start-hidden-01.svg pass.svg # followup from Bug 596765
 == foreignObject-start-hidden-02.svg pass.svg
 == foreignObject-style-change-01.svg pass.svg
 == foreignObject-dynamic-abspos-01.html foreignObject-dynamic-abspos-01-ref.html
 fuzzy-if(Android,18,600) == foreignObject-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
 == foreignObject-fixedpos-02.html foreignObject-fixedpos-ref.html
 == foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
 == foreignObject-vertical-01.svg foreignObject-vertical-01-ref.svg
+== foreignObject-dynamic-line-height-01.html foreignObject-dynamic-line-height-01-ref.html
 == g-transform-01.svg pass.svg
 == getElementById-a-element-01.svg pass.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01-ref.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg gradient-live-01-ref.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01-ref.svg
 fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01-ref.svg
 == gradient-transform-01.svg pass.svg
 fuzzy-if(skiaContent,1,550) == import-svg-01.html pass.svg
@@ -339,16 +340,19 @@ random-if(gtkWidget) != text-language-01
 == text-layout-05.svg text-layout-05-ref.svg
 fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layout-06-ref.svg
 == text-layout-07.svg text-layout-07-ref.svg
 == text-layout-08.svg text-layout-08-ref.svg
 == text-scale-01.svg text-scale-01-ref.svg
 fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02-ref.svg
 HTTP(..) == text-scale-03.svg text-scale-03-ref.svg
 == text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
+fuzzy(16,3) == text-stroke-scaling-02a.html text-stroke-scaling-02-ref.html # antialiasing
+fuzzy(16,3) == text-stroke-scaling-02b.html text-stroke-scaling-02-ref.html # antialiasing
+== text-stroke-scaling-02a.html text-stroke-scaling-02b.html
 == stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
 fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg pass.svg
 fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg pass.svg
 == stroke-dasharray-and-pathLength-01.svg pass.svg
 == stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg
 == stroke-dashoffset-01.svg pass.svg
 == stroke-dashoffset-and-pathLength-01.svg pass.svg
 == stroke-linecap-round-w-zero-length-segs-01.svg pass.svg
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <svg width="500" height="400">
+    <text x="0" y="20" style="stroke: orange; stroke-width: 0.5px"
+          transform="scale(4)">
+      This is some text
+    </text>
+  </svg>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02a.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <svg width="500" height="400">
+    <text x="0" y="20" style="stroke: orange; stroke-width: 2px"
+          transform="scale(4)">
+      This is some text
+    </text>
+  </svg>
+  <script>
+    onload = function() {
+      var obj = document.querySelector("text");
+      window.w = obj.getBoundingClientRect().width;
+      obj.style.vectorEffect = "non-scaling-stroke";
+      document.documentElement.className = "";
+    }
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/text-stroke-scaling-02b.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+  <svg width="500" height="400">
+    <text x="0" y="20" style="stroke: orange; vector-effect: non-scaling-stroke;
+                              stroke-width: 2px"
+          transform="scale(4)">
+      This is some text
+    </text>
+  </svg>
+</html>
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -5647,8 +5647,18 @@ SVGTextFrame::TransformFrameRectFromText
   // Subtract the mRect offset from the result, as our user space for
   // this frame is relative to the top-left of mRect.
   float factor = presContext->AppUnitsPerCSSPixel();
   gfxPoint framePosition(NSAppUnitsToFloatPixels(mRect.x, factor),
                          NSAppUnitsToFloatPixels(mRect.y, factor));
 
   return result - framePosition;
 }
+
+void
+SVGTextFrame::DoUpdateStyleOfOwnedAnonBoxes(ServoStyleSet& aStyleSet,
+                                            nsStyleChangeList& aChangeList,
+                                            nsChangeHint aHintForThisFrame)
+{
+  MOZ_ASSERT(PrincipalChildList().FirstChild(), "Must have our anon box");
+  UpdateStyleOfChildAnonBox(PrincipalChildList().FirstChild(),
+                            aStyleSet, aChangeList, aHintForThisFrame);
+}
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -366,16 +366,23 @@ public:
    * Takes an app unit rectangle in the coordinate space of a given descendant
    * frame of this frame, and returns a rectangle in the <text> element's user
    * space that covers all parts of rendered runs that intersect with the
    * rectangle.
    */
   gfxRect TransformFrameRectFromTextChild(const nsRect& aRect,
                                           nsIFrame* aChildFrame);
 
+  /**
+   * Update the style of our ::-moz-svg-text anonymous box.
+   */
+  void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+                                     nsStyleChangeList& aChangeList,
+                                     nsChangeHint aHintForThisFrame) override;
+
 private:
   /**
    * Mutation observer used to watch for text positioning attribute changes
    * on descendent text content elements (like <tspan>s).
    */
   class MutationObserver final : public nsStubMutationObserver {
   public:
     explicit MutationObserver(SVGTextFrame* aFrame)
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -584,9 +584,18 @@ nsSVGForeignObjectFrame::GetInvalidRegio
     r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
     nsRect rect = nsSVGUtils::ToCanvasBounds(r, GetCanvasTM(), PresContext());
     rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
     return rect;
   }
   return nsRect();
 }
 
-
+void
+nsSVGForeignObjectFrame::DoUpdateStyleOfOwnedAnonBoxes(
+  ServoStyleSet& aStyleSet,
+  nsStyleChangeList& aChangeList,
+  nsChangeHint aHintForThisFrame)
+{
+  MOZ_ASSERT(PrincipalChildList().FirstChild(), "Must have our anon box");
+  UpdateStyleOfChildAnonBox(PrincipalChildList().FirstChild(),
+                            aStyleSet, aChangeList, aHintForThisFrame);
+}
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -84,16 +84,23 @@ public:
   virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace,
                                       uint32_t aFlags) override;
   virtual bool IsDisplayContainer() override { return true; }
 
   gfxMatrix GetCanvasTM();
 
   nsRect GetInvalidRegion();
 
+  /**
+   * Update the style of our ::-moz-svg-foreign-content anonymous box.
+   */
+  void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
+                                     nsStyleChangeList& aChangeList,
+                                     nsChangeHint aHintForThisFrame) override;
+
 protected:
   // implementation helpers:
   void DoReflow();
   void RequestReflow(nsIPresShell::IntrinsicDirty aType);
 
   // If width or height is less than or equal to zero we must disable rendering
   bool IsDisabled() const { return mRect.width <= 0 || mRect.height <= 0; }