Re: [webcomponents] Custom elements disconnected from a document should not be upgraded (#419)

After thinking about this some more I am a fan of the following parts of @rniwa's plan:

- add a new upgradeable flag to [create an element](https://w3c.github.io/webcomponents/spec/custom/#dfn-create-element), which if set and the element is an [undefined potentially-custom element](https://w3c.github.io/webcomponents/spec/custom/#dfn-undefined-potentially-custom-element), will add it to the [upgrade candidates map](https://w3c.github.io/webcomponents/spec/custom/#dfn-upgrade-candidates-map).
- createElement(NS) gets a new option that lets authors control this flag. upgrade is easier to spell than upgradeable even if it's slightly less accurate, so let's go with upgrade.
- the parser always sets this flag when parsing documents

Unresolved questions:

- Does the parser set the flag when parsing fragments?
- Do we set the flag when cloning nodes?

I think "yes" is probably OK for both of these questions? The undefined potentially-custom elements inside the parsed fragment or cloned tree will have other things referencing them, almost certainly.

We then have the issue of how to provide more ergonomic sugar for after-the-fact upgrading. @rniwa proposed a template-based helper but I think we should explore this space in a bit more detail before settling on that.

I think the lowest-level possible primitive is `document.upgradeElement(el)` which will perform an upgrade if possible (e.g. if the element was created without the upgradeable flag set), and will add it to the upgrade candidates map otherwise. (Assuming it has a valid custom element name as its local name, and is in the HTML namespace.) Maybe it returns a value to signify what happened. I'm not sure whether this primitive is useful enough to expose, but in extensible web style I'd lean toward exposing it.

A higher-level API might look something like `Node.prototype.upgradeDescendants()` which will find all children that are potentially upgradeable and perform the `document.upgradeElement(el)` algorithm on them. This seems a bit more useful for working with document fragments or other nodes that are disconnected but not necessarily part of a template.

Finally if we think that it'll be common to use disconnected `<template>` elements that are created before appropriate element definitions are loaded, we could have a `template.instantiateIn(document)` or similar that essentially does a combination of `document.importNode(template.contents, true)` + `result.upgradeDescendants()`. I think how useful this is and even how it works is pretty dependent on the two "unresolved questions" above.

---

This is a pretty big issue, so thanks @rniwa for catching it. It's frustrating we can't just do things automatically, and this will definitely hurt the ability for upgrades to "just work" without the developer knowing about them, but it's important to stay deterministic and not expose GC semantics.

---
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/419#issuecomment-194640804

Received on Thursday, 10 March 2016 03:15:52 UTC