tor-browser

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

test_media_query_list.html (12230B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=542058
      5 -->
      6 <head>
      7  <title>Test for MediaQueryList (Bug 542058)</title>
      8  <script src="/tests/SimpleTest/SimpleTest.js"></script>
      9  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     10 </head>
     11 <body onload="run()">
     12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=542058">Mozilla Bug 542058</a>
     13 <iframe id="subdoc" src="about:blank"></iframe>
     14 <div id="content" style="display:none"></div>
     15 <pre id="test">
     16 <script type="application/javascript">
     17 
     18 /** Test for MediaQueryList (Bug 542058) */
     19 
     20 SimpleTest.waitForExplicitFinish();
     21 
     22 function tick() {
     23  // MediaQueryList events are guaranteed to run before requestAnimationFrame
     24  // per spec.
     25  return new Promise(r => requestAnimationFrame(r));
     26 }
     27 
     28 async function run() {
     29  var iframe = document.getElementById("subdoc");
     30  var subdoc = iframe.contentDocument;
     31  var subwin = iframe.contentWindow;
     32  var subroot = subdoc.documentElement;
     33 
     34  var content_div = document.getElementById("content");
     35  content_div.style.font = "initial";
     36  var em_size =
     37    getComputedStyle(content_div).fontSize.match(/^(\d+)px$/)[1];
     38 
     39  var w = Math.floor(em_size * 9.3);
     40  var h = Math.floor(em_size * 4.2);
     41  iframe.style.width = w + "px";
     42  iframe.style.height = h + "px";
     43  subroot.offsetWidth; // flush layout
     44  await tick();
     45 
     46  function setup_mql(str) {
     47    var obj = {
     48      str: str,
     49      mql: subwin.matchMedia(str),
     50      notifyCount: 0,
     51      listener: function(event) {
     52                  ok(event instanceof subwin.MediaQueryListEvent,
     53                     "correct argument to listener: " + obj.str);
     54                  is(event.media, obj.mql.media,
     55                     "correct media in the event: " + obj.str);
     56                  is(event.target, obj.mql,
     57                     "correct target in the event: " + obj.str);
     58                  ++obj.notifyCount;
     59                  // Test the last match result only on odd
     60                  // notifications.
     61                  if (obj.notifyCount & 1) {
     62                    obj.lastOddMatchResult = event.target.matches;
     63                  }
     64                }
     65    }
     66    obj.mql.addListener(obj.listener);
     67    return obj;
     68  }
     69 
     70  function finish_mql(obj) {
     71    obj.mql.removeListener(obj.listener);
     72  }
     73 
     74  var w_exact_w = setup_mql("(width: " + w + "px)");
     75  var w_min_9em = setup_mql("(min-width : 9em)");
     76  var w_min_10em = setup_mql("(  min-width: 10em ) ");
     77  var w_max_9em = setup_mql("(max-width: 9em)");
     78  var w_max_10em = setup_mql("(max-width: 10em)");
     79 
     80  is(w_exact_w.mql.media, "(width: " + w + "px)", "serialization");
     81  is(w_min_9em.mql.media, "(min-width: 9em)", "serialization");
     82  is(w_min_10em.mql.media, "(min-width: 10em)", "serialization");
     83  is(w_max_9em.mql.media, "(max-width: 9em)", "serialization");
     84  is(w_max_10em.mql.media, "(max-width: 10em)", "serialization");
     85 
     86  function check_match(obj, expected, desc) {
     87    is(obj.mql.matches, expected,
     88       obj.str + " media query list .matches " + desc);
     89    if (obj.notifyCount & 1) { // odd notifications only
     90      is(obj.lastOddMatchResult, expected,
     91       obj.str + " media query list last notify result " + desc);
     92    }
     93  }
     94  function check_notify(obj, expected, desc) {
     95    is(obj.notifyCount, expected,
     96       obj.str + " media query list .notify count " + desc);
     97  }
     98  check_match(w_exact_w, true, "initially");
     99  check_notify(w_exact_w, 0, "initially");
    100  check_match(w_min_9em, true, "initially");
    101  check_notify(w_min_9em, 0, "initially");
    102  check_match(w_min_10em, false, "initially");
    103  check_notify(w_min_10em, 0, "initially");
    104  check_match(w_max_9em, false, "initially");
    105  check_notify(w_max_9em, 0, "initially");
    106  check_match(w_max_10em, true, "initially");
    107  check_notify(w_max_10em, 0, "initially");
    108 
    109  var w2 = Math.floor(em_size * 10.3);
    110  iframe.style.width = w2 + "px";
    111  subroot.offsetWidth; // flush layout
    112  await tick();
    113 
    114  check_match(w_exact_w, false, "after width increase to around 10.3em");
    115  check_notify(w_exact_w, 1, "after width increase to around 10.3em");
    116  check_match(w_min_9em, true, "after width increase to around 10.3em");
    117  check_notify(w_min_9em, 0, "after width increase to around 10.3em");
    118  check_match(w_min_10em, true, "after width increase to around 10.3em");
    119  check_notify(w_min_10em, 1, "after width increase to around 10.3em");
    120  check_match(w_max_9em, false, "after width increase to around 10.3em");
    121  check_notify(w_max_9em, 0, "after width increase to around 10.3em");
    122  check_match(w_max_10em, false, "after width increase to around 10.3em");
    123  check_notify(w_max_10em, 1, "after width increase to around 10.3em");
    124 
    125  var w3 = w * 2;
    126  iframe.style.width = w3 + "px";
    127  subroot.offsetWidth; // flush layout
    128  await tick();
    129 
    130  check_match(w_exact_w, false, "after width double from original");
    131  check_notify(w_exact_w, 1, "after width double from original");
    132  check_match(w_min_9em, true, "after width double from original");
    133  check_notify(w_min_9em, 0, "after width double from original");
    134  check_match(w_min_10em, true, "after width double from original");
    135  check_notify(w_min_10em, 1, "after width double from original");
    136  check_match(w_max_9em, false, "after width double from original");
    137  check_notify(w_max_9em, 0, "after width double from original");
    138  check_match(w_max_10em, false, "after width double from original");
    139  check_notify(w_max_10em, 1, "after width double from original");
    140 
    141  SpecialPowers.setFullZoom(subwin, 2.0);
    142  subroot.offsetWidth; // flush layout
    143  await tick();
    144 
    145  check_match(w_exact_w, true, "after zoom");
    146  check_notify(w_exact_w, 2, "after zoom");
    147  check_match(w_min_9em, true, "after zoom");
    148  check_notify(w_min_9em, 0, "after zoom");
    149  check_match(w_min_10em, false, "after zoom");
    150  check_notify(w_min_10em, 2, "after zoom");
    151  check_match(w_max_9em, false, "after zoom");
    152  check_notify(w_max_9em, 0, "after zoom");
    153  check_match(w_max_10em, true, "after zoom");
    154  check_notify(w_max_10em, 2, "after zoom");
    155 
    156  SpecialPowers.setFullZoom(subwin, 1.0);
    157 
    158  await tick();
    159 
    160  finish_mql(w_exact_w);
    161  finish_mql(w_min_9em);
    162  finish_mql(w_min_10em);
    163  finish_mql(w_max_9em);
    164  finish_mql(w_max_10em);
    165 
    166  // Additional tests of listener mutation.
    167  {
    168    let received = [];
    169    let received_mql = [];
    170    function listener1(event) {
    171      received.push(1);
    172      received_mql.push(event.target);
    173    }
    174    function listener2(event) {
    175      received.push(2);
    176      received_mql.push(event.target);
    177    }
    178 
    179    iframe.style.width = "200px";
    180    subroot.offsetWidth; // flush layout
    181    await tick();
    182 
    183    let mql = subwin.matchMedia("(min-width: 150px)");
    184    mql.addListener(listener1);
    185    mql.addListener(listener1);
    186    mql.addListener(listener2);
    187    is(JSON.stringify(received), "[]", "listeners before notification");
    188 
    189    iframe.style.width = "100px";
    190    subroot.offsetWidth; // flush layout
    191    await tick();
    192 
    193    is(JSON.stringify(received), "[1,2]", "duplicate listeners removed");
    194    received = [];
    195    mql.removeListener(listener1);
    196 
    197    iframe.style.width = "200px";
    198    subroot.offsetWidth; // flush layout
    199    await tick();
    200 
    201    is(JSON.stringify(received), "[2]", "listener removal");
    202    received = [];
    203    mql.addListener(listener1);
    204 
    205    iframe.style.width = "100px";
    206    subroot.offsetWidth; // flush layout
    207    await tick();
    208 
    209    is(JSON.stringify(received), "[2,1]", "listeners notified in order");
    210    received = [];
    211    mql.addListener(listener2);
    212 
    213    iframe.style.width = "200px";
    214    subroot.offsetWidth; // flush layout
    215    await tick();
    216 
    217    is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
    218    received = [];
    219    mql.addListener(listener1);
    220 
    221    iframe.style.width = "100px";
    222    subroot.offsetWidth; // flush layout
    223    await tick();
    224 
    225    is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
    226    mql.removeListener(listener2);
    227    received = [];
    228    received_mql = [];
    229 
    230    var mql2 = subwin.matchMedia("(min-width: 160px)");
    231    mql2.addListener(listener1);
    232    mql.addListener(listener2);
    233 
    234    iframe.style.width = "200px";
    235    subroot.offsetWidth; // flush layout
    236    await tick();
    237 
    238    // mql (1, 2), mql2 (1)
    239    is(JSON.stringify(received), "[1,2,1]",
    240       "notification of lists in order created");
    241    is(received_mql[0], mql,
    242       "notification of lists in order created");
    243    is(received_mql[1], mql,
    244       "notification of lists in order created");
    245    is(received_mql[2], mql2,
    246       "notification of lists in order created");
    247    received = [];
    248    received_mql = [];
    249 
    250    function removing_listener(event) {
    251      received.push(3);
    252      received_mql.push(event.target);
    253      event.target.removeListener(listener2);
    254      mql2.removeListener(listener1);
    255    }
    256 
    257    mql.addListener(removing_listener);
    258    mql.removeListener(listener2);
    259    mql.addListener(listener2); // after removing_listener (3)
    260 
    261    iframe.style.width = "100px";
    262    subroot.offsetWidth; // flush layout
    263    await tick();
    264 
    265    // mql(1, 3)
    266    is(JSON.stringify(received), "[1,3]",
    267       "listeners still notified after removed if change was before");
    268    is(received_mql[0], mql,
    269       "notification order (removal tests)");
    270    is(received_mql[1], mql,
    271       "notification order (removal tests)");
    272    received = [];
    273    received_mql = [];
    274 
    275    iframe.style.width = "200px";
    276    subroot.offsetWidth; // flush layout
    277    await tick();
    278 
    279    // mql(1, 3)
    280    is(JSON.stringify(received), "[1,3]",
    281       "listeners not notified for changes after their removal");
    282    is(received_mql[0], mql,
    283       "notification order (removal tests)");
    284    is(received_mql[1], mql,
    285       "notification order (removal tests)");
    286  }
    287 
    288  /* Bug 753777: test that things work in a freshly-created iframe */
    289  {
    290    let newIframe = document.createElement("iframe");
    291    document.body.appendChild(newIframe);
    292 
    293    is(newIframe.contentWindow.matchMedia("all").matches, true,
    294       "matchMedia should work in newly-created iframe");
    295    // Passes due to initial about:blank poking layout.
    296    // See https://github.com/w3c/csswg-drafts/issues/3101, bug 1458816,
    297    // and bug 1011468.
    298    is(newIframe.contentWindow.matchMedia("(min-width: 1px)").matches, true,
    299       "(min-width: 1px) should match in newly-created iframe");
    300    is(newIframe.contentWindow.matchMedia("(max-width: 1px)").matches, false,
    301       "(max-width: 1px) should not match in newly-created iframe");
    302 
    303    document.body.removeChild(newIframe);
    304  }
    305 
    306  /* Bug 716751: listeners lost due to GC */
    307  var gc_received = [];
    308  {
    309    let received = [];
    310    let listener1 = function(event) {
    311      gc_received.push(1);
    312    }
    313 
    314    iframe.style.width = "200px";
    315    subroot.offsetWidth; // flush layout
    316    await tick();
    317 
    318    let mql = subwin.matchMedia("(min-width: 150px)");
    319    mql.addListener(listener1);
    320    is(JSON.stringify(gc_received), "[]", "GC test: before notification");
    321 
    322    iframe.style.width = "100px";
    323    subroot.offsetWidth; // flush layout
    324    await tick();
    325 
    326    is(JSON.stringify(gc_received), "[1]", "GC test: after notification 1");
    327 
    328    // Because of conservative GC, we need to go back to the event loop
    329    // to GC properly.
    330    setTimeout(step2, 0);
    331  }
    332 
    333  async function step2() {
    334    SpecialPowers.DOMWindowUtils.garbageCollect();
    335 
    336    iframe.style.width = "200px";
    337    subroot.offsetWidth; // flush layout
    338    await tick();
    339 
    340    is(JSON.stringify(gc_received), "[1,1]", "GC test: after notification 2");
    341 
    342    bug1270626();
    343  }
    344 
    345  /* Bug 1270626: listeners that throw exceptions */
    346  async function bug1270626() {
    347    var throwingListener = function(event) {
    348      throw "error";
    349    }
    350 
    351    iframe.style.width = "200px";
    352    subroot.offsetWidth; // flush layout
    353    await tick();
    354 
    355    var mql = subwin.matchMedia("(min-width: 150px)");
    356    mql.addListener(throwingListener);
    357 
    358    SimpleTest.expectUncaughtException(true);
    359    is(SimpleTest.isExpectingUncaughtException(), true,
    360       "should be waiting for an uncaught exception");
    361 
    362    iframe.style.width = "100px";
    363    subroot.offsetWidth; // flush layout
    364    await tick();
    365 
    366    is(SimpleTest.isExpectingUncaughtException(), false,
    367       "should have gotten an uncaught exception");
    368 
    369    SimpleTest.finish();
    370  }
    371 }
    372 
    373 </script>
    374 </pre>
    375 </body>
    376 </html>