[w3c/webcomponents] Some sort of guarantee on upgrade order? (#737)

It'd be nice to have some sort of guarantee on upgrade order. For example, it'd be great if upgrade order of elements in an HTML payload was always depth-first.

## The problem

In #559, I have some problems, which ultimately stem from the fact that the order in which elements are upgraded in the DOM (breadth-first vs depth-first) depends on whether upgrade happens

1. during parsing (i.e. elements were defined using `customElements.define()` in a `<script>` tag in the `<head>`, before the `<body>` is parsed)
2. or after the HTML is parsed (f.e. elements are defined in a `<script>` tag at the end of the `<body>` so that by the time `customElements.define()` is called, the DOM already exists)

Either of the cases apply at other points in runtime too:

1. The first case also applies in any case at runtime and after DOM is ready, where `customElements.define()` is used to define an element then _after that_ the respective type of element is created and appended into DOM.
2. The second case also applies in any case at runtime and after DOM is ready, where an element is _first_ created and appended into the DOM _then_ it is defined with `customElements.define()`

Here is a demonstration of one form of each case (though other forms exist):

https://jsfiddle.net/wkwmzLwL

The order of upgrade is reversed between those two cases.

## Why is this bad?

This leads to ugly conditional checking and/or deferral hacks needed in order for parent elements to be able to always work with child elements where the child elements are expected to be certain types of custom elements. This can lead to harder-to-maintain code and increases surface area for unexpected and weird bugs.

Here's an example of a hack that solves the problem from the previous fiddle:

https://jsfiddle.net/aqp4uaja

## Solution?

I'm not quite sure what a solution (for browsers to implement) would be exactly. Some solution ideas:

1. Maybe https://github.com/w3c/webcomponents/issues/550 could help in some cases:
  - For example, suppose that during parsing, `childConnectedCallback`s are only called after child elements are upgraded _**iff** the child elements have already been defined by `customElements.define`_.
  - If the child elements' names are not yet defined in `customElements`, then it doesn't make sense to wait for upgrades that may never happen. In this case, I'm not sure what's a clear solution.
2. Another possibility could be to forbid elements from being defined after they're already in the DOM. F.e.:
  - `DOMException: An element named 'some-thing' has already been created. Elements should be defined before they are created.`
3. Instantiate custom elements like we do now during parsing, which is not in breadth-first order, but wait for a closing tag of a custom elements to be encountered before calling it's `connectedCallback`, which makes it possible to ensure that child element `connectedCallbacks` are called first, in depth-first order.
  - The only problem with this is that if the HTML payload is huge, it may take a long time (due to network) before elements come to life.
    - Personally, I'm fine with this. I'd rather add a nice loader animation, and break down my web app to small pieces (f.e. a huge table can be paginated so that load time is bearable).

Basically, some consistency would be great: it would lend to cleaner and more solid Web Components.

-- 
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/737

Received on Sunday, 18 February 2018 02:24:46 UTC