tor-browser

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

eventloop.html (7431B)


      1 <!doctype html>
      2 <title>ResizeObserver notification event loop tests</title>
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="./resources/resizeTestHelper.js"></script>
      6 <div id="log"></div>
      7 <script>
      8 'use strict';
      9 
     10 // allow uncaught exception because ResizeObserver posts exceptions
     11 // to window error handler when limit is exceeded.
     12 // This codepath is tested in this file.
     13 
     14 setup({allow_uncaught_exception: true});
     15 
     16 function template() {
     17  let helper = new ResizeTestHelper(
     18    "test0: title",
     19  [
     20    {
     21      setup: observer => {
     22      },
     23      notify: (entries, observer) => {
     24        return true;  // Delay next step
     25      }
     26    }
     27  ]);
     28  return helper.start();
     29 }
     30 
     31 var onErrorCalled = false;
     32 
     33 window.onerror = err => {
     34  onErrorCalled = true;
     35 }
     36 
     37 function test0() {
     38  let t1 = createAndAppendElement("div");
     39  let t2 = createAndAppendElement("div", t1);
     40  let t3 = createAndAppendElement("div", t2);
     41 
     42  let divs = [t1, t2, t3];
     43  let rAF = 0;
     44  let helper = new ResizeTestHelper(
     45    "test0: multiple notifications inside same event loop",
     46  [
     47    {
     48      setup: observer => {
     49        onErrorCalled = false;
     50        observer.observe(t1);
     51        observer.observe(t2);
     52        observer.observe(t3);
     53      },
     54      notify: (entries, observer) => {
     55        assert_equals(entries.length, 3, "3 notifications");
     56      }
     57    },
     58    {
     59      setup: observer => {
     60        helper.startCountingRaf();
     61        divs.forEach( el => { el.style.width = "101px";});
     62      },
     63      notify: (entries, observer) => {
     64        // t1 is not delivered
     65        assert_equals(entries.length, 2, "2 notifications");
     66        assert_equals(helper.rafCount, 0, "still in same loop");
     67      }
     68    },
     69    {
     70      setup: observer => {
     71        divs.forEach( el => { el.style.width = "102px";});
     72      },
     73      notify: (entries, observer) => {
     74        assert_equals(entries.length, 1, "1 notifications");
     75        assert_equals(helper.rafCount, 0, "same loop");
     76      }
     77    },
     78    { // t1 and t2 get notified
     79      setup: observer => {
     80      },
     81      notify: (entries, observer) => {
     82        assert_equals(entries.length, 2, "2 notifications");
     83        assert_equals(helper.rafCount, 1, "new loop");
     84        assert_equals(onErrorCalled, true, "error was fired");
     85        observer.disconnect();
     86      }
     87    }
     88  ]);
     89 
     90  return new Promise((resolve, reject) => {
     91    // This test uses requestAnimationFrame() to check the count of event loop,
     92    // but on some browsers, the FrameRequestCallback may be throttled (i.e.
     93    // simply fired after some extra time) in cases where this test is running
     94    // in an iframe that hasn't yet been painted (i.e. we're not visible).
     95    // This may result in some intermittent failures if this test didn't get a
     96    // first paint (and hence may not have started firing FrameRequestCallbacks)
     97    // by the time the test starts expecting helper.rafCount to have changed.
     98    //
     99    // Therefore, we don't start the test logic until body.onload has fired.
    100    // This increases the likelihood that this testcase will have gotten a
    101    // chance to paint when we start invoking requestAnimationFrame, and that
    102    // its rAF callbacks will fire when the test logic expects them to.
    103    document.body.onload = () => resolve();
    104  }).then(() => {
    105    return helper.start(() => t1.remove());
    106  });
    107 }
    108 
    109 function test1() {
    110  let t1 = createAndAppendElement("div");
    111  t1.style.width = '100px';
    112  let t2 = createAndAppendElement("div", t1);
    113  let t3 = createAndAppendElement("div", t2);
    114  let shadow = t3.attachShadow({ mode: "open" });
    115  let t4 = createAndAppendElement("div", shadow);
    116  let t5 = createAndAppendElement("div", t4);
    117 
    118  let resizers = [t1, t2, t3, t4, t5];
    119 
    120  // Testing depths of shadow roots
    121  // DOM: t1 <- t2 <- t3 <-shadow- t4 <- t5
    122  let helper = new ResizeTestHelper(
    123    "test1: depths of shadow roots",
    124  [
    125    {
    126      setup: observer => {
    127        onErrorCalled = false;
    128        resizers.forEach( el => observer.observe(el) );
    129      },
    130      notify: (entries, observer) => {
    131        assert_equals(entries.length, 5, "all entries resized");
    132      }
    133    },
    134    {
    135      setup: observer => {
    136        resizers.forEach( el => el.style.width = "111px" );
    137      },
    138      notify: (entries, observer) => {
    139        assert_equals(entries.length, 4, "depth limited");
    140      }
    141    },
    142    {
    143      setup: observer => {
    144        resizers.forEach( el => el.style.width = "112px" );
    145      },
    146      notify: (entries, observer) => {
    147        assert_equals(entries.length, 3, "depth limited");
    148      }
    149    },
    150    {
    151      setup: observer => {
    152        resizers.forEach( el => el.style.width = "113px" );
    153      },
    154      notify: (entries, observer) => {
    155        assert_equals(entries.length, 2, "depth limited");
    156      }
    157    },
    158    {
    159      setup: observer => {
    160        resizers.forEach( el => el.style.width = "114px" );
    161      },
    162      notify: (entries, observer) => {
    163        assert_equals(entries.length, 1, "depth limited");
    164      }
    165    },
    166    {
    167      setup: observer => {
    168      },
    169      notify: (entries, observer) => {
    170        assert_equals(entries.length, 4, "limit notifications");
    171        assert_equals(onErrorCalled, true, "breached limit");
    172        observer.disconnect();
    173      }
    174    },
    175  ]);
    176  return helper.start(() => t1.remove());
    177 }
    178 
    179 function test2() {
    180  // <div id="container">
    181  //   <div id="a1" style="width:100px;height:100px">
    182  //     <div id="a2" style="width:100px;height:100px"></div>
    183  //   </div>
    184  //   <div id="b1" style="width:100px;height:100px">
    185  //     <div id="b2" style="width:100px;height:100px"></div>
    186  //   </div>
    187  // </div>
    188  let container = createAndAppendElement("div");
    189  let a1 = createAndAppendElement("div", container);
    190  let a2 = createAndAppendElement("div", a1);
    191  let b1 = createAndAppendElement("div", container);
    192  let b2 = createAndAppendElement("div", b1);
    193  let targets = [a1, a2, b1, b2];
    194 
    195  let helper = new ResizeTestHelper(
    196    "test2: move target in dom while inside event loop",
    197  [
    198    {
    199      setup: observer => {
    200        for (let t of targets)
    201          observer.observe(t);
    202      },
    203      notify: (entries, observer) => {
    204        return true;  // delay next observation
    205      }
    206    },
    207    { // resize them all
    208      setup: observer => {
    209        for (let t of targets)
    210          t.style.width = "110px";
    211      },
    212      notify: (entries, observer) => {
    213        assert_equals(entries.length, targets.length, "all targets observed");
    214      }
    215    },
    216    { // resize all, move dom upwards
    217      setup: observer => {
    218        for (let t of targets)
    219          t.style.width = "130px";
    220        container.appendChild(b2);
    221      },
    222      notify: (entries, observer) => {
    223        assert_equals(entries.length, 1, "b2 moved upwards");
    224        assert_equals(entries[0].target, a2);
    225      }
    226    },
    227    { // resize all, move dom downwards
    228      setup: observer => {
    229        for (let t of targets)
    230          t.style.width = "130px";
    231        a2.appendChild(b2);
    232      },
    233      notify: (entries, observer) => {
    234        assert_equals(entries.length, 1, "b2 moved downwards");
    235        assert_equals(entries[0].target, b2);
    236      }
    237    },
    238  ]);
    239  return helper.start(() => container.remove());
    240 }
    241 
    242 let guard;
    243 test(_ => {
    244  assert_own_property(window, "ResizeObserver");
    245  guard = async_test('guard');
    246 }, "ResizeObserver implemented")
    247 
    248 test0()
    249  .then(() => test1())
    250  .then(() => test2())
    251  .then(() => guard.done());
    252 
    253 </script>