Bug 1517860 [wpt PR 14721] - WebKit export of https://bugs.webkit.org/show_bug.cgi?id=183586, a=testonly
authorDarshan Kadu <darsh7807@gmail.com>
Thu, 31 Jan 2019 15:44:36 +0000
changeset 456851 0e5f3ce027d62f9ab26d6665361e5adf57cd8ae3
parent 456850 1dff2d61900ff60212ba453d0ec6353c1a94b111
child 456852 2509717eb74258c2f2e9b0b105dd1d53543b369b
push id111705
push userjames@hoppipolla.co.uk
push dateTue, 05 Feb 2019 18:07:20 +0000
treeherdermozilla-inbound@9592b19c9b09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1517860, 14721, 183586
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1517860 [wpt PR 14721] - WebKit export of https://bugs.webkit.org/show_bug.cgi?id=183586, a=testonly Automatic update from web-platform-tests WebKit export of https://bugs.webkit.org/show_bug.cgi?id=183586 (#14721) -- wpt-commits: 1d3a454b4af3f3d70206b53a6dce49ae0ddcc7a9 wpt-pr: 14721
testing/web-platform/tests/custom-elements/enqueue-custom-element-callback-reactions-inside-another-callback.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/enqueue-custom-element-callback-reactions-inside-another-callback.html
@@ -0,0 +1,223 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: must enqueue an element on the appropriate element queue after checking callback is null and the attribute name</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="To enqueue a custom element callback reaction, the callback must be checked of being null and whether the attribute name is observed or not">
+<link rel="help" content="https://html.spec.whatwg.org/multipage/custom-elements.html#enqueue-a-custom-element-callback-reaction">
+<link rel="help" content="https://github.com/w3c/webcomponents/issues/760">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/custom-elements-helpers.js"></script>
+</head>
+<body>
+<script>
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            const child = this.firstChild;
+            child.remove();
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        connectedCallback() { logs.push('connected'); }
+        disconnectedCallback() { logs.push('disconnected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'connected', 'disconnected', 'end']);
+}, 'Disconnecting an element with disconnectedCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the removal completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            const child = this.firstChild;
+            child.remove();
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        connectedCallback() { logs.push('connected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'end', 'connected']);
+}, 'Disconnecting an element without disconnectedCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the removal completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        disconnectedCallback()
+        {
+            logs.push('begin');
+            contentDocument.body.appendChild(this.firstChild);
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        connectedCallback() { logs.push('connected'); }
+        disconnectedCallback() { logs.push('disconnected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    parent.remove();
+    assert_array_equals(logs, ['connected', 'begin', 'disconnected', 'connected', 'end']);
+}, 'Connecting a element with connectedCallback while it has a disconnectedCallback in its custom element reaction queue must result in disconnectedCallback getting invoked before the insertion completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        disconnectedCallback()
+        {
+            logs.push('begin');
+            contentDocument.body.appendChild(this.firstChild);
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        disconnectedCallback() { logs.push('disconnected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    parent.remove();
+    assert_array_equals(logs, ['begin', 'end', 'disconnected']);
+}, 'Connecting an element without connectedCallback while it has a disconnectedCallback in its custom element reaction queue must not result in disconnectedCallback getting invoked before the insertion completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            document.adoptNode(this.firstChild);
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        adoptedCallback() { logs.push('adopted'); }
+        connectedCallback() { logs.push('connected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'connected', 'adopted', 'end']);
+}, 'Adopting an element with adoptingCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the adoption completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            document.adoptNode(this.firstChild);
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        connectedCallback() { logs.push('connected'); }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'end', 'connected']);
+}, 'Adopting an element without adoptingCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the adoption completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            this.firstChild.setAttribute('title', 'foo');
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        attributeChangedCallback() { logs.push('attributeChanged'); }
+        connectedCallback() { logs.push('connected'); }
+        static get observedAttributes() { return ['title']; }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'connected', 'attributeChanged', 'end']);
+}, 'Setting an observed attribute on an element with attributeChangedCallback while it has a connectedCallback in its custom element reaction queue must result in connectedCallback getting invoked before the attribute change completes');
+
+test_with_window((contentWindow, contentDocument) => {
+    class ParentElement extends contentWindow.HTMLElement {
+        connectedCallback()
+        {
+            logs.push('begin');
+            this.firstChild.setAttribute('lang', 'en');
+            logs.push('end');
+        }
+    }
+    contentWindow.customElements.define('parent-element', ParentElement);
+
+    const logs = [];
+    class ChildElement extends contentWindow.HTMLElement {
+        attributeChangedCallback() { logs.push('attributeChanged'); }
+        connectedCallback() { logs.push('connected'); }
+        static get observedAttributes() { return ['title']; }
+    }
+    contentWindow.customElements.define('child-element', ChildElement);
+
+    const parent = new ParentElement;
+    const child = new ChildElement;
+    parent.appendChild(child);
+    contentDocument.body.appendChild(parent);
+    assert_array_equals(logs, ['begin', 'end', 'connected']);
+}, 'Setting an observed attribute on an element with attributeChangedCallback while it has a connectedCallback in its custom element reaction queue must not result in connectedCallback getting invoked before the attribute change completes');
+
+</script>
+</body>
+</html>