summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/scroll-animations/css/scroll-timeline-multi-pass.tentative.html
diff options
context:
space:
mode:
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.html109
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>