W3C home > Mailing lists > Public > public-webapps@w3.org > January to March 2015

Re: Custom element design with ES6 classes and Element constructors

From: Boris Zbarsky <bzbarsky@mit.edu>
Date: Tue, 13 Jan 2015 00:04:50 -0500
Message-ID: <54B4A772.60105@mit.edu>
To: public-webapps@w3.org
On 1/11/15 3:13 PM, Domenic Denicola wrote:
> So, at least as a thought experiment: what if we got rid of all the local name checks in implementations and the spec. I think then `<my-q>` could work, as long as it was done *after* `document.registerElement` calls.

Yes.

> However, I don't understand how to make it work for upgraded elements at all, i.e., in the case where `<my-q>` is parsed, and then later `document.registerElement("my-q", MyQ)` happens. You'd have to somehow graft the internal slots onto all MyQ instances after the fact

Yep.  It's no fun.

> Is there any way around this you could imagine?

Not without making the set of internal slots mutable.

Note that in some implementations (e.g. a self-hosted implementation 
using WeakMaps for internal slots) this might not be so difficult.  But 
in general it does constrain implementation strategies quite significantly.

> I know how seriously you were considering my suggestion to rewrite them all ;)

I've pretty seriously considered it on and off....

> The story is still pretty unsatisfactory, however. Consider the case where your document consists of `<my-el></my-el>`, and then later you do `class MyEl extends HTMLElement {}; document.registerElement("my-el", MyEl)`. (Note how I don't save the return value of document.registerElement.) When the parser encountered `<my-el>`, it called `new HTMLUnknownElement(...)`, allocating a HTMLUnknownElement. The current design says to `__proto__`-munge the element after the fact, i.e. `document.body.firstChild.__proto__ = MyEl.prototype`. But it never calls the `MyEl` constructor!

Yeah, I'm not a fan of this part either.

> - It means that the code `class MyEl extends HTMLElement {}` is largely a lie.

I think this part of the spec was largely written before ES6 class stuff 
stabilized, fwiw.  Which is not hard, since it's still not stabilized.  ;)

> - It means that what you get when doing `new MyEl()` is different from what you got when parsing-then-upgrading `<my-el></my-el>`.

This seems pretty undesirable.

> (The same problems apply with <q is="qq">, by the way. It needs to be upgraded from HTMLQuoteElement to QQ, but we can only `__proto__`-munge, not call the constructor.)

Hmm.  So given the current direction whereby ES6 constructors may not 
even be [[Call]]-able at all, I'm not sure we have any great options 
here.  :(  Basically, ES6 is moving toward coupling allocation and 
initialization but the upgrade scenario can't really be expressed by 
coupled alloc+init if it preserves object identity, right?

> I was hopeful that ES6 would give us a way out of this, but after thinking things through, I don't see any improvement at all. In particular it seems you're always going to have to have `var C2 = document.registerElement("my-el", C1)` giving `C2 !== C1`.

This part is not immediately obvious to me.  Why does that have to be true?

-Boris
Received on Tuesday, 13 January 2015 05:05:22 UTC

This archive was generated by hypermail 2.3.1 : Friday, 27 October 2017 07:27:25 UTC