Avoid auto-resize re-entrancy problems.
ASSERT(needsLayout()) failed in various layout() methods. The reason is
that autoSizeIfEnabled() will re-enter FrameView::layout(), and upon return,
the rootForThisLayout RenderObject has already been layed out.
This CL moves the auto-sizing up to the top of FrameView::layout() to avoid
the re-entrancy problem with rootForThisLayout.
BUG=403743
Review URL: https://codereview.chromium.org/473903002
git-svn-id: svn://svn.chromium.org/blink/trunk@181258 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/Source/core/frame/FrameView.cpp b/Source/core/frame/FrameView.cpp
index 5d42bda..0112489 100644
--- a/Source/core/frame/FrameView.cpp
+++ b/Source/core/frame/FrameView.cpp
@@ -784,6 +784,9 @@
// Every scroll that happens during layout is programmatic.
TemporaryChange<bool> changeInProgrammaticScroll(m_inProgrammaticScroll, true);
+ if (m_autoSizeInfo)
+ m_autoSizeInfo->autoSizeIfNeeded();
+
m_hasPendingLayout = false;
DocumentLifecycle::Scope lifecycleScope(lifecycle(), DocumentLifecycle::LayoutClean);
@@ -834,8 +837,6 @@
}
}
updateCounters();
- if (m_autoSizeInfo)
- m_autoSizeInfo->autoSizeIfNeeded();
ScrollbarMode hMode;
ScrollbarMode vMode;
diff --git a/Source/web/tests/WebViewTest.cpp b/Source/web/tests/WebViewTest.cpp
index c45519c..ca2e263 100644
--- a/Source/web/tests/WebViewTest.cpp
+++ b/Source/web/tests/WebViewTest.cpp
@@ -82,6 +82,7 @@
#include <gtest/gtest.h>
using namespace blink;
+using blink::FrameTestHelpers::loadFrame;
using blink::FrameTestHelpers::runPendingTasks;
using blink::URLTestHelpers::toKURL;
@@ -2168,4 +2169,20 @@
EXPECT_EQ(expected, actual);
}
+TEST_F(WebViewTest, AutoResizeSubtreeLayout)
+{
+ std::string url = m_baseURL + "subtree-layout.html";
+ URLTestHelpers::registerMockedURLLoad(toKURL(url), "subtree-layout.html");
+ WebView* webView = m_webViewHelper.initialize(true);
+
+ webView->enableAutoResizeMode(WebSize(200, 200), WebSize(200, 200));
+ loadFrame(webView->mainFrame(), url);
+
+ blink::FrameView* frameView = m_webViewHelper.webViewImpl()->mainFrameImpl()->frameView();
+
+ // Auto-resizing used to ASSERT(needsLayout()) in RenderBlockFlow::layout. This EXPECT is
+ // merely a dummy. The real test is that we don't trigger asserts in debug builds.
+ EXPECT_FALSE(frameView->needsLayout());
+};
+
} // namespace
diff --git a/Source/web/tests/data/subtree-layout.html b/Source/web/tests/data/subtree-layout.html
new file mode 100644
index 0000000..c96b0a6
--- /dev/null
+++ b/Source/web/tests/data/subtree-layout.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<style>
+/* RenderObject::objectIsRelayoutBoundary() should be true */
+#relayoutBoundary {
+ overflow: hidden;
+ width: 100px;
+ height: 100px;
+}
+</style>
+<div id="relayoutBoundary">
+ <div id="layouter"></div>
+</div>
+<script>
+document.body.offsetTop;
+document.getElementById("layouter").style.position = "relative";
+document.body.offsetTop;
+</script>