helper_bug1669625.html (3311B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width; initial-scale=1.0"> 6 <title>Scrolling doesn't cause extra SchedulePaint calls</title> 7 <script src="/tests/SimpleTest/EventUtils.js"></script> 8 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 9 <script type="application/javascript" src="apz_test_utils.js"></script> 10 <script src="/tests/SimpleTest/paint_listener.js"></script> 11 <script type="application/javascript"> 12 13 async function test() { 14 if (getPlatform() == "android") { 15 return; 16 } 17 18 while (window.scrollY == 0) { 19 // the scrollframe is not yet marked as APZ-scrollable. Mark it so before 20 // continuing. 21 window.scrollTo(0, 1000); 22 await promiseApzFlushedRepaints(); 23 } 24 25 window.synthesizeKey("KEY_ArrowDown"); 26 // This is really tricky. We want to check that during the main part of 27 // scrolling after this we don't get any SchedulePaint calls. The way that we 28 // test that is to use checkAndClearDisplayListState on the document element 29 // to make sure it didn't have display list building ran for it. The 30 // synthesizeKey calls above will end up in ScrollFrameHelper::ScrollBy, 31 // which calls SchedulePaint in order to pass the scroll to the compositor to 32 // perform. That SchedulePaint will result in display list building for the 33 // document element, and that's okay, but we want to call 34 // checkAndClearDisplayListState (to clear the display list building state) 35 // right after that display list building, so that we can observe if any 36 // display list building happens after it. That way that we do that is a rAF, 37 // which runs immediately before painting, and then a setTimeout from the 38 // rAF, which should run almost immediately after painting. Then we wait for 39 // a scroll event, this scroll event is triggered by the compositor updating 40 // the main thread scroll position. And here is where we finally get to what 41 // we want to actually test. The original bug came about when the main 42 // thread, while processing the repaint request from the compositor, called 43 // SchedulePaint, and hence caused display list building. So we want to check 44 // that the refresh driver tick after the scroll event does not do any 45 // display list building. We again use a setTimeout from a rAF to run right 46 // after the paint and check that there was no display list building. 47 await new Promise(resolve => { 48 window.requestAnimationFrame(() => { 49 setTimeout(checkNoDisplayListRebuild, 0, resolve); 50 }); 51 }); 52 } 53 54 function checkNoDisplayListRebuild(resolve) { 55 var utils = window.opener.SpecialPowers.getDOMWindowUtils(window); 56 var elem = document.documentElement; 57 utils.checkAndClearDisplayListState(elem); 58 window.addEventListener("scroll", function () { 59 window.requestAnimationFrame(() => { 60 setTimeout(function() { 61 is(utils.checkAndClearDisplayListState(elem), false, "Document element didn't get display list"); 62 resolve(); 63 },0); 64 }); 65 }, {once: true}); 66 } 67 68 waitUntilApzStable() 69 .then(test) 70 .then(subtestDone, subtestFailed); 71 72 </script> 73 </head> 74 <body style="height: 5000px"> 75 <div style="height: 50px">spacer</div> 76 <button id="b" style="width: 10px; height: 10px"></button> 77 </body> 78 </html>