Bug 1527353 [wpt PR 15335] - [LayoutNG] Invalidate layout when OOF-positioned gets added/removed., a=testonly
authorIan Kilpatrick <ikilpatrick@chromium.org>
Tue, 05 Mar 2019 12:14:48 +0000
changeset 525442 43322b4cde08eb96eb0ce8837af809d5c69ee508
parent 525441 35d0e81b48a8edd80664f47a99cf23b9331e9ce5
child 525443 51e1957476b218de66b0d3587106a8fb7589e244
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1527353, 15335, 635619, 1396777, 632256
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1527353 [wpt PR 15335] - [LayoutNG] Invalidate layout when OOF-positioned gets added/removed., a=testonly Automatic update from web-platform-tests [LayoutNG] Invalidate layout when OOF-positioned gets added/removed. This patch allows us to reuse a cached layout result when we have OOF-positioned descendants in the result. In order to do this whenever a OOF-positioned object gets added or removed we invalidate the parent chain for all objects which may contain this element inside its layout result. There are more optimal versions of this approach, which I've noted inside a comment, but this seems good enough for now. Bug: 635619 Change-Id: I4b29fcc26154dcd76cee55455d83558c6cf798fa Reviewed-on: https://chromium-review.googlesource.com/c/1396777 Reviewed-by: Emil A Eklund <eae@chromium.org> Reviewed-by: Morten Stenshorne <mstensho@chromium.org> Reviewed-by: Aleks Totic <atotic@chromium.org> Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org> Cr-Commit-Position: refs/heads/master@{#632256} -- wpt-commits: bbe1144015e708f62b9ae30b3770884db94e504b wpt-pr: 15335
testing/web-platform/tests/css/css-position/position-absolute-dynamic-containing-block.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-position/position-absolute-dynamic-containing-block.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<title>CSS Position: position:absolute dynamic containing block</title>
+<link rel="author" title="mailto:atotic@google.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/css-position-3/#def-cb">
+<meta name="assert" content="Tests changes in containing block for out-of-flow positioned descendants.">
+<style>
+
+#outer {
+  width: 400px;
+  height: 300px;
+  outline: black solid 1px;
+}
+#intermediate {
+  width: 300px;
+  height: 200px;
+  outline: gray solid 1px;
+}
+#target {
+  background: green;
+}
+.abs {
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+.fixed {
+  position: fixed;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+.abs-container {
+  position: relative;
+}
+.fixed-container {
+  will-change: transform;
+}
+div {
+  padding: 5px;
+}
+</style>
+<!-- This tests potential caching of out-of-flow positioned descendants. -->
+<div id="outer">
+  <div>
+    <div id="intermediate">
+      <div>
+        <div id="target">TTT</div>
+        <div id="noLayout1"></div>
+      </div>
+      <div id="noLayout2"></div>
+    </div>
+  </div>
+</div>
+<script>
+  let outer = document.querySelector("#outer");
+  let intermediate = document.querySelector("#intermediate");
+  let target = document.querySelector("#target");
+  let padding = 5;
+
+  function cleanup() {
+    outer.className = "";
+    intermediate.className = "";
+    target.className = "";
+    document.body.offsetTop;
+  }
+
+  test( t => {
+    t.add_cleanup(cleanup);
+    outer.classList.add("abs-container");
+    target.classList.add("abs");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+    intermediate.classList.add("abs-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+  }, "abs containing block moves from outer to intermediate" );
+  test( t => {
+    t.add_cleanup(cleanup);
+    target.classList.add("abs");
+    intermediate.classList.add("abs-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+    outer.classList.add("abs-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+    intermediate.classList.remove("abs-container");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+  }, "abs containing block moves from intermediate to outer" );
+  test( t => {
+    t.add_cleanup(cleanup);
+    target.classList.add("abs");
+    outer.classList.add("abs-container");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+    target.classList.remove("abs");
+    assert_equals(target.offsetWidth, intermediate.offsetWidth - 4 * padding);
+  }, "target is no longer absolute");
+  test( t => {
+    t.add_cleanup(cleanup);
+    outer.classList.add("abs-container");
+    assert_equals(target.offsetWidth, intermediate.offsetWidth - 4 * padding);
+    target.classList.add("abs");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+  }, "target becomes absolute");
+
+ // Repeat same tests with fixed
+  test( t => {
+    t.add_cleanup(cleanup);
+    outer.classList.add("fixed-container");
+    target.classList.add("fixed");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+    intermediate.classList.add("fixed-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+  }, "fixed containing block moves from outer to intermediate" );
+  test( t => {
+    t.add_cleanup(cleanup);
+    target.classList.add("fixed");
+    intermediate.classList.add("fixed-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+    outer.classList.add("fixed-container");
+    assert_equals(target.offsetHeight, intermediate.offsetHeight);
+    intermediate.classList.remove("fixed-container");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+  }, "fixed containing block moves from intermediate to outer" );
+  test( t => {
+    t.add_cleanup(cleanup);
+    target.classList.add("fixed");
+    outer.classList.add("fixed-container");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+    target.classList.remove("fixed");
+    assert_equals(target.offsetWidth, intermediate.offsetWidth - 4 * padding);
+  }, "target is no longer fixed");
+  test( t => {
+    t.add_cleanup(cleanup);
+    outer.classList.add("fixed-container");
+    assert_equals(target.offsetWidth, intermediate.offsetWidth - 4 * padding);
+    target.classList.add("fixed");
+    assert_equals(target.offsetHeight, outer.offsetHeight);
+  }, "target becomes fixed");
+</script>