Bug 1520722 Part 2 - When removing bidi continuations, go no further than the block which needs resolution. r=dbaron
authorTing-Yu Lin <aethanyc@gmail.com>
Fri, 01 Feb 2019 06:14:27 +0000
changeset 456391 1617ad03a14ef357d9e68c103f9291ea8982759a
parent 456390 506261cc5d79c01c770fcb2e9d450ba8e92c98b1
child 456392 9e6217a541aa84c3bd635459d842b6fbfed311de
push id19
push usermdeboer@mozilla.com
push dateFri, 01 Feb 2019 10:05:45 +0000
reviewersdbaron
bugs1520722
milestone67.0a1
Bug 1520722 Part 2 - When removing bidi continuations, go no further than the block which needs resolution. r=dbaron When doing bidi resolution for column-content blocks, we may still traverse the parent chain up in RemoveBidiContinuation, reach nsColumnSetFrame, and accidentally convert nsColumnSetFrame's continuation into fluid ones. Differential Revision: https://phabricator.services.mozilla.com/D17551
layout/base/nsBidiPresUtils.cpp
layout/reftests/columns/column-span-bidi-1-ref.html
layout/reftests/columns/column-span-bidi-1.html
layout/reftests/columns/reftest.list
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -122,33 +122,39 @@ struct MOZ_STACK_CLASS BidiParagraphData
   nsDataHashtable<nsPtrHashKey<const nsIContent>, int32_t> mContentToFrameIndex;
   // Cached presentation context for the frames we're processing.
   nsPresContext* mPresContext;
   bool mIsVisual;
   bool mRequiresBidi;
   nsBidiLevel mParaLevel;
   nsIContent* mPrevContent;
   nsIFrame* mPrevFrame;
+  // Cache the block frame which needs bidi resolution.
+  const nsIFrame* mBlock;
 #ifdef DEBUG
   // Only used for NOISY debug output.
   nsBlockFrame* mCurrentBlock;
 #endif
 
   explicit BidiParagraphData(nsBlockFrame* aBlockFrame)
       : mPresContext(aBlockFrame->PresContext()),
         mIsVisual(mPresContext->IsVisualMode()),
         mRequiresBidi(false),
         mParaLevel(nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->Style())),
         mPrevContent(nullptr),
-        mPrevFrame(nullptr)
+        mPrevFrame(nullptr),
+        mBlock(aBlockFrame)
 #ifdef DEBUG
         ,
         mCurrentBlock(aBlockFrame)
 #endif
   {
+    MOZ_ASSERT(mBlock->FirstContinuation() == mBlock,
+               "mBlock must be the first continuation!");
+
     if (mParaLevel > 0) {
       mRequiresBidi = true;
     }
 
     if (mIsVisual) {
       /**
        * Drill up in content to detect whether this is an element that needs to
        * be rendered with logical order even on visual pages.
@@ -1774,17 +1780,19 @@ void nsBidiPresUtils::RemoveBidiContinua
   bidiData.precedingControl = kBidiLevelNone;
   for (int32_t index = aFirstIndex + 1; index <= aLastIndex; index++) {
     nsIFrame* frame = aBpd->FrameAt(index);
     if (frame != NS_BIDI_CONTROL_FRAME) {
       // Make the frame and its continuation ancestors fluid,
       // so they can be reused or deleted by normal reflow code
       frame->SetProperty(nsIFrame::BidiDataProperty(), bidiData);
       frame->AddStateBits(NS_FRAME_IS_BIDI);
-      while (frame) {
+
+      // Go no further than the block which needs resolution.
+      while (frame && aBpd->mBlock != frame->FirstContinuation()) {
         nsIFrame* prev = frame->GetPrevContinuation();
         if (prev) {
           MakeContinuationFluid(prev, frame);
           frame = frame->GetParent();
         } else {
           break;
         }
       }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/column-span-bidi-1-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+  <meta charset="utf-8">
+  <style>
+  h3 {
+    column-span: all;
+  }
+  html {
+    columns: 3em;
+  }
+  </style>
+
+  <body onload=go()>
+    <h3></h3>
+    <!-- The following content will be in a -moz-column-content frame where it's
+         parent is a hard continuation of a nsColumnSetFrame. -->
+    ltr
+    ltr
+    <div dir="rtl">rtl</div>
+    <div></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/columns/column-span-bidi-1.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+  <meta charset="utf-8">
+  <style>
+  h3 {
+    column-span: all;
+  }
+  html {
+    columns: 3em;
+  }
+  </style>
+  <script>
+  function go() {
+    document.body.offsetHeight;
+    document.body.appendChild(a);
+    document.documentElement.removeAttribute("class");
+  }
+  </script>
+  <body onload=go()>
+    <h3>
+      <div id="a"></div>
+    </h3>
+    <!-- The following content will be in a -moz-column-content frame where it's
+         parent is a hard continuation of a nsColumnSetFrame. -->
+    ltr
+    ltr
+    <div dir="rtl">rtl</div>
+  </body>
+</html>
--- a/layout/reftests/columns/reftest.list
+++ b/layout/reftests/columns/reftest.list
@@ -34,8 +34,9 @@ fuzzy-if(OSX,0-32,0-1000) == columnfill-
 == columnrule-overflow.html columnrule-overflow-ref.html
 == columns-table-caption-000.html columns-table-caption-000-ref.html
 == positioning-transforms-bug1112501.html positioning-transforms-bug1112501-ref.html
 fuzzy-if(browserIsRemote&&winWidget,0-142,0-276) == fieldset-columns-001.html fieldset-columns-001-ref.html
 == dynamic-change-with-overflow-1.html dynamic-change-with-overflow-1-ref.html
 == dynamic-text-indent-1.html dynamic-text-indent-1-ref.html
 == dynamic-text-indent-2.html dynamic-text-indent-2-ref.html
 == break-avoid-line-position-1.html break-avoid-line-position-1-ref.html
+pref(layout.css.column-span.enabled,true) == column-span-bidi-1.html column-span-bidi-1-ref.html