Description
https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Scoped-Custom-Element-Registries.md is a good proposal, but it ties the functionality too much to shadow roots. This is Ryosuke and I's proposed improvement attempting to account for feedback given in various Web Components issues on this topic: https://github.com/WICG/webcomponents/issues?q=is%3Aissue+label%3A%22scoped+custom+element+registry%22.
First, the IDL, illustrating the new members:
interface CustomElementRegistry {
constructor();
...
undefined initialize((Element or ShadowRoot) root);
};
partial interface Document {
[CEReactions, NewObject] Element createElement(DOMString localName, optional (DOMString or ElementCreationOptions) options = {});
[CEReactions, NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional (DOMString or ElementCreationOptions) options = {});
[CEReactions, NewObject] Node importNode(Node node, optional (boolean or ImportNodeOptions) options = false);
}
dictionary ElementCreationOptions {
CustomElementRegistry customElementRegistry;
}
dictionary ImportNodeOptions {
CustomElementRegistry customElementRegistry;
selfOnly = false;
}
partial interface Element {
readonly attribute CustomElementRegistry? customElementRegistry;
};
dictionary ShadowRootInit { // used by Element.prototype.attachShadow
...
CustomElementRegistry customElementRegistry;
};
partial interface DocumentOrShadowRoot {
readonly attribute CustomElementRegistry? customElementRegistry;
};
partial interface HTMLTemplateElement {
[CEReactions] attribute DOMString shadowRootCustomElementRegistry;
}
Here’s a summary of how the proposal evolved:
CustomElementRegistry
still gains a constructor.ShadowRoot
still supports aCustomElementRegistry
, exposed through acustomElementRegistry
getter.- It seems important for the shadow root to be able to be independent from its host in terms of registries.
- Interaction with declarative shadow DOM WICG/webcomponents#914 has a proposal for declarative shadow trees to be able to disable inheriting from the global registry. This adopts that with the
shadowrootcustomelements
attribute, which is reflected as a string for forward compatibility. ElementInternals
gainsinitializeShadowRoot()
CustomElementRegistry
gainsinitialize()
so a declarative shadow root (or any element) can have itsCustomElementRegistry
set (when it’s null).- The
attachShadow()
member is now calledcustomElementRegistry
for consistency.
Element
should support an associatedCustomElementRegistry
, exposed through acustomElementRegistry
getter. This impacts elements created throughinnerHTML
and future such methods, such assetHTMLUnsafe()
. This will allow using non-globalCustomElementRegistry
outside of shadow roots.setHTMLUnsafe()
in the future could maybe also set its ownCustomElementRegistry
. Given the ergonomics of that it makes sense to expose it directly onElement
as well.
document.createElement()
,document.createElementNS()
, anddocument.importNode()
are updated to account for registries.
I’ll create specification PRs as well to allow for review of the processing model changes. We believe this resolves the remaining issues with the latest iteration of the initial proposal.
I'd like to briefly go over this in the December 19 WHATNOT meeting and will also be available then to answer any questions. Marking agenda+ therefore.
cc @rniwa @justinfagnani @whatwg/components
Minor issue tracker:
- Instead of inventing a new
createElement()
we should attempt to reuse the existing one ondocument
(with a newcustomElements
member) as we're not quite ready to reinvent how to best do element-creation. - Should
initializeSubtree()
perform upgrades in the connected case? (If yes, it should probably also update the scoped document set.) (No.) - Is there a better name for
initializeSubtree()
? (Also consider the names already exposed on this object.) Just initialize. -
importNode()
is better after all as we need a document anyway. So we should go with adocument.importNode(node, { subtree, customElements })
overload.