test_flex_interrupt.html (3402B)
1 <!doctype html> 2 <title>Test for bug 1579929</title> 3 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"> 4 <script src="/tests/SimpleTest/SimpleTest.js"></script> 5 <script src="/tests/SimpleTest/EventUtils.js"></script> 6 <style> 7 .container { 8 display: flex; 9 flex-direction: column; 10 overflow-y: scroll; 11 } 12 #outer { 13 width: 500px; 14 height: 300px; 15 } 16 </style> 17 <div class="container" id="outer"> 18 <div class="item" id="firstItem" style="width: 50px"> 19 <!--popuplated by script--> 20 </div> 21 <div class="container"> 22 <div class="container"> 23 <div class="container"> 24 <div class="container"> 25 <div class="container"> 26 <div class="item">Item</div> 27 </div> 28 </div> 29 </div> 30 </div> 31 </div> 32 </div> 33 <script> 34 SimpleTest.waitForExplicitFinish(); 35 36 // Globals/constants: 37 38 const gUtils = SpecialPowers.DOMWindowUtils; 39 40 // This needs to match/exceed nsPresContext::sInterruptChecksToSkip in order 41 // for us to actually be able to trigger the mHasPendingInterrupt=true codepath 42 // in this test. Each of these "dummy" blocks will trigger a call to 43 // nsPresContext::CheckForInterrupt, and after 200, we'll actually trigger an 44 // interrupt. 45 const gInterruptCheckThreshold = 200; 46 47 // Expected to match the inline style="width:..." for #firstItem (we slowly 48 // increment it to trigger reflows): 49 let gFirstItemWidthPX = 50; 50 51 function main() { 52 const outer = document.getElementById("outer"); 53 const firstItem = document.getElementById("firstItem"); 54 55 // Insert a bunch of elements to be sure we actually get interrupted. 56 // (See description of gInterruptCheckThreshold above) 57 for (let i = 0; i < gInterruptCheckThreshold; i++) { 58 let dummyBlock = document.createElement("div"); 59 dummyBlock.innerText = "dummy"; 60 firstItem.appendChild(dummyBlock); 61 } 62 63 // Flush any pending relayout: 64 outer.offsetHeight; 65 66 // Take control of the refresh driver 67 gUtils.advanceTimeAndRefresh(0); 68 69 // Force reflow and store the "cost" (in num-frames-reflowed) 70 const costOfNormalReflow = forceReflow(); 71 72 // Sanity-check: do that again and remeasure cost, to be sure it's stable: 73 const costOfNormalReflow2 = forceReflow(); 74 is(costOfNormalReflow, costOfNormalReflow2, 75 "Our forceReflow function is expected to reliably trigger " + 76 "the same set of frames to be reflowed. If this fails, there's a " + 77 "bug in the test, or non-determinism in layout code."); 78 79 // Now, we force the next reflow to get interrupted, and then measure the 80 // cost under those conditions: 81 gUtils.forceReflowInterrupt(); 82 const costOfInterruptedReflow = forceReflow(); 83 84 // Hopefully the interrupted one was less expensive... 85 ok(costOfInterruptedReflow <= costOfNormalReflow, 86 "num frames reflowed in interrupted reflow (" + 87 costOfInterruptedReflow + 88 ") shouldn't exceed the num frames reflowed in normal reflow (" + 89 costOfNormalReflow + ")"); 90 91 gUtils.restoreNormalRefresh(); 92 SimpleTest.finish(); 93 } 94 95 // This function dirties firstItem's width, forces a reflow, and 96 // returns the number of frames that were reflowed as a result. 97 function forceReflow() { 98 gFirstItemWidthPX++; 99 firstItem.style.width = gFirstItemWidthPX + "px"; 100 101 const origFramesReflowed = gUtils.framesReflowed; 102 gUtils.advanceTimeAndRefresh(0); 103 return gUtils.framesReflowed - origFramesReflowed; 104 } 105 106 main(); 107 </script>