Bug 1375315. Make sure to update block pseudo-element styles on various anonymous blocks. r?emilio draft
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 22 Jun 2017 11:24:11 -0400
changeset 599034 81062674e9ea44ad54704681634c69c9412cda81
parent 599033 7e3f28ca5a8ffa04c97bbcac34e37fea4f60552b
child 634660 008427e9383882e9abe72c98abc873c10fcb4c51
push id65404
push userbzbarsky@mozilla.com
push dateThu, 22 Jun 2017 15:24:44 +0000
reviewersemilio
bugs1375315
milestone56.0a1
Bug 1375315. Make sure to update block pseudo-element styles on various anonymous blocks. r?emilio MozReview-Commit-ID: HBabvfWYgdP
layout/base/ServoRestyleManager.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsFrame.cpp
layout/reftests/bugs/1375315-1-ref.html
layout/reftests/bugs/1375315-1.html
layout/reftests/bugs/1375315-10-ref.html
layout/reftests/bugs/1375315-10.html
layout/reftests/bugs/1375315-11-ref.html
layout/reftests/bugs/1375315-11.html
layout/reftests/bugs/1375315-12-ref.html
layout/reftests/bugs/1375315-12.html
layout/reftests/bugs/1375315-2-ref.html
layout/reftests/bugs/1375315-2.html
layout/reftests/bugs/1375315-3-ref.html
layout/reftests/bugs/1375315-3.html
layout/reftests/bugs/1375315-4-ref.html
layout/reftests/bugs/1375315-4.html
layout/reftests/bugs/1375315-5-ref.html
layout/reftests/bugs/1375315-5.html
layout/reftests/bugs/1375315-6-ref.html
layout/reftests/bugs/1375315-6.html
layout/reftests/bugs/1375315-7-ref.html
layout/reftests/bugs/1375315-7.html
layout/reftests/bugs/1375315-8-ref.html
layout/reftests/bugs/1375315-8.html
layout/reftests/bugs/1375315-9-ref.html
layout/reftests/bugs/1375315-9.html
layout/reftests/bugs/reftest.list
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -246,32 +246,16 @@ private:
   ServoRestyleState& mParentRestyleState;
   RefPtr<nsStyleContext> mStyle;
   bool mShouldPostHints;
   bool mShouldComputeHints;
   nsChangeHint mComputedHint;
 };
 
 static void
