- From: Domenic Denicola <notifications@github.com>
- Date: Wed, 13 Jul 2016 09:30:49 -0700
- To: w3c/webcomponents <webcomponents@noreply.github.com>
- Cc:
- Message-ID: <w3c/webcomponents/issues/512/232410812@github.com>
OK, @dominiccooney pointed out a problem with "stay custom with same definition" semantics, and now I am not sure we are on the right path here.
### The problem
A common pattern is for people to use a `<template>` to instantiate their element's contents. However, this pattern fails with our current setup for custom element registries and our proposed setup for adopting. Consider:
```html
<!DOCTYPE html>
<template id="xfoo">
<x-bar>hello</x-bar>
</template>
<script>
"use strict";
customElements.define("x-bar", class XBar extends HTMLElement { ... });
const template = document.querySelector("template#xfoo");
class XFoo extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define("x-foo", XFoo);
</script>
```
The problem is, template contents belong to a special browsing context-less Document. Thus, any elements created inside the template contents are never custom (step 2 of [look up a custom element definition](https://html.spec.whatwg.org/multipage/scripting.html#look-up-a-custom-element-definition) returns null). Cloning the template contents doesn't change that. And then, per the proposed adoption semantics in this thread, when we append the resulting document fragment, the cloned non-custom elements will carry their non-customness with them into XFoo's shadowRoot---not at all what we intended.
I hope we can all agree this is a problem? This kind of template + custom elements + shadow DOM scenario has been part of the web components story for as long as I have been involved, and it seems like we accidentally broke it. (Or at least, discovered that it wasn't on very solid footing.)
### Proposed solutions
@dominiccooney and I came up with several solutions, trying to take into account the various opinions expressed in this thread about defaults, added concepts, and more.
- "Auto downgrade": this is essentially the old "downgrade, then upgrade" from https://github.com/w3c/webcomponents/issues/512#issuecomment-226281431. This has the drawback of running a constructor twice. However, `adoptedCallback()` has the potential of allowing some kind of teardown/reset of state, which could help...
- "Manual downgrade": we keep the "stay custom with same definition" semantics by default, but elements which wish to work with `<template>` can use some new API, say `customElements.downgrade(element)`, inside their `adoptedCallback()`.
- "Branching adoption": when adopting elements, if the element already has a custom element definition, keep it. However, if it does not have one, then look up the potential custom element definition in the destination document, and if such a definition exists, assign it. This prevents running any constructors twice, and solves the template problem (as well as the similar-but-less-common `responseXML` and `DOMParser` problems).
- There's a variant of this where we branch based on whether the source document had a browsing context, instead of based on whether the being-adopted element had a custom element definition. The difference being that "has a browsing context" would only catch the template/responseXML/DOMParser cases, whereas "has a custom element definition" would also allow moving elements between "normal" documents and the element "lighting up" if only the destination document has a definition.
Of these I am warming up to "branching adoption"... The "has a browsing context" version even seems somewhat principled. I guess we conceptualize that as "elements get a chance to become custom the first time their node document has a browsing context", which is either at creation, or at adoption.
I'm really sorry to retread this after we already went through the discussion and seemingly settled on a good solution. But I think we missed something big, and fixing it will be worth it!
---
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/512#issuecomment-232410812
Received on Wednesday, 13 July 2016 16:31:34 UTC