The Jonas proposal is to have a normal JavaScript subclass:
class MyElement extends HTMLElement {
constructor(htmlElementConstructorOptions, ...extraArgs) {
super(htmlElementConstructorOptions);
// initialization code here, potentially using extraArgs for non-parser cases
}
}
The catch is that while parsing you need to do bookkeeping when you encounter custom elements (those with a dash) and then construct and insert them at a later point. This does not quite explain the platform:
- If you iterate over the tree before such synchronization it will look weird.
- Mutation observers will tell a rather interesting story that does not match what the parser does today.
- Does not support asynchronous loading of custom element constructors.
The alternative is the Dmitry proposal which proposes a two-tier constructor. An element is constructed and inserted as normal and later "upgraded" to get the appropriate internal slots:
class MyElement extends HTMLElement {
[Element.create](...extraArgs) {
// initialization code here, potentially using extraArgs for non-parser cases
}
}
This also does not quite explain the platform:
- Requires instantiating the internal slots through
Element.create
rather than the constructor. - Requires mutating the prototype of objects at the time of invoking
Element.create
. - Requires an extension to JavaScript (
Reflect.isDefaultConstructor
) that has not been vetted by TC39.
However, it has been argued that we could possibly retrofit existing elements to follow a similar design, making elements self-consistent.