test_bug1756118.html (3209B)
1 <!DOCTYPE HTML> 2 <html> 3 <!-- 4 https://bugzilla.mozilla.org/show_bug.cgi?id=1756118 5 --> 6 <head> 7 <meta charset="utf-8"> 8 <title>Test for Bug 1756118: A removed ResizeObserver shouldn't keep the refresh driver ticking</title> 9 <script src="/tests/SimpleTest/SimpleTest.js"></script> 10 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 11 </head> 12 <body onload="run()"> 13 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1756118">Mozilla Bug 1756118</a> 14 <div id="display"> 15 <div id="resizeMe"></div> 16 </div> 17 <pre id="test"> 18 <script> 19 "use strict"; 20 SimpleTest.waitForExplicitFinish(); 21 SimpleTest.requestFlakyTimeout("need to allow time to pass so that we can " + 22 "detect unwanted extra refresh driver ticks"); 23 const gUtils = SpecialPowers.getDOMWindowUtils(window); 24 25 async function addAndRemoveResizeObserver(shouldResizeTarget) { 26 // Register a resize observer: 27 let ro = new ResizeObserver(function() { info("ResizeObserver callback"); }); 28 ro.observe(resizeMe); 29 30 // double-rAF to flush pending paints: 31 await new Promise(r => requestAnimationFrame(r)); 32 await new Promise(r => requestAnimationFrame(r)); 33 34 ok(gUtils.refreshDriverHasPendingTick, 35 "Expecting refresh driver to be ticking, with ResizeObserver registered"); 36 37 // Unregister resize observer: 38 ro.unobserve(resizeMe); 39 40 // double-rAF to flush pending paints: 41 await new Promise(r => requestAnimationFrame(r)); 42 await new Promise(r => requestAnimationFrame(r)); 43 44 // ...and importantly: make one additional change to the document. 45 // This causes a refresh driver tick, which in buggy builds causes 46 // the refresh driver to keep ticking indefinitely. (In buggy builds, this 47 // bonus tick notifies our ResizeObserverController, and it never unregisters 48 // and hence keeps the refresh driver ticking from that point on.) 49 resizeMe.style.height = "100px"; 50 } 51 52 async function expectTicksToStop() { 53 let didStopTicking = false; 54 // Note: The maximum loop count here is an arbitrary large value, just to let 55 // us gracefully handle edge cases where multiple setTimeouts resolve before 56 // a pending refresh driver tick. Really, we just want to be sure the refresh 57 // driver *eventually* stops ticking, and we can do so gracefully by polling 58 // with some generous-but-finite number of checks here. 59 for (var i = 0; i < 100; i++) { 60 await new Promise(r => setTimeout(r, 8)); 61 if(!gUtils.refreshDriverHasPendingTick) { 62 didStopTicking = true; 63 break; 64 } 65 } 66 ok(didStopTicking, "refresh driver should have eventually stopped ticking"); 67 } 68 69 async function run() { 70 // By default, the refresh driver ticks on its own for some period of time 71 // after pageload. Turn that off so we don't have to wait it out: 72 await SpecialPowers.pushPrefEnv({'set': 73 [['layout.keep_ticking_after_load_ms', 0]]}); 74 75 // Start out with a double-rAF, to flush paints from pageload: 76 await new Promise(r => requestAnimationFrame(r)); 77 await new Promise(r => requestAnimationFrame(r)); 78 79 await addAndRemoveResizeObserver(true); 80 await expectTicksToStop(); 81 82 SimpleTest.finish(); 83 } 84 </script> 85 </pre> 86 </body> 87 </html>