-UpdateBlockFramePseudoElements(nsBlockFrame* aFrame,
-                               ServoRestyleState& aRestyleState)
-{
-  if (nsBulletFrame* bullet = aFrame->GetBullet()) {
-    RefPtr<nsStyleContext> newContext =
-      aRestyleState.StyleSet().ResolvePseudoElementStyle(
-        aFrame->GetContent()->AsElement(),
-        bullet->StyleContext()->GetPseudoType(),
-        aFrame->StyleContext(),
-        /* aPseudoElement = */ nullptr);
-
-    aFrame->UpdateStyleOfOwnedChildFrame(bullet, newContext, aRestyleState);
-  }
-}
-
-static void
 UpdateBackdropIfNeeded(nsIFrame* aFrame, ServoRestyleState& aRestyleState)
 {
   const nsStyleDisplay* display = aFrame->StyleContext()->StyleDisplay();
   if (display->mTopLayer != NS_STYLE_TOP_LAYER_TOP) {
     return;
   }
 
   // Elements in the top layer are guaranteed to have absolute or fixed
@@ -302,18 +286,17 @@ UpdateBackdropIfNeeded(nsIFrame* aFrame,
     backdropFrame, newContext, aRestyleState);
 }
 
 static void
 UpdateFramePseudoElementStyles(nsIFrame* aFrame,
                                ServoRestyleState& aRestyleState)
 {
   if (aFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
-    UpdateBlockFramePseudoElements(static_cast<nsBlockFrame*>(aFrame),
-                                   aRestyleState);
+    static_cast<nsBlockFrame*>(aFrame)->UpdatePseudoElementStyles(aRestyleState);
   }
 
   UpdateBackdropIfNeeded(aFrame, aRestyleState);
 }
 
 bool
 ServoRestyleManager::ProcessPostTraversal(Element* aElement,
                                           nsStyleContext* aParentContext,
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -50,16 +50,18 @@
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSFrameConstructor.h"
 #include "TextOverflow.h"
 #include "nsIFrameInlines.h"
 #include "CounterStyleManager.h"
 #include "nsISelection.h"
 #include "mozilla/dom/HTMLDetailsElement.h"
 #include "mozilla/dom/HTMLSummaryElement.h"
+#include "mozilla/ServoRestyleManager.h"
+#include "mozilla/ServoStyleSet.h"
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsBidiPresUtils.h"
 
 #include <inttypes.h>
 
@@ -7074,24 +7076,18 @@ nsBlockFrame::CreateBulletFrameForListIt
                                            bool aListStylePositionInside)
 {
   nsIPresShell* shell = PresContext()->PresShell();
 
   CSSPseudoElementType pseudoType = aCreateBulletList ?
     CSSPseudoElementType::mozListBullet :
     CSSPseudoElementType::mozListNumber;
 
-  nsStyleContext* parentStyle =
-    CorrectStyleParentFrame(this,
-                            nsCSSPseudoElements::GetPseudoAtom(pseudoType))->
-    StyleContext();
-
-  RefPtr<nsStyleContext> kidSC = shell->StyleSet()->
-    ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
-                              parentStyle, nullptr);
+  RefPtr<nsStyleContext> kidSC = ResolveBulletStyle(pseudoType,
+                                                    shell->StyleSet());
 
   // Create bullet frame
   nsBulletFrame* bullet = new (shell) nsBulletFrame(kidSC);
   bullet->Init(mContent, this, nullptr);
 
   // If the list bullet frame should be positioned inside then add
   // it to the flow now.
   if (aListStylePositionInside) {
@@ -7514,16 +7510,40 @@ nsBlockFrame::ResolveBidi()
   nsPresContext* presContext = PresContext();
   if (!presContext->BidiEnabled()) {
     return NS_OK;
   }
 
   return nsBidiPresUtils::Resolve(this);
 }
 
