-
Notifications
You must be signed in to change notification settings - Fork 318
Description
What is the issue with the DOM Standard?
Calling registry.initialize
should provoke custom elements to upgrade. Currently, it does not do so and this can lead to a custom element being in a confusing hard to reason about state.
The fact that custom elements can be in multiple states (e.g. defined or not, upgraded or not) is an inherent complexity, especially when compared to platform elements. It is never desirable for an element that has a valid definition to be in an un-upgraded state. To avoid this, developers must always remember to call registry.upgrade
or the tree is left in a confusing state after calling registry.initialize
. Consider this simple case:
<x-host id="host">
<template shadowrootmode="open" shadowrootcustomelementregistry>
<x-child id="child"></x-child>
</template>
</x-host>
const registry = new CustomElementRegistry();
registry.define('x-child', XChildElement);
// child is *not* upgraded by initialize()
registry.initialize(host.shadowRoot);
console.assert(child.customElementRegistry === registry) // true
console.assert(child.customElementRegistry.get(child.localName) !== undefined) // true
console.assert(child.isConnected === true) // true
console.assert(child.matches(':defined')) // false
// child is upgraded by upgrade()
registry.upgrade(host.shadowRoot);
// *or* or child is upgraded by connection...
child.parentNode.append(child)
console.assert(child.matches(':defined')) // true
The confusion stems from the fact that if an element has a valid definition and is connected, before the introduction of scoped registries, a developer could expect it would be defined. Now, this is not the case, and the fact that subsequently re-connecting the element can cause it to become defined is behavior that is hard to reason about without full knowledge of the lifecycle of the element.