- From: Scott Miles <sjmiles@google.com>
- Date: Wed, 6 Feb 2013 13:07:32 -0800
- To: Erik Arvidsson <arv@chromium.org>
- Cc: Daniel Buchner <daniel@mozilla.com>, Dimitri Glazkov <dglazkov@google.com>, public-webapps <public-webapps@w3.org>, Boris Zbarsky <bzbarsky@mit.edu>
- Message-ID: <CAHbmOLaw92YqdKuPKO1Q+oU+COWv6tn16ePOtWNCtNf6UKw6EQ@mail.gmail.com>
Well, this (non-robust quicky test) works in IE: http://jsfiddle.net/zUzCx/1/ On Wed, Feb 6, 2013 at 12:59 PM, Scott Miles <sjmiles@google.com> wrote: > Afaik, the 'generated constructor' is technical debt we are stuck with > until we can actually invoke DOM constructors from JS. If there is a better > way around it, I'm all ears! > > polyfilling without __proto__: I don't know if it's possible, which is a > good point. I was basically ignoring that problem, but I guess I should not > do that: we may have to utterly change our target. > > Iow, perhaps we can decorate node instances with API scraped off of a > separate prototype chain. Ironically, this is close to what my component > sugaring layer does anyway, in order to support protected API. > > S > > > On Wed, Feb 6, 2013 at 12:50 PM, Erik Arvidsson <arv@chromium.org> wrote: > >> If we are willing to return a new constructor function I think we have >> no problems. I was concerned that it would lead to people using the >> wrong function but it does solve the issues. >> >> class MyButtonImpl extends HTMLButtonElement { >> } >> let MyButton = document.register('my-button', { >> class: MyButtonImpl // maybe call the property "implementation" if >> we don't want to use "class". >> }); >> >> I feel like this is getting close to my pain tolerance for boilerplate >> code but I'm willing to realize that currently this is the only >> working proposal (for polyfilling in __proto__ browser). >> >> I'm still curious how people are planning to do this in non __proto__ >> browsers? >> >> On Wed, Feb 6, 2013 at 3:43 PM, Scott Miles <sjmiles@google.com> wrote: >> > Yes, it's not intended to work in IE ... I used __proto__. >> > >> > >> > On Wed, Feb 6, 2013 at 12:41 PM, Daniel Buchner <daniel@mozilla.com> >> wrote: >> >> >> >> Scott: is this example not intended to work in IE9? It throws, the >> output >> >> object is missing the 'oranginate' method. >> >> >> >> Daniel J. Buchner >> >> Product Manager, Developer Ecosystem >> >> Mozilla Corporation >> >> >> >> >> >> On Wed, Feb 6, 2013 at 12:32 PM, Scott Miles <sjmiles@google.com> >> wrote: >> >>> >> >>> There were several errors in my pseudo-code, here is a working >> version: >> >>> >> >>> http://jsfiddle.net/yNbnL/1/ >> >>> >> >>> S >> >>> >> >>> >> >>> On Wed, Feb 6, 2013 at 12:01 PM, Scott Miles <sjmiles@google.com> >> wrote: >> >>>> >> >>>> Errata: >> >>>> makePrototypeTwiddlingConstructorForDomNodes needs to know the >> extendee >> >>>> >> >>>> var ctor = makePrototypeTwiddlingConstructorForDomNodes(inExtends, >> >>>> inClass); >> >>>> >> >>>> >> >>>> On Wed, Feb 6, 2013 at 11:59 AM, Scott Miles <sjmiles@google.com> >> wrote: >> >>>>> >> >>>>> 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 >> >>>>> >> >>>>> >> >>>> >> >>> >> >> >> > >> >> >> >> -- >> erik >> > >
Received on Wednesday, 6 February 2013 21:08:02 UTC