Disable layout optimization when column height may be non-uniform.

We have no way of telling what changes beyond the first column break, so if we
cannot guarantee that the column height *is* and *was* non-uniform, we need to
re-lay out children that may stretch into the unknown.

Review-Url: https://codereview.chromium.org/2562273003
Cr-Commit-Position: refs/heads/master@{#437928}
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html b/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html
new file mode 100644
index 0000000..17202ea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/multicol/dynamic/change-second-row-height.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<p>The word "HEST" should be seen below.</p>
+<div style="position:relative; columns:2; column-gap:0; column-fill:auto; width:400px; height:40px; line-height:20px; orphans:1; widows:1;">
+    <div id="inner" style="columns:2; column-gap:0; column-fill:auto; height:80px;">
+        <div>
+            <br>
+            <br>
+            <br>
+            <br>
+            <br>
+            <span id="elm">HEST</span><br>
+        </div>
+    </div>
+</div>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script>
+test(() => {
+    var inner = document.getElementById("inner");
+    var elm = document.getElementById("elm");
+    assert_equals(elm.offsetLeft, 200);
+    document.body.offsetLeft;
+    inner.style.height = "72px";
+    assert_equals(elm.offsetLeft, 300);
+}, "Change inner multicol height, which only affects the second row.");
+</script>
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 894f7d8..ae74933 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -4720,6 +4720,7 @@
   // just marking and bailing here.
   if (child.isFloating())
     return true;
+  const LayoutFlowThread* flowThread = child.flowThreadContainingBlock();
   LayoutUnit logicalTop = child.logicalTop();
   // Figure out if we really need to force re-layout of the child. We only need
   // to do this if there's a chance that we need to recalculate pagination
@@ -4733,6 +4734,10 @@
       // location as before.
       if (child.offsetToNextPage() != remainingSpace)
         return true;
+      // If column height isn't guaranteed to be uniform, we have no way of
+      // telling what has happened after the first break.
+      if (flowThread && flowThread->mayHaveNonUniformPageLogicalHeight())
+        return true;
     } else if (logicalHeight > remainingSpace) {
       // Last time we laid out this child, we didn't need to break, but now we
       // have to. So we need to relayout.
@@ -4747,7 +4752,6 @@
   // It seems that we can skip layout of this child, but we need to ask the flow
   // thread for permission first. We currently cannot skip over objects
   // containing column spanners.
-  LayoutFlowThread* flowThread = child.flowThreadContainingBlock();
   return flowThread && !flowThread->canSkipLayout(child);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
index 594eafd9..354991c 100644
--- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
+++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.h
@@ -141,6 +141,7 @@
       LayoutUnit contentLogicalHeight) const;
 
   virtual bool isPageLogicalHeightKnown() const { return true; }
+  virtual bool mayHaveNonUniformPageLogicalHeight() const = 0;
   bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
 
   // Return the visual bounding box based on the supplied flow-thread bounding
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
index 807fe96..f532eda6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.cpp
@@ -365,6 +365,15 @@
   return false;
 }
 
+bool LayoutMultiColumnFlowThread::mayHaveNonUniformPageLogicalHeight() const {
+  const LayoutMultiColumnSet* columnSet = firstMultiColumnSet();
+  if (!columnSet)
+    return false;
+  if (columnSet->nextSiblingMultiColumnSet())
+    return true;
+  return enclosingFragmentationContext();
+}
+
 LayoutSize LayoutMultiColumnFlowThread::flowThreadTranslationAtOffset(
     LayoutUnit offsetInFlowThread,
     PageBoundaryRule rule,
diff --git a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
index a1ad047..8264eb4 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
+++ b/third_party/WebKit/Source/core/layout/LayoutMultiColumnFlowThread.h
@@ -216,6 +216,7 @@
   virtual bool needsNewWidth() const;
 
   bool isPageLogicalHeightKnown() const final;
+  bool mayHaveNonUniformPageLogicalHeight() const final;
 
   LayoutSize flowThreadTranslationAtOffset(LayoutUnit,
                                            PageBoundaryRule,