- Revision
- 220112
- Author
- [email protected]
- Date
- 2017-08-01 14:42:28 -0700 (Tue, 01 Aug 2017)
Log Message
REGRESSION (r217197): New Yorker website hangs for a long time on load, lots of blank tiles
https://bugs.webkit.org/show_bug.cgi?id=175009
<rdar://problem/33505791>
Reviewed by Simon Fraser.
Source/WebCore:
This patch ensures that we report the desktop, non-frame-flattened frame size for media queries in subframes.
Some websites don't expect the iframes to be expanded to the size of the content and when the media query
callback mutates the content (triggering frame resize), they might end up getting into a never ending layout.
Test: fast/frames/flattening/media-query-growing-content.html
* css/MediaQueryEvaluator.cpp:
(WebCore::orientationEvaluate):
(WebCore::aspectRatioEvaluate):
(WebCore::heightEvaluate):
(WebCore::widthEvaluate):
* page/FrameView.cpp:
(WebCore::FrameView::layout):
(WebCore::FrameView::layoutSizeForMediaQuery const):
(WebCore::FrameView::evaluateMediaQueryList):
* page/FrameView.h:
LayoutTests:
* fast/frames/flattening/media-query-growing-content-expected.txt: Added.
* fast/frames/flattening/media-query-growing-content.html: Added.
* fast/frames/flattening/resources/media-query-min-height-with-flattening.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (220111 => 220112)
--- trunk/LayoutTests/ChangeLog 2017-08-01 21:02:37 UTC (rev 220111)
+++ trunk/LayoutTests/ChangeLog 2017-08-01 21:42:28 UTC (rev 220112)
@@ -1,3 +1,15 @@
+2017-08-01 Zalan Bujtas <[email protected]>
+
+ REGRESSION (r217197): New Yorker website hangs for a long time on load, lots of blank tiles
+ https://bugs.webkit.org/show_bug.cgi?id=175009
+ <rdar://problem/33505791>
+
+ Reviewed by Simon Fraser.
+
+ * fast/frames/flattening/media-query-growing-content-expected.txt: Added.
+ * fast/frames/flattening/media-query-growing-content.html: Added.
+ * fast/frames/flattening/resources/media-query-min-height-with-flattening.html: Added.
+
2017-08-01 Youenn Fablet <[email protected]>
Layout tests with 'https' suffix should be run over HTTPS
Added: trunk/LayoutTests/fast/frames/flattening/media-query-growing-content-expected.txt (0 => 220112)
--- trunk/LayoutTests/fast/frames/flattening/media-query-growing-content-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/frames/flattening/media-query-growing-content-expected.txt 2017-08-01 21:42:28 UTC (rev 220112)
@@ -0,0 +1,2 @@
+
+
Added: trunk/LayoutTests/fast/frames/flattening/media-query-growing-content.html (0 => 220112)
--- trunk/LayoutTests/fast/frames/flattening/media-query-growing-content.html (rev 0)
+++ trunk/LayoutTests/fast/frames/flattening/media-query-growing-content.html 2017-08-01 21:42:28 UTC (rev 220112)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that media query can't get into an ever-growing cycle.</title>
+<script>
+if (window.testRunner)
+ testRunner.dumpAsText();
+if (window.internals)
+ internals.settings.setFrameFlattening("FullyEnabled");
+
+function runTest() {
+ if (window.testRunner) {
+ testRunner.waitUntilDone();
+ setTimeout(function() {
+ testRunner.notifyDone();
+ }, 50);
+ }
+}
+</script>
+</head>
+<body>
+<iframe _onload_="runTest()" src=""
+<div id=testResult></div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/frames/flattening/resources/media-query-min-height-with-flattening.html (0 => 220112)
--- trunk/LayoutTests/fast/frames/flattening/resources/media-query-min-height-with-flattening.html (rev 0)
+++ trunk/LayoutTests/fast/frames/flattening/resources/media-query-min-height-with-flattening.html 2017-08-01 21:42:28 UTC (rev 220112)
@@ -0,0 +1,34 @@
+<style>
+ div {
+ width: 200px;
+ height: 600px;
+ }
+</style>
+<div id=growingDiv></div>
+<script>
+var counter = 0;
+window.matchMedia('(min-height: 200px)').addListener(function(changed) {
+ ++counter;
+ setTimeout(function() {
+ growingDiv.innerText = growingDiv.innerText + ' media query callback ';
+ parent.document.getElementById("testResult").innerText = counter;
+ }, 0);
+});
+
+window.matchMedia('(min-width: 600px)').addListener(function(changed) {
+ ++counter;
+ setTimeout(function() {
+ growingDiv.innerText = growingDiv.innerText + ' media query callback ';
+ parent.document.getElementById("testResult").innerText = counter;
+ }, 0);
+});
+
+window.matchMedia('(min-aspect-ratio: 1/1)').addListener(function(changed) {
+ ++counter;
+ setTimeout(function() {
+ growingDiv.innerText = growingDiv.innerText + ' media query callback ';
+ parent.document.getElementById("testResult").innerText = counter;
+ }, 0);
+});
+
+</script>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (220111 => 220112)
--- trunk/Source/WebCore/ChangeLog 2017-08-01 21:02:37 UTC (rev 220111)
+++ trunk/Source/WebCore/ChangeLog 2017-08-01 21:42:28 UTC (rev 220112)
@@ -1,3 +1,28 @@
+2017-08-01 Zalan Bujtas <[email protected]>
+
+ REGRESSION (r217197): New Yorker website hangs for a long time on load, lots of blank tiles
+ https://bugs.webkit.org/show_bug.cgi?id=175009
+ <rdar://problem/33505791>
+
+ Reviewed by Simon Fraser.
+
+ This patch ensures that we report the desktop, non-frame-flattened frame size for media queries in subframes.
+ Some websites don't expect the iframes to be expanded to the size of the content and when the media query
+ callback mutates the content (triggering frame resize), they might end up getting into a never ending layout.
+
+ Test: fast/frames/flattening/media-query-growing-content.html
+
+ * css/MediaQueryEvaluator.cpp:
+ (WebCore::orientationEvaluate):
+ (WebCore::aspectRatioEvaluate):
+ (WebCore::heightEvaluate):
+ (WebCore::widthEvaluate):
+ * page/FrameView.cpp:
+ (WebCore::FrameView::layout):
+ (WebCore::FrameView::layoutSizeForMediaQuery const):
+ (WebCore::FrameView::evaluateMediaQueryList):
+ * page/FrameView.h:
+
2017-07-26 Jiewen Tan <[email protected]>
Add tests to detect mistakes in backward compatibility when the structured clone algorithm is changed in the future
Modified: trunk/Source/WebCore/css/MediaQueryEvaluator.cpp (220111 => 220112)
--- trunk/Source/WebCore/css/MediaQueryEvaluator.cpp 2017-08-01 21:02:37 UTC (rev 220111)
+++ trunk/Source/WebCore/css/MediaQueryEvaluator.cpp 2017-08-01 21:42:28 UTC (rev 220112)
@@ -304,16 +304,14 @@
if (!view)
return false;
- auto width = view->layoutWidth();
- auto height = view->layoutHeight();
-
+ auto viewSize = view->layoutSizeForMediaQuery();
if (!is<CSSPrimitiveValue>(value)) {
// _expression_ (orientation) evaluates to true if width and height >= 0.
- return height >= 0 && width >= 0;
+ return viewSize.height() >= 0 && viewSize.width() >= 0;
}
auto keyword = downcast<CSSPrimitiveValue>(*value).valueID();
- if (width > height) // Square viewport is portrait.
+ if (viewSize.width() > viewSize.height()) // Square viewport is portrait.
return keyword == CSSValueLandscape;
return keyword == CSSValuePortrait;
}
@@ -324,12 +322,11 @@
// assume if we have a device, its aspect ratio is non-zero
if (!value)
return true;
-
FrameView* view = frame.view();
if (!view)
return true;
-
- return compareAspectRatioValue(value, view->layoutWidth(), view->layoutHeight(), op);
+ auto viewSize = view->layoutSizeForMediaQuery();
+ return compareAspectRatioValue(value, viewSize.width(), viewSize.height(), op);
}
static bool deviceAspectRatioEvaluate(CSSValue* value, const CSSToLengthConversionData&, Frame& frame, MediaFeaturePrefix op)
@@ -445,7 +442,7 @@
FrameView* view = frame.view();
if (!view)
return false;
- int height = view->layoutHeight();
+ int height = view->layoutSizeForMediaQuery().height();
if (!value)
return height;
if (auto* renderView = frame.document()->renderView())
@@ -459,7 +456,7 @@
FrameView* view = frame.view();
if (!view)
return false;
- int width = view->layoutWidth();
+ int width = view->layoutSizeForMediaQuery().width();
if (!value)
return width;
if (auto* renderView = frame.document()->renderView())
Modified: trunk/Source/WebCore/page/FrameView.cpp (220111 => 220112)
--- trunk/Source/WebCore/page/FrameView.cpp 2017-08-01 21:02:37 UTC (rev 220111)
+++ trunk/Source/WebCore/page/FrameView.cpp 2017-08-01 21:42:28 UTC (rev 220112)
@@ -1316,6 +1316,8 @@
bool inChildFrameLayoutWithFrameFlattening = isInChildFrameWithFrameFlattening();
if (inChildFrameLayoutWithFrameFlattening) {
+ if (!m_frameFlatteningViewSizeForMediaQuery)
+ m_frameFlatteningViewSizeForMediaQuery = ScrollView::layoutSize();
startLayoutAtMainFrameViewIfNeeded(allowSubtree);
RenderElement* root = m_layoutRoot ? m_layoutRoot : frame().document()->renderView();
if (!root || !root->needsLayout())
@@ -1370,13 +1372,10 @@
// FIXME: This instrumentation event is not strictly accurate since cached media query results do not persist across StyleResolver rebuilds.
InspectorInstrumentation::mediaQueryResultChanged(document);
}
-
document.evaluateMediaQueryList();
-
// If there is any pagination to apply, it will affect the RenderView's style, so we should
// take care of that now.
applyPaginationToViewport();
-
// Always ensure our style info is up-to-date. This can happen in situations where
// the layout beats any sort of style recalc update that needs to occur.
document.updateStyleIfNeeded();
@@ -5407,5 +5406,10 @@
{
return renderView() && renderView()->shouldPlaceBlockDirectionScrollbarOnLeft();
}
-
+
+IntSize FrameView::layoutSizeForMediaQuery() const
+{
+ return m_frameFlatteningViewSizeForMediaQuery.value_or(ScrollView::layoutSize());
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/page/FrameView.h (220111 => 220112)
--- trunk/Source/WebCore/page/FrameView.h 2017-08-01 21:02:37 UTC (rev 220111)
+++ trunk/Source/WebCore/page/FrameView.h 2017-08-01 21:42:28 UTC (rev 220112)
@@ -216,7 +216,8 @@
bool shouldUpdate() const;
WEBCORE_EXPORT void adjustViewSize();
-
+ IntSize layoutSizeForMediaQuery() const;
+
WEBCORE_EXPORT void setViewportSizeForCSSViewportUnits(IntSize);
IntSize viewportSizeForCSSViewportUnits() const;
@@ -890,6 +891,8 @@
int m_autoSizeFixedMinimumHeight;
// The intrinsic content size decided by autosizing.
IntSize m_autoSizeContentSize;
+ // Report the first computed frame view size to media queries.
+ std::optional<IntSize> m_frameFlatteningViewSizeForMediaQuery;
std::unique_ptr<ScrollableAreaSet> m_scrollableAreas;
std::unique_ptr<ViewportConstrainedObjectSet> m_viewportConstrainedObjects;