From e3efa9e8c3e586552834408440b6560eca7dcc09 Mon Sep 17 00:00:00 2001 From: Rune Lillesveen Date: Thu, 19 Mar 2026 08:14:29 -0700 Subject: [PATCH 1/2] Snapshot post-layout for all but scroll-timelines 'Run snapshot post-layout state steps' was introduced in the CSSOM View spec[1] to formalize when state for scroll-state() queries, anchor position effects based on scrolling, and scroll-timeline progress is updated. There is a pull request[2] to tell when to invoke snapshotting from the HTML event loop. This CL aligns snapshotting with that CL for all snapshotting except for scroll-timelines. scroll-timeline-multi-pass.tentative.html is updated to align with the one-snapshot-per-resizeObserver-loop-iteration in the HTML spec PR. The difference between scroll-timelines and other snapshotting is that the scroll-timelines are still snapshotted before the first style/layout update in the resizeObserver loop. The reason we keep the pre-layout snapshotting of scroll-timelines for now is that timleines are only progressed before the first style/layout update, which means the post-layout snapshotting will always cause scroll-timelines to be a frame late (with the exception of the first frame) unless we start allowing scroll-timelines to progress in the resizeObserver loop. [1] https://drafts.csswg.org/cssom-view/#run-snapshot-post-layout-state-steps [2] https://github.com/whatwg/html/pull/11613 Bug: 384523570 Change-Id: Iabb35fd06e5a2b9a95a09a25d27d7baad545653f Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7673480 Reviewed-by: Robert Flack Commit-Queue: Rune Lillesveen Reviewed-by: Anders Hartvoll Ruud Cr-Commit-Position: refs/heads/main@{#1601971} --- .../scroll-timeline-multi-pass.tentative.html | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/scroll-animations/css/scroll-timeline-multi-pass.tentative.html b/scroll-animations/css/scroll-timeline-multi-pass.tentative.html index 6a05d7f3dc3066..23b9a67883e8be 100644 --- a/scroll-animations/css/scroll-timeline-multi-pass.tentative.html +++ b/scroll-animations/css/scroll-timeline-multi-pass.tentative.html @@ -1,6 +1,7 @@ ScrollTimelines may trigger multiple style/layout passes + @@ -96,17 +97,21 @@ assert_equals(events1[0][0].contentBoxSize.length, 1); assert_equals(events1[0][0].contentBoxSize[0].inlineSize, 100); - // ScrollTimelines created during the ResizeObserver should remain - // inactive during the frame they're created, so the ResizeObserver - // event should not reflect the animated value. - assert_equals(events2.length, 1); + // The HTML PR[3] that uses the 'run snapshot post-layout state steps', + // would try to create new scroll-timelines for each iteration of the + // resize observer loop, so the ResizeObserver event should reflect the + // animated value for the second observation. + // + // [3] https://github.com/whatwg/html/pull/11613/ + assert_equals(events2.length, 2); assert_equals(events2[0].length, 1); assert_equals(events2[0][0].contentBoxSize.length, 1); assert_equals(events2[0][0].contentBoxSize[0].blockSize, 1); + assert_equals(events2[1].length, 1); + assert_equals(events2[1][0].contentBoxSize.length, 1); + assert_equals(events2[1][0].contentBoxSize[0].blockSize, 100); assert_equals(getComputedStyle(element1).width, '100px'); - - await waitForNextFrame(); assert_equals(getComputedStyle(element2).height, '100px'); }, 'Multiple style/layout passes occur when necessary'); From 8377e061928b680845f4d9112b739fb48412b7a8 Mon Sep 17 00:00:00 2001 From: Jonathan Lee Date: Fri, 3 Apr 2026 14:26:06 -0400 Subject: [PATCH 2/2] Capture uncaught error causing harness flakiness --- .../css/scroll-timeline-multi-pass.tentative.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scroll-animations/css/scroll-timeline-multi-pass.tentative.html b/scroll-animations/css/scroll-timeline-multi-pass.tentative.html index 23b9a67883e8be..0ab5876627f5b0 100644 --- a/scroll-animations/css/scroll-timeline-multi-pass.tentative.html +++ b/scroll-animations/css/scroll-timeline-multi-pass.tentative.html @@ -56,7 +56,7 @@ main.insertBefore(scroller, element1); } - promise_test(async () => { + promise_test(async (t) => { await waitForNextFrame(); let events1 = []; @@ -68,11 +68,11 @@ // // https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles assert_equals(getComputedStyle(element1).width, '1px'); - (new ResizeObserver(entries => { + (new ResizeObserver(entries => t.step_func(() => { events1.push(entries); insertScroller('--timeline2'); assert_equals(getComputedStyle(element2).height, '1px'); - })).observe(element1); + }))).observe(element1); (new ResizeObserver(entries => { events2.push(entries);