+void
+nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState)
+{
+  if (nsBulletFrame* bullet = GetBullet()) {
+    CSSPseudoElementType type = bullet->StyleContext()->GetPseudoType();
+    RefPtr<nsStyleContext> newBulletStyle =
+      ResolveBulletStyle(type, &aRestyleState.StyleSet());
+    UpdateStyleOfOwnedChildFrame(bullet, newBulletStyle, aRestyleState);
+  }
+}
+
+already_AddRefed<nsStyleContext>
+nsBlockFrame::ResolveBulletStyle(CSSPseudoElementType aType,
+                                 StyleSetHandle aStyleSet)
+{
+  nsStyleContext* parentStyle =
+    CorrectStyleParentFrame(this,
+                            nsCSSPseudoElements::GetPseudoAtom(aType))->
+    StyleContext();
+
+  return aStyleSet->ResolvePseudoElementStyle(mContent->AsElement(), aType,
+                                              parentStyle, nullptr);
+}
+
 #ifdef DEBUG
 void
 nsBlockFrame::VerifyLines(bool aFinalCheckOK)
 {
   if (!gVerifyLines) {
     return;
   }
   if (mLines.empty()) {
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -39,16 +39,18 @@ enum class LineReflowStatus {
   // the next page or column if it's not the first line on the current page/column.
   Truncated
 };
 
 class nsBlockInFlowLineIterator;
 class nsBulletFrame;
 namespace mozilla {
 class BlockReflowInput;
+class ServoRestyleState;
+class StyleSetHandle;
 } // namespace mozilla
 
 /**
  * Some invariants:
  * -- The overflow out-of-flows list contains the out-of-
  * flow frames whose placeholders are in the overflow list.
  * -- A given piece of content has at most one placeholder
  * frame in a block's normal child list.
@@ -390,16 +392,22 @@ public:
    */
   static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
 
   struct FrameLines {
     nsLineList mLines;
     nsFrameList mFrames;
   };
 
+  /**
+   * Update the styles of our various pseudo-elements (bullets, first-letter,
+   * first-line, etc).
+   */
+  void UpdatePseudoElementStyles(mozilla::ServoRestyleState& aRestyleState);
+
 protected:
   explicit nsBlockFrame(nsStyleContext* aContext, ClassID aID = kClassID)
     : nsContainerFrame(aContext, aID)
     , mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
     , mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
   {
 #ifdef DEBUG
   InitDebugFlags();
@@ -898,16 +906,23 @@ protected:
   // this block until our next continuation takes them.
   nsFrameList* GetPushedFloats() const;
   // Get the pushed floats list, or if there is not currently one,
   // make a new empty one.
   nsFrameList* EnsurePushedFloats();
   // Remove and return the pushed floats list.
   nsFrameList* RemovePushedFloats();
 
+  // Resolve a style context for our bullet frame.  aType should be
+  // mozListBullet or mozListNumber.  Passing in the style set is an
+  // optimization, because all callsites have it.
+  already_AddRefed<nsStyleContext> ResolveBulletStyle(
+    mozilla::CSSPseudoElementType aType,
+    mozilla::StyleSetHandle aStyleSet);
+
 #ifdef DEBUG
   void VerifyLines(bool aFinalCheckOK);
   void VerifyOverflowSituation();
   int32_t GetDepth() const;
 #endif
 
   nscoord mMinWidth, mPrefWidth;
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10226,16 +10226,27 @@ nsIFrame::UpdateStyleOfChildAnonBox(nsIF
 
   nsChangeHint childHint =
     UpdateStyleOfOwnedChildFrame(aChildFrame, newContext, aRestyleState);
 
   // Now that we've updated the style on aChildFrame, check whether it itself
   // has anon boxes to deal with.
   ServoRestyleState childrenState(aRestyleState, childHint);
   aChildFrame->UpdateStyleOfOwnedAnonBoxes(childrenState);
+
+  // Assuming anon boxes don't have ::backdrop associated with them... if that
+  // ever changes, we'd need to handle that here, like we do in
+  // ServoRestyleManager::ProcessPostTraversal
+
+  // We do need to handle block pseudo-elements here, though.  Especially list
+  // bullets.
+  if (aChildFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
+    auto block = static_cast<nsBlockFrame*>(aChildFrame);
+    block->UpdatePseudoElementStyles(childrenState);
+  }
 }
 
 nsChangeHint
 nsIFrame::UpdateStyleOfOwnedChildFrame(nsIFrame* aChildFrame,
                                        nsStyleContext* aNewStyleContext,
                                        ServoRestyleState& aRestyleState)
 {
   // Figure out whether we have an actual change.  It's important that we do
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ul>
+  <li style="overflow: hidden; list-style-position: inside; color: green">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("li").style.color = "green";
+  }
+</script>
+<ul>
+  <li style="overflow: hidden; list-style-position: inside; color: red">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-10-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<button style="display: list-item; color: green">
+  Bullet should be green.
+</button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-10.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("button").style.color = "green";
+  }
+</script>
+<button style="display: list-item; color: red">
+  Bullet should be green.
+</button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-11-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<select style="display: list-item; list-style-position: inside; color: green">
+  <option>Bullets should be green</option>
+</select>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-11.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("select").style.color = "green";
+  }
+</script>
+<select style="display: list-item; list-style-position: inside; color: red">
+  <option>Bullets should be green</option>
+</select>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-12-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<select multiple
+        style="display: list-item; list-style-position: inside; color: green">
+  <option>Bullet should be green</option>
+</select>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-12.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("select").style.color = "green";
+  }
+</script>
+<select multiple
+        style="display: list-item; list-style-position: inside; color: red">
+  <option>Bullet should be green</option>
+</select>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-2-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ul>
+  <li style="column-count: 2; width: 50px; list-style-position: inside; color: green">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("li").style.color = "green";
+  }
+</script>
+<ul>
+  <li style="column-count: 2; width: 50px; list-style-position: inside; color: red">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-3-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ul>
+  <li style="column-count: 2; width: 50px; color: green">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-3.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("li").style.color = "green";
+  }
+</script>
+<ul>
+  <li style="column-count: 2; width: 50px; color: red">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-4-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ul>
+  <li style="column-count: 2; width: 50px; color: green">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-4.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("li").style.color = "green";
+  }
+</script>
+<ul>
+  <li style="column-count: 2; width: 50px; color: red">
+    Bullet should be green.
+  </li>
+</ul>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-5-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<details open
+         style="display: list-item; padding: 40px; margin: 40px; color: green">
+    Bullet should be green.
+</details>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-5.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("details").style.color = "green";
+  }
+</script>
+<details open
+         style="display: list-item; padding: 40px; margin: 40px; color: red">
+    Bullet should be green.
+</details>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-6-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<details open
+         style="display: list-item; list-style-position: inside; color: green">
+    Bullet should be green.
+</details>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-6.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("details").style.color = "green";
+  }
+</script>
+<details open
+         style="display: list-item; list-style-position: inside; color: red">
+    Bullet should be green.
+</details>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-7-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<fieldset>
+  <legend style="display: list-item; color: green">Bullet should be green</legend>
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-7.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("legend").style.color = "green";
+  }
+</script>
+<fieldset>
+  <legend style="display: list-item; color: red">Bullet should be green</legend>
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-8-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<fieldset style="display: list-item; margin: 40px; color: green">
+  Bullet should be green
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-8.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("fieldset").style.color = "green";
+  }
+</script>
+<fieldset style="display: list-item; margin: 40px; color: red">
+  Bullet should be green
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-9-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<fieldset style="display: list-item; column-count: 2; width: 100px; color: green">
+  Bullet should be green
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1375315-9.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+  onload = function() {
+    var height = document.body.offsetHeight; // Flush layout
+    document.querySelector("fieldset").style.color = "green";
+  }
+</script>
+<fieldset style="display: list-item; column-count: 2; width: 100px; color: red">
+  Bullet should be green
+</fieldset>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2010,9 +2010,21 @@ fails-if(!stylo||styloVsGecko) == 136516
 == 1366144.html 1366144-ref.html
 == 1367592-1.html 1367592-1-ref.html
 == 1368113-1.html 1368113-1-ref.html
 == 1369584-1a.html 1369584-1-ref.html
 == 1369584-1b.html 1369584-1-ref.html
 == 1369954-1.xhtml 1369954-1-ref.xhtml
 == 1369985-1.html 1369985-1-ref.html
 == 1371130.xhtml 1371130-ref.xhtml
+== 1375315-1.html 1375315-1-ref.html
+== 1375315-2.html 1375315-2-ref.html
+== 1375315-3.html 1375315-3-ref.html
+== 1375315-4.html 1375315-4-ref.html
+== 1375315-5.html 1375315-5-ref.html
+== 1375315-6.html 1375315-6-ref.html
+== 1375315-7.html 1375315-7-ref.html
+== 1375315-8.html 1375315-8-ref.html
+== 1375315-9.html 1375315-9-ref.html
+== 1375315-10.html 1375315-10-ref.html
+== 1375315-11.html 1375315-11-ref.html
+== 1375315-12.html 1375315-12-ref.html
 == 1374062.html 1374062-ref.html