Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<html>
<head>
<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<div id="host">
<template shadowrootmode="open" shadowrootclonable="true" shadowrootcustomelementregistry>
<new-element></new-element>
</template>
</div>
<body>
<script>
function createConnectedShadowTree(test, customElementRegistry) {
const host = document.createElement('div');
const shadowRoot = host.attachShadow({mode: 'closed', customElementRegistry});
document.body.appendChild(host);
test.add_cleanup(() => host.remove());
return shadowRoot;
}
class GlobalSomeElement extends HTMLElement { };
customElements.define('some-element', GlobalSomeElement);
class GlobalOtherElement extends HTMLElement { };
customElements.define('other-element', GlobalOtherElement);
class WrongNewElement extends HTMLElement{ };
customElements.define('new-element', WrongNewElement);
test((test) => {
const registry = new CustomElementRegistry;
class ScopedSomeElement extends HTMLElement { };
registry.define('some-element', ScopedSomeElement);
class ScopedOtherElement extends HTMLElement { };
registry.define('other-element', ScopedOtherElement);
const someElement = document.createElement('some-element', {customElementRegistry: registry});
assert_true(someElement instanceof ScopedSomeElement);
someElement.innerHTML = '<other-element></other-element>';
assert_true(someElement.querySelector('other-element') instanceof ScopedOtherElement);
}, 'innerHTML on a disconnected element should use the scoped registry it was created with');
test((test) => {
const registry = new CustomElementRegistry;
class ScopedSomeElement extends HTMLElement { };
registry.define('some-element', ScopedSomeElement);
class ScopedOtherElement extends HTMLElement { };
registry.define('other-element', ScopedOtherElement);
const someElement = document.createElement('some-element', {customElementRegistry: registry});
assert_true(someElement instanceof ScopedSomeElement);
someElement.innerHTML = `
<other-element id="foo">
<other-element id="bar">
<div id="baz">
<other-element id="nested-ce"></other-element>
</div>
</other-element>
</other-element>
<div id="bux"></div>
<another-element></another-element>`;
assert_true(someElement.querySelector('#foo') instanceof ScopedOtherElement);
assert_true(someElement.querySelector('#bar') instanceof ScopedOtherElement);
assert_true(someElement.querySelector('#nested-ce') instanceof ScopedOtherElement);
assert_true(someElement.querySelector('#foo').customElementRegistry === registry);
assert_true(someElement.querySelector('#bar').customElementRegistry === registry);
assert_true(someElement.querySelector('#baz').customElementRegistry === registry);
assert_true(someElement.querySelector('#nested-ce').customElementRegistry === registry);
assert_true(someElement.querySelector('#bux').customElementRegistry === registry);
assert_true(someElement.querySelector('another-element').customElementRegistry === registry);
}, 'nested descendants in innerHTML on a disconnected element should use the scoped registry the element was created with');
test((test) => {
const registry = new CustomElementRegistry;
class ScopedSomeElement extends HTMLElement { };
registry.define('some-element', ScopedSomeElement);
const div = document.createElement('div', {customElementRegistry: registry});
div.innerHTML = '<span></span>';
assert_equals(div.querySelector('span').customElementRegistry, registry);
}, 'innerHTML on a disconnected element should use the scoped registry it was created with when parsing a simple HTML');
test((test) => {
const registry1 = new CustomElementRegistry;
const registry2 = new CustomElementRegistry;
class ScopedSomeElement extends HTMLElement { };
registry1.define('some-element', ScopedSomeElement);
class ScopedOtherElement1 extends HTMLElement { };
registry1.define('other-element', ScopedOtherElement1);
class ScopedOtherElement2 extends HTMLElement { };
registry2.define('other-element', ScopedOtherElement2);
const shadowRoot1 = createConnectedShadowTree(test, registry1);
const shadowRoot2 = createConnectedShadowTree(test, registry2);
const someElement = document.createElement('some-element', {customElementRegistry: registry1});
someElement.innerHTML = '<other-element></other-element>';
assert_true(someElement.querySelector('other-element') instanceof ScopedOtherElement1);
shadowRoot2.appendChild(someElement);
someElement.innerHTML = '<other-element></other-element>';
assert_true(someElement.querySelector('other-element') instanceof ScopedOtherElement1);
someElement.remove();
someElement.innerHTML = '<other-element></other-element>';
assert_true(someElement.querySelector('other-element') instanceof ScopedOtherElement1);
}, 'innerHTML on an inserted element should continue to use the scoped registry it was created with');
test((test) => {
const shadowRoot = host.cloneNode(true).shadowRoot;
const container_element = shadowRoot.lastElementChild;
assert_equals(container_element.customElementRegistry, null);
assert_false(container_element instanceof WrongNewElement);
container_element.innerHTML = '<new-element><new-element></new-element></new-element>';
const outer_element = container_element.querySelector('new-element');
const inner_element = outer_element.querySelector('new-element');
assert_equals(outer_element.customElementRegistry, null);
assert_false(outer_element instanceof WrongNewElement);
assert_equals(inner_element.customElementRegistry, null);
assert_false(inner_element instanceof WrongNewElement);
}, 'nested descendants in innerHTML should use the null registry when the container element has null registry');
test((test) => {
const shadowRoot = host.cloneNode(true).shadowRoot;
shadowRoot.firstElementChild.insertAdjacentHTML('afterend', '<new-element></new-element>');
const container_element = shadowRoot.lastElementChild;
assert_equals(container_element.customElementRegistry, null);
assert_false(container_element instanceof WrongNewElement);
}, 'insertAdjacentHTML should use the element\'s registry even when the registry is null');
</script>
</body>
</html>