invalidating-animation-before-start-time-synced.html (2518B)
1 <!DOCTYPE html> 2 <link rel="author" href="mailto:bokan@chromium.org"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <style> 6 .target { 7 width: 100px; 8 height: 100px; 9 background-color: dodgerblue; 10 } 11 </style> 12 <script> 13 function jank() { 14 let start = performance.now(); 15 let x = 0; 16 while(performance.now() - start < 100) { 17 x++; 18 } 19 } 20 21 function target1() { return document.querySelector('#target1'); } 22 function target2() { return document.querySelector('#target2'); } 23 function spinner() { return document.querySelector('#spinner'); } 24 25 function firstFrame() { 26 target1().animate([{transform: 'translateX(400px)'}], {id: "target1", duration: 10000}); 27 target2().animate([{transform: 'translateX(400px)'}], {id: "target2", duration: 10000}); 28 requestAnimationFrame(secondFrame); 29 30 // Simulate some jank so that, if the above animations are started 31 // asynchronously, the next rendering opportunity is likely to start 32 // immediately after this one and without the animations having started yet. 33 jank(); 34 } 35 36 function secondFrame() { 37 // Modify the style to invalidate the starting keyframe on the first target 38 // only. 39 target1().style.transform = `translateY(-1px)`; 40 41 // The spinner is used to avoid a specific Chrome behavior (bug?). It ensures 42 // a new animation is pushed to the compositor in this frame and prevents the 43 // #target1 animation being started from the main thread in 44 // PendingAnimations::Update when `started_synchronized_on_compositor` is 45 // false. 46 spinner().animate([{transform: 'rotateZ(90deg)'}], {id: 'spinner', duration: 1000}); 47 48 requestAnimationFrame(finishTestCb); 49 } 50 51 let finishTestCb = null; 52 const finishTest = new Promise(resolve => { finishTestCb = resolve; }); 53 54 promise_test(async (t) => { 55 onload = () => requestAnimationFrame(firstFrame); 56 await finishTest; 57 58 anim1 = target1().getAnimations()[0]; 59 anim2 = target2().getAnimations()[0]; 60 61 await Promise.all([anim1.ready, anim2.ready]); 62 assert_not_equals(anim1.startTime, 0); 63 assert_equals(anim1.startTime, anim2.startTime); 64 }, "Animation invalidated before startTime is set doesn't affect startTime"); 65 </script> 66 <!-- This text is necessary in Chrome in order to trigger a first contentful 67 paint which unblocks compositor commits. --> 68 The blue boxes below should stay aligned in the x-axis. 69 <div id="target1" class="target"></div> 70 <div id="target2" class="target"></div> 71 <div id="spinner" class="target" style="background:limegreen"></div>