tor-browser

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

microtasks-and-constructors.html (3514B)


      1 <!DOCTYPE html>
      2 <title>Custom elements: performing a microtask checkpoint after construction</title>
      3 <meta name="author" title="Domenic Denicola" href="mailto:d@domenic.me">
      4 <link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element">
      5 <link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
      6 <link rel="help" href="https://github.com/whatwg/html/issues/2381">
      7 <script src="/resources/testharness.js"></script>
      8 <script src="/resources/testharnessreport.js"></script>
      9 
     10 <div id="log"></div>
     11 
     12 <x-upgrade></x-upgrade>
     13 
     14 <script>
     15 "use strict";
     16 setup({ allow_uncaught_exception: true });
     17 
     18 window.doMicrotasks = (callback1, callback2 = callback1) => {
     19  Promise.resolve().then(callback1);
     20 
     21  const mo = new MutationObserver(callback2);
     22  const node = document.createTextNode("");
     23  mo.observe(node, { characterData: true });
     24  node.data = "x";
     25 };
     26 
     27 window.logMicrotasks = events => {
     28  window.doMicrotasks(() => events.push("promise microtask"),
     29                      () => events.push("MutationObserver microtask"));
     30 };
     31 
     32 window.flushAsyncEvents = () => {
     33  return new Promise(resolve => step_timeout(resolve, 0));
     34 };
     35 
     36 window.x0Events = [];
     37 customElements.define("x-0", class extends HTMLElement {
     38  constructor() {
     39    super();
     40    logMicrotasks(window.x0Events);
     41  }
     42 });
     43 </script>
     44 
     45 <x-0></x-0>
     46 
     47 <script>
     48 "use strict";
     49 
     50 test(() => {
     51  assert_array_equals(window.x0Events, ["promise microtask", "MutationObserver microtask"]);
     52 }, "Microtasks evaluate immediately when the stack is empty inside the parser");
     53 
     54 customElements.define("x-bad", class extends HTMLElement {
     55  constructor() {
     56    super();
     57    doMicrotasks(() => this.setAttribute("attribute", "value"));
     58  }
     59 });
     60 </script>
     61 
     62 <x-bad></x-bad>
     63 
     64 <script>
     65 "use strict";
     66 
     67 test(() => {
     68  const xBad = document.querySelector("x-bad");
     69  assert_false(xBad.hasAttribute("attribute"), "The attribute must not be present");
     70  assert_true(xBad instanceof HTMLUnknownElement, "The element must be a HTMLUnknownElement");
     71 }, "Microtasks evaluate immediately when the stack is empty inside the parser, causing the " +
     72   "checks on no attributes to fail")
     73 
     74 promise_test(() => {
     75  const events = [];
     76  customElements.define("x-1", class extends HTMLElement {
     77    constructor() {
     78      super();
     79      logMicrotasks(events);
     80    }
     81  });
     82 
     83  document.createElement("x-1");
     84  events.push("after");
     85 
     86  return flushAsyncEvents().then(() => {
     87    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
     88  });
     89 }, "Microtasks evaluate afterward when the stack is not empty using createElement()");
     90 
     91 promise_test(() => {
     92  const events = [];
     93  class X2 extends HTMLElement {
     94    constructor() {
     95      super();
     96      logMicrotasks(events);
     97    }
     98  }
     99  customElements.define("x-2", X2);
    100 
    101  new X2();
    102  events.push("after");
    103 
    104  return flushAsyncEvents().then(() => {
    105    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
    106  });
    107 }, "Microtasks evaluate afterward when the stack is not empty using the constructor");
    108 
    109 promise_test(() => {
    110  const events = [];
    111  customElements.define("x-upgrade", class extends HTMLElement {
    112    constructor() {
    113      super();
    114      logMicrotasks(events);
    115    }
    116  });
    117  events.push("after");
    118 
    119  return flushAsyncEvents().then(() => {
    120    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
    121  });
    122 }, "Microtasks evaluate afterward when the stack is not empty due to upgrades");
    123 </script>