Commit fcaed195 authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

Add test for changing ancestor overflow layer away from non-scrollable layer

This tests the DCHECK fix that was applied in http://crrev.com/1c6d2c6

Bug: 467721, 766140
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I96a2f0e608f4bb22a03e6e6845219de63fba2423
Reviewed-on: https://chromium-review.googlesource.com/668957Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#505773}
parent a3c10f43
<!DOCTYPE html>
<title>Changing the ancestor scroller of a position:sticky element should not crash</title>
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
<meta name="assert" content="This test checks that changing the ancestor scroller of a position:sticky element should not crash." />
<script src="../../../resources/testharness.js"></script>
<script src="../../../resources/testharnessreport.js"></script>
<style>
.outerScroller {
position: relative;
overflow: scroll;
height: 500px;
width: 100px;
}
.innerScroller {
position: relative;
height: 100px;
}
.sticky {
position: sticky;
top: 0;
height: 50px;
width: 50px;
}
.padding {
height: 200px;
}
</style>
<div class='outerScroller'>
<div class='innerScroller'>
<div class='sticky'></div>
<div class='padding'></div>
</div>
</div>
<script>
test(() => {
var outerScroller = document.querySelector('.outerScroller');
var innerScroller = document.querySelector('.innerScroller');
var sticky = document.querySelector('.sticky');
// Querying the offsetTop will force compositing inputs update, setting the
// outer scroller as the ancestor scroller of the sticky element.
var offsetTop = sticky.offsetTop;
// Make the outer scroller non-scrollable (i.e. overflow: visible), and the
// inner scroller into an actual scroller.
outerScroller.style.overflow = 'visible';
innerScroller.style.overflow = 'scroll';
// Querying the offsetTop will force compositing inputs update. This update will
// change the ancestor scroller from the (now non-scrollable) outer scroller
// to the inner one, and should not crash.
offsetTop = sticky.offsetTop;
}, 'Transitioning a sticky away from an ancestor overflow layer that does not have a scrollable area should not crash');
</script>
......@@ -1673,6 +1673,7 @@ jumbo_source_set("unit_tests") {
"paint/VideoPainterTest.cpp",
"paint/ViewPainterTest.cpp",
"paint/compositing/CompositedLayerMappingTest.cpp",
"paint/compositing/CompositingInputsUpdaterTest.cpp",
"paint/compositing/CompositingReasonFinderTest.cpp",
"paint/compositing/PaintLayerCompositorTest.cpp",
"paint/ng/ng_text_fragment_painter_test.cc",
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/layout/LayoutTestHelper.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/compositing/CompositingInputsUpdater.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
using CompositingInputsUpdaterTest = RenderingTest;
// Tests that transitioning a sticky away from an ancestor overflow layer that
// does not have a scrollable area does not crash.
//
// See http://crbug.com/467721#c14
TEST_F(CompositingInputsUpdaterTest,
ChangingAncestorOverflowLayerAwayFromNonScrollableDoesNotCrash) {
// The setup for this test is quite complex. We need UpdateRecursive to
// transition directly from a non-scrollable ancestor overflow layer to a
// scrollable one.
//
// To achieve this both scrollers must always have a PaintLayer (achieved by
// making them positioned), and the previous ancestor overflow must change
// from being scrollable to non-scrollable (achieved by setting its overflow
// property to visible at the same time as we change the inner scroller.)
SetBodyInnerHTML(
"<style>#outerScroller { position: relative; overflow: scroll; "
"height: 500px; width: 100px; }"
"#innerScroller { position: relative; height: 100px; }"
"#sticky { position: sticky; top: 0; height: 50px; width: 50px; }"
"#padding { height: 200px; }</style>"
"<div id='outerScroller'><div id='innerScroller'><div id='sticky'></div>"
"<div id='padding'></div></div></div>");
LayoutBoxModelObject* outer_scroller =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("outerScroller"));
LayoutBoxModelObject* inner_scroller =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("innerScroller"));
LayoutBoxModelObject* sticky =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("sticky"));
// Both scrollers must always have a layer.
EXPECT_TRUE(outer_scroller->Layer());
EXPECT_TRUE(inner_scroller->Layer());
// The inner 'scroller' starts as non-overflow, so the sticky element's
// ancestor overflow layer should be the outer scroller.
EXPECT_TRUE(outer_scroller->GetScrollableArea());
EXPECT_FALSE(inner_scroller->GetScrollableArea());
EXPECT_TRUE(
outer_scroller->GetScrollableArea()->GetStickyConstraintsMap().Contains(
sticky->Layer()));
EXPECT_EQ(sticky->Layer()->AncestorOverflowLayer(), outer_scroller->Layer());
// Now make the outer scroller non-scrollable (i.e. overflow: visible), and
// the inner scroller into an actual scroller.
ToElement(outer_scroller->GetNode())
->SetInlineStyleProperty(CSSPropertyOverflow, "visible");
ToElement(inner_scroller->GetNode())
->SetInlineStyleProperty(CSSPropertyOverflow, "scroll");
// Before we update compositing inputs, validate that the current ancestor
// overflow no longer has a scrollable area.
GetDocument().View()->UpdateLifecycleToLayoutClean();
EXPECT_FALSE(sticky->Layer()->AncestorOverflowLayer()->GetScrollableArea());
EXPECT_EQ(sticky->Layer()->AncestorOverflowLayer(), outer_scroller->Layer());
GetDocument().View()->UpdateAllLifecyclePhases();
// Both scrollers must still have a layer.
EXPECT_TRUE(outer_scroller->Layer());
EXPECT_TRUE(inner_scroller->Layer());
// However now the sticky is hanging off the inner scroller - and most
// importantly we didnt crash when we switched ancestor overflow layers.
EXPECT_TRUE(inner_scroller->GetScrollableArea());
EXPECT_TRUE(
inner_scroller->GetScrollableArea()->GetStickyConstraintsMap().Contains(
sticky->Layer()));
EXPECT_EQ(sticky->Layer()->AncestorOverflowLayer(), inner_scroller->Layer());
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment