Re: Custom elements "Constructor-Dmitry" baseline proposal

> On Aug 17, 2015, at 3:19 PM, Domenic Denicola <d@domenic.me> wrote:
> 
> In https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_w3c_webcomponents_blob_gh-2Dpages_proposals_Constructor-2DDmitry.md&d=BQIGaQ&c=eEvniauFctOgLOKGJOplqw&r=Cq0heWYmrUNShLjLIzuzGQ&m=U2qIHSkYawudMNTponjVOJxTr1-blzlm_skvYTCFFrk&s=Fqq6RL3oe2zmH8pGykh6XfqVC6LYMZILABlqZPRGG74&e=  I’ve written up in some detail what I consider to be the current state-of-the-art in custom elements proposals. That is, if we take the current spec, and modify it in ways that everyone agrees are good ideas, we end up with the "Constructor-Dmitry" proposal.
> 
> The changes, in descending order of importance, are:
> 
> - Don't generate new classes as return values from registerElement, i.e. don't treat the second argument as a dumb { prototype } property bag. (This is the original "Dmitry proposal".)
> - Allow the use of ES2015 constructors directly, instead of createdCallback. (This uses the constructor-call trick we discovered at the F2F.)
> - Use symbols instead of strings for custom element callbacks.
> - Fire attributeChanged and attached callbacks during parsing/upgrading
> 
> Those of you at the F2F may remember me saying something like "If only we knew about the constructor call trick before this meeting, I think we would have had consensus!" This document outlines what I think the consensus would have looked like, perhaps modulo some quibbling about replacing or supplementing attached/detached with different callbacks.
> 
> So my main intent in writing this up is to provide a starting point that we can all use, to talk about potential modifications. In particular, at the F2F there was a lot of contention over the "consistent world view" issue, which is still present in the proposal:
> 
> - Parser-created custom elements and upgraded custom elements will have their constructor and attributeChange callbacks called at a time when all their children and attributes are already present, but

Did you change that relative to the spec? Previously, parser-created custom elements would have their constructor called at a time when an unpredictable number of their children were present. 

> - Elements created via new XCustomElement() or document.createElement("x-custom-element") will have their constructor run at a time when no children or attributes are present.

If you really got it down to two states, I like reducing the number of word states, but I would prefer to put parser-created custom elements in this second bucket. They should have their constructor called while they have no children and attributes, instead of when they have all of them.

My reasons for this:

(1) This is more likely to lead to correctly coding your custom elements to rely on change notifications exclusively, rather than on what is present at parse time.
(2) Framework developers find it a footgun and an inconvenience for parser-created elements to have their constructor called with children present.
(3) It is possible for a parser-created element to render before "all of its children are present". It's also possible for it to never reach the state where it is known "all of its children [that will be created by the parser] are present". I can give examples if you like. Based on this, I think it's better to upgrade them as early as possible.

For these two reasons (#1 and #2 were mentioned in the f2f, #3 is something I thought of later), I think parser-created elements should have their constructor called early instead of late.

However, if we care about these edge cases, note that #3 *also* applies to upgrade. If we want to do upgrade late, and it's on a parser-created element, it may be the case that the element has already rendered when the info needed to upgrade it comes in, but it may be an unboundedly long time until all its children come in.

I guess I should give examples, so cases where this can happen:

(A) Load of the main document stalls partway through the element's children, before a close tag has been seen. But the upgrade script comes in via <script async> even during the stall.
(B) The document keeps loading forever by design. Admittedly this is unlikely for modern web design.
(C) The document is created with document.open()/document.write(), the element in question never has a close tag written, and no one ever calls document.close(). People actually still do this sometimes to populate opened windows or the like.

If any of this happens, an upgradeable element will be stuck in the pre-upgrade state for a possibly unboundedly long amount of time.

This seems like a bad property. 

Against this, we have the proposal to forcibly put elements in a naked state before calling the constructor for upgrade, then restore them. That has the known bad property of forcing iframe children to reload. I owe the group thoughts on whether we can avoid that problem.

> 
> If we still think that this is a showstopper to consensus (do we!?) then I hope we can use this proposal as a baseline from which to derive additive solutions. Alternately, maybe you all will read this proposal and be amazed at how great it is already, and agree we can move on, leaving the consistent world view issue aside as an edge-case that shouldn't prevent cross-browser consensus on custom elements :)

I will read the document more closely soon, to see if it seems like a reasonable baseline. I agree it would be fine to start with something good that uses the constructor and has two possible stats for constructor invocation, then see if we can get it down to one.

Regards,
Maciej

Received on Friday, 21 August 2015 06:07:07 UTC