tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

helper_bug1695598.html (4572B)


      1 <html>
      2 <head>
      3  <title>Test for bug 1695598</title>
      4  <script src="/tests/SimpleTest/EventUtils.js"></script>
      5  <script src="/tests/SimpleTest/paint_listener.js"></script>
      6  <script type="application/javascript" src="apz_test_utils.js"></script>
      7  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
      8  <script type="text/javascript">
      9    let scrollEvents = 100;
     10    let i = 0;
     11 
     12    // Scroll points
     13    let numscrolls = 0;
     14    let last_numscrolls = 0;
     15    let start_scrolly = 0;
     16    let missed_events = 0;
     17    let missed_scroll_updates = 0;
     18 
     19    let utils = SpecialPowers.getDOMWindowUtils(window);
     20 
     21    let timeStamp = document.timeline.currentTime;
     22    async function sendScrollEvent() {
     23      if (i < scrollEvents) {
     24        if (timeStamp == document.timeline.currentTime) {
     25          // If we are in a rAF callback at the same time stamp we've already
     26          // sent a key event, skip it, otherwise we will not get the
     27          // corresponding scroll event for the key event since it will be
     28          // coalesced into a single scroll event.
     29          window.requestAnimationFrame(sendScrollEvent);
     30          return;
     31        }
     32        timeStamp = document.timeline.currentTime;
     33        // Sent a key event in a setTimeout callback so that it will be
     34        // processed in between nsRefreshDriver::Tick calls, thus the async
     35        // scroll triggered by the key event is going to be processed on the
     36        // main-thread before RepaintRequests are processed inside
     37        // nsRefreshDriver::Tick, which results there's an async scroll when
     38        // RepaintRequests are processed.
     39        setTimeout(async () => {
     40          window.synthesizeKey("KEY_ArrowDown");
     41          i++;
     42          // "apz-repaints-flush" is notified in an early runner of
     43          // nsRefreshDriver, which means it will be delivered inside
     44          // a nsRefreshDriver::Tick call before rAF callbacks.
     45          await promiseOnlyApzControllerFlushedWithoutSetTimeout();
     46 
     47          // Wait an animationiteration event since animation events are fired
     48          // before rAF callbacks and after scroll events so that it's a good
     49          // place to tell whether the expected scroll event got fired or not.
     50          await promiseOneEvent(document.getElementById("animation"),
     51                                "animationiteration", null);
     52          if (numscrolls == last_numscrolls) {
     53            missed_events++;
     54          }
     55          if (window.scrollY <= start_scrolly) {
     56            missed_scroll_updates++;
     57          }
     58          last_numscrolls = numscrolls;
     59          start_scrolly = window.scrollY;
     60          window.requestAnimationFrame(sendScrollEvent);
     61        }, 0);
     62      } else {
     63        // There's a race condition even if we got an "apz-repaints-flush"
     64        // notification but any scroll event isn't fired and scroll position
     65        // isn't updated since the notification was corresponding to a layers
     66        // update triggered by the key event above, which means there was no
     67        // repaint request corresponding to APZ animation sample in the time
     68        // frame. We allow the case here in the half of key events.
     69        ok(missed_events < scrollEvents / 2, `missed event firing ${missed_events} times`);
     70        ok(missed_scroll_updates < scrollEvents / 2, `missed scroll update ${missed_scroll_updates} times`);
     71        endTest();
     72      }
     73    }
     74 
     75    async function endTest() {
     76      document.removeEventListener("scroll", gotScroll);
     77      subtestDone();
     78    }
     79 
     80    function gotScroll() {
     81      numscrolls++;
     82    }
     83 
     84    function startTest() {
     85      document.addEventListener("scroll", gotScroll);
     86      window.requestAnimationFrame(sendScrollEvent);
     87    }
     88 
     89    if (!isApzEnabled()) {
     90      ok(true, "APZ not enabled, skipping test");
     91      subtestDone();
     92    }
     93 
     94    waitUntilApzStable()
     95    .then(forceLayerTreeToCompositor)
     96    .then(startTest);
     97  </script>
     98  <style>
     99  #content {
    100    height: 10000vh;
    101    background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
    102  }
    103  @keyframes anim {
    104    from { opacity: 0; }; /* To avoid churning this scroll test */
    105    to { opacity: 0; };
    106  }
    107  #animation {
    108    position: absolute;
    109    width: 100px;
    110    height: 100px;
    111    visibility: hidden; /* for skipping restyles on the main-thread */
    112    animation-name: anim;
    113    animation-iteration-count: infinite;
    114    animation-duration: 1ms; /* to get an animationiteration event in each tick */
    115  }
    116  </style>
    117 </head>
    118 <body>
    119  <div id="animation"></div>
    120  <div id="content">
    121  </div>
    122 </body>
    123 </html>