224 lines
9.3 KiB
HTML
224 lines
9.3 KiB
HTML
<!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>
|