Revision 85f9d70519e5259f01e8653a4916134227e0f178 authored by Adam Rice on 24 April 2018, 09:55:23 UTC, committed by GitHub on 24 April 2018, 09:55:23 UTC
ReadableStream, WritableStream and TransformStream look up and validate
properties on their arguments. Add tests to verify that these lookups
and validations happen in the order specified by the standard.

https://github.com/whatwg/streams/pull/922 adjusts some of the ordering
of these operations. These tests correspond to that change.

A new utility file streams/resources/constructor-ordering.js contains
functions to construct objects which track property lookups and
validations and can cause them to fail.

For each constructor the constructor.js file contains a list of the
expected operations in order, and a test case to verify it.

A test in streams/transform-streams/properties.js already detected the
ordering of property accesses by the TransformStream constructor.
writableStrategy is now accessed before readableStrategy to match the
order of the constructor arguments, and so the expectations of this test
are changed to match.
1 parent 7a199e9
Raw File
microtasks-and-constructors.html
<!DOCTYPE html>
<title>Custom elements: performing a microtask checkpoint after construction</title>
<meta name="author" title="Domenic Denicola" href="mailto:d@domenic.me">
<link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element">
<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
<link rel="help" href="https://github.com/whatwg/html/issues/2381">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<div id="log"></div>

<x-upgrade></x-upgrade>

<script>
"use strict";
setup({ allow_uncaught_exception: true });

window.doMicrotasks = (callback1, callback2 = callback1) => {
  Promise.resolve().then(callback1);

  const mo = new MutationObserver(callback2);
  const node = document.createTextNode("");
  mo.observe(node, { characterData: true });
  node.data = "x";
};

window.logMicrotasks = events => {
  window.doMicrotasks(() => events.push("promise microtask"),
                      () => events.push("MutationObserver microtask"));
};

window.flushAsyncEvents = () => {
  return new Promise(resolve => step_timeout(resolve, 0));
};

window.x0Events = [];
customElements.define("x-0", class extends HTMLElement {
  constructor() {
    super();
    logMicrotasks(window.x0Events);
  }
});
</script>

<x-0></x-0>

<script>
"use strict";

test(() => {
  assert_array_equals(window.x0Events, ["promise microtask", "MutationObserver microtask"]);
}, "Microtasks evaluate immediately when the stack is empty inside the parser");

customElements.define("x-bad", class extends HTMLElement {
  constructor() {
    super();
    doMicrotasks(() => this.setAttribute("attribute", "value"));
  }
});
</script>

<x-bad></x-bad>

<script>
"use strict";

test(() => {
  const xBad = document.querySelector("x-bad");
  assert_false(xBad.hasAttribute("attribute"), "The attribute must not be present");
  assert_true(xBad instanceof HTMLUnknownElement, "The element must be a HTMLUnknownElement");
}, "Microtasks evaluate immediately when the stack is empty inside the parser, causing the " +
   "checks on no attributes to fail")

promise_test(() => {
  const events = [];
  customElements.define("x-1", class extends HTMLElement {
    constructor() {
      super();
      logMicrotasks(events);
    }
  });

  document.createElement("x-1");
  events.push("after");

  return flushAsyncEvents().then(() => {
    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
  });
}, "Microtasks evaluate afterward when the stack is not empty using createElement()");

promise_test(() => {
  const events = [];
  class X2 extends HTMLElement {
    constructor() {
      super();
      logMicrotasks(events);
    }
  }
  customElements.define("x-2", X2);

  new X2();
  events.push("after");

  return flushAsyncEvents().then(() => {
    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
  });
}, "Microtasks evaluate afterward when the stack is not empty using the constructor");

promise_test(() => {
  const events = [];
  customElements.define("x-upgrade", class extends HTMLElement {
    constructor() {
      super();
      logMicrotasks(events);
    }
  });
  events.push("after");

  return flushAsyncEvents().then(() => {
    assert_array_equals(events, ["after", "promise microtask", "MutationObserver microtask"]);
  });
}, "Microtasks evaluate afterward when the stack is not empty due to upgrades");
</script>
back to top