Re: document.register and ES6

On Wed, Feb 6, 2013 at 11:18 AM, Erik Arvidsson <arv@chromium.org> wrote:

> On Wed, Feb 6, 2013 at 1:38 PM, Scott Miles <sjmiles@google.com> wrote:
> > Sorry, replace MyButton.super() with MyButton.super.call(this);
> >
> >
> > On Wed, Feb 6, 2013 at 10:37 AM, Scott Miles <sjmiles@google.com> wrote:
> >>
> >> So, neglecting issues around the syntax of document.register and the
> >> privatization of callbacks, is it fair to say the following is the
> intended
> >> future:
> >>
> >> class MyButton extends HTMLButtonElement {
> >>   constructor() {
> >>     super();
> >>     // make root, etc.
> >>   }
> >> }
> >> document.register('x-button', MyButton);
> >>
> >> If so then can we do this in the present:
> >>
> >> MyButtonImpl = function() {
>
> What do you mean here?
>
> >>   MyButton.super();
>
> Did you get that backwards? I don't see how MyButtonImpl can be
> derived from MyButton.
>

Its not. The 'super' means 'the super-class constructor for MyButton that
does not include magic DOM object generation' (in this case,
HTMLButtonElement). For MyDerivedButton, MyDerivedButton.super would point
to MyButtonImpl.

The existence of MyButtonImpl is an unfortunate side-effect of needing a
generated constructor.

The idea is to correspond as closely as possible with the ES6
version. MyButtonImpl goes away in ES6, it's purpose in the meantime is
just to provide something that looks like a proper class.

I could write it this way:

*MyButton = function() {
  MyButton.super();
  // make root, etc.
};
MyButton.prototype = Object.create(HTMLButtonElement, { ... });*
*
MyButton = document.register(‘x-button’, MyButton);
*

Written this way, MyButton no longer refers to the constructor you
specified, but instead refers to the generated constructor. This is
conceptually cleaner, but it's a bit tricky. For maximum clarity, I named
the internal version MyButtonImpl in my example code, but there is no
reason to have that symbol.


>
> >>   // make root, etc.
> >> };
> >> MyButtonImpl.prototype = Object.create(HTMLButtonElement, { ... });
> >>
> >> // the ‘real’ constructor comes from document.register
> >> // register injects ‘super’ into MyButton
> >> MyButton = document.register(‘x-button’, MyButtonImpl);
>
> What is the relationship between MyButton and MyButtonImpl?
>
> If MyButton.__proto__ === MyButtonImpl and
> MyButton.prototype.__proto__ === MyButtonImpl.prototype then this
> might work (but this cannot be polyfilled either).
>
>
MyButton.prototype == MyButtonImpl.prototype or
MyButton.prototype.__proto__ == MyButtonImpl.prototype, depending on needs.

MyButton itself does magic DOM construction work that we cannot do with
normal inheritance, then invokes MyButtonImpl. MyButtonImpl is never used
as a constructor itself (not as an argument to 'new' anyway).

>From the user's perspective, he has made a single class which implements
his element (the goal!). The unfortunate name shenanigan (I called my class
MyButtonImpl, but after 'register' I refer to it as MyButton) is the
simplest way I could conceive to overcome the 'generated constructor'
problem.

To be clear, everything I come up with is intended to polyfill (modulo my
error), because I generally am writing those myself (at first anyway). One
version might look like this:

document.register = function(inExtends, inClass) {
  var ctor = makePrototypeTwiddlingConstructorForDomNodes(inClass);
  ctor.prototype = inClass.prototype;
  addToTagRegistry(inExtends, ctor, inClass);
  ctor.super = getClassForExtendee(inExtends);
  return ctor;
};


--
> erik
>

Received on Wednesday, 6 February 2013 19:59:37 UTC