diff options
Diffstat (limited to 'testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html')
-rw-r--r-- | testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html b/testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html new file mode 100644 index 0000000000..91668ada5b --- /dev/null +++ b/testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html @@ -0,0 +1,109 @@ +<!DOCTYPE html> +<title>ScrollTimelines may trigger multiple style/layout passes</title> +<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/5261"> +<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="support/testcommon.js"></script> +<style> + @keyframes expand_width { + from { width: 100px; } + to { width: 100px; } + } + @keyframes expand_height { + from { height: 100px; } + to { height: 100px; } + } + main { + height: 0px; + overflow: hidden; + } + .scroller { + height: 100px; + overflow: scroll; + } + .scroller > div { + height: 200px; + } + #element1 { + width: 1px; + animation: expand_width 10s; + animation-timeline: timeline1; + } + #element2 { + height: 1px; + animation: expand_height 10s; + animation-timeline: timeline2; + } +</style> +<main id=main> + <div id=element1></div> + <div> + <div id=element2></div> + </div> +</main> +<script> + setup(assert_implements_animation_timeline); + + function insertScroller(timeline_name) { + let scroller = document.createElement('div'); + scroller.classList.add('scroller'); + scroller.style.scrollTimeline = timeline_name; + scroller.append(document.createElement('div')); + main.insertBefore(scroller, element1); + } + + promise_test(async () => { + await waitForNextFrame(); + + let events1 = []; + let events2 = []; + + insertScroller('timeline1'); + // Even though the scroller was just inserted into the DOM, |timeline1| + // remains inactive until the next frame. + // + // https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles + assert_equals(getComputedStyle(element1).width, '1px'); + (new ResizeObserver(entries => { + events1.push(entries); + insertScroller('timeline2'); + assert_equals(getComputedStyle(element2).height, '1px'); + })).observe(element1); + + (new ResizeObserver(entries => { + events2.push(entries); + })).observe(element2); + + await waitForNextFrame(); + + // According to the basic rules of the spec [1], the timeline is + // inactive at the time the resize observer event was delivered, because + // #scroller1 did not have a layout box at the time style recalc for + // #element1 happened. + // + // However, an additional style/layout pass should take place + // (before resize observer deliveries) if we detect new ScrollTimelines + // in this situation, hence we ultimately do expect the animation to + // apply [2]. + // + // [1] https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles + // [2] https://github.com/w3c/csswg-drafts/issues/5261 + assert_equals(events1.length, 1); + assert_equals(events1[0].length, 1); + 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); + 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(getComputedStyle(element1).width, '100px'); + assert_equals(getComputedStyle(element2).height, '100px'); + }, 'Multiple style/layout passes occur when necessary'); +</script> |