RE: ES6 and upgrading custom elements

2015-01-07 Thread Domenic Denicola
From: annevankeste...@gmail.com [mailto:annevankeste...@gmail.com] On Behalf Of 
Anne van Kesteren

> That's why I tried to scope this thread to upgrading and not the script side.
>
> The main question is how you tie MyInputElement to something like  
> and have that actually work. It seems Dimitri's answer is that you don't, you 
> use  in combination with a (delayed) prototype mutation 
> and creation callback. And you use createElement("input", "my-input") or the 
> constructor on the script side of things.

Oh my goodness, I'm sorry. I completely misunderstood what was meant by 
"upgrading." My fault entirely, as it's a well-defined custom elements term.

I see the problem now. I'll try to think on it harder and get back to you. In 
the meantime, apologies for derailing the thread.



Re: ES6 and upgrading custom elements

2015-01-07 Thread Anne van Kesteren
On Wed, Jan 7, 2015 at 5:53 AM, Domenic Denicola  wrote:
> ... all instances of MyInputElement will get all internal slots and other 
> exotic behavior of HTMLInputElement.

That's why I tried to scope this thread to upgrading and not the script side.

The main question is how you tie MyInputElement to something like
 and have that actually work. It seems Dimitri's answer is
that you don't, you use  in combination with a
(delayed) prototype mutation and creation callback. And you use
createElement("input", "my-input") or the constructor on the script
side of things.


> Which is that the HTML standard should just define that 
> `HTMLInputElement.extends = "input"`.

We could have that I guess, but it still doesn't help with upgrading, does it?


-- 
https://annevankesteren.nl/



RE: ES6 and upgrading custom elements

2015-01-06 Thread Domenic Denicola
This is all intimately tied to the still-ongoing how-to-subclass-builtins 
discussion that is unfortunately happening on a private TC39 thread. The 
essential idea, however, is that as long as you do

```js
class MyInputElement extends HTMLInputElement {
  constructor() {
super(); // this is key
  }
}
```

then all instances of MyInputElement will get all internal slots and other 
exotic behavior of HTMLInputElement. The `super()` call is the signal that the 
object should be allocated and initialized using the logic of HTMLInputElement 
instead of Function.prototype (the default).

This will require defining a constructor for HTMLInputElement, of course, but 
it's pretty predictable you wouldn't be able to create subclasses of something 
without a constructor.

I am not sure exactly how this fits in with an ES6-era 
document.registerElement. This is the right time to start thinking about that, 
certainly.

Off the top of my head, ideally document.registerElement should just be a 
"registration" call, and should not actually need to modify the constructor or 
create a new constructor as it does today. The generated constructor in [1] 
does nothing special that the above constructor (which consists entirely of 
`super()`) could not be made to do automatically, as long as the Element 
constructor was made smart enough. (`super()` eventually will delegate up to 
the Element constructor.)

To explain that in more detail I need one more probable-ES6 concept, which is 
the "new target." In the expression `var x = new MyInputElement()`, ` 
MyInputElement` is the "new target". Part of the ES6 subclassing story is that 
all superclass constructors will be passed an implicit parameter for the new 
target. So, when the `MyInputElement()` constructor calls `super()`, that calls 
the [[Construct]] internal method of HTMLInputElement, passing in the new 
target of MyInputElement. Similarly when HTMLInputElement in turn calls 
`super()`, that will call the [[Construct]] internal method of HTMLElement, 
still passing in the new target of MyInputElement. Etc. until Element also gets 
a new target of MyInputElement.

With this in hand we could see how to define a "smart enough" element 
constructor. It would first look up the new target in the custom element 
registry. If it is there, it retrieves the definition for it, and can do all 
the work currently specified in [1]. That means that the actual constructor for 
`MyInputElement` can be as above, i.e. simply `super()`.

[1]: 
https://w3c.github.io/webcomponents/spec/custom/#dfn-custom-element-constructor-generation

> Conceptually, when I wrote it I'd imagined that the constructor will be 
> called only when you explicitly invoke it (new FooElement...). When parsing 
> or upgrading, the constructor would not be called. The createdCallback will 
> be invoked in either case.

I do not think this makes any sense. All instances of a class can only be 
created through its constructor. createdCallback should be left behind as 
legacy IMO.

--

With all this in mind I do not think "extends" is necessary. I am less sure 
about this though so take what follows with a grain of salt. But anyway, IMO 
you should just look at the inheritance chain for the constructor passed in to 
registerElement.

Also there is a pretty simple hack if you still want extends. Which is that the 
HTML standard should just define that `HTMLInputElement.extends = "input"`. 
Then in Dmitry's

```js
class X extends HTMLInputElement { .. }
X.extends = "input" // additional line.
document.register("x-input", X)
var xinput = new X
```

the need for the additional line disappears since `X.extends === 
HTMLInputElement.extends === "input"`.

(I guess this breaks for classes that have multiple tag names :-/. But it is 
pretty weird that I can't define `class QQ extends HTMLQuoteElement {}` and 
then do both `` and ``. You would think I 
could do both. More reason to dislike `extends`.)



Re: ES6 and upgrading custom elements

2015-01-06 Thread Dimitri Glazkov
On Tue, Jan 6, 2015 at 10:59 AM, Anne van Kesteren  wrote:

> On Tue, Jan 6, 2015 at 7:54 PM, Dimitri Glazkov 
> wrote:
> > Right, that's why to create a valid custom element that subclasses
> > HTMLInputElement, you should use type extensions. With type extensions,
> the
> > HTMLInputElement is what's instantiated.
>
> But without using type extensions this will work (provided we sort out
> the other bits):
>
>   class X extends HTMLInputElement { ... }
>   document.registerElement("x-input", X)
>   var xinput = new X
>
> It seems sad to require type extensions (and therefore requiring a
> more complicated version of document.registerElement) for translating
> this into markup.
>

You shouldn't need anything more complicated:

class X extends HTMLInputElements { .. }
X.extends = "input" // additional line.
document.register("x-input", X)
var xinput = new X


>
> Having actual subclassing in JavaScript, but not for elements unless
> you use some sort of hack seems sad.
>

The type extensions is a hack, I agree :(

:DG<


Re: ES6 and upgrading custom elements

2015-01-06 Thread Anne van Kesteren
On Tue, Jan 6, 2015 at 7:54 PM, Dimitri Glazkov  wrote:
> Right, that's why to create a valid custom element that subclasses
> HTMLInputElement, you should use type extensions. With type extensions, the
> HTMLInputElement is what's instantiated.

But without using type extensions this will work (provided we sort out
the other bits):

  class X extends HTMLInputElement { ... }
  document.registerElement("x-input", X)
  var xinput = new X

It seems sad to require type extensions (and therefore requiring a
more complicated version of document.registerElement) for translating
this into markup.

Having actual subclassing in JavaScript, but not for elements unless
you use some sort of hack seems sad.


-- 
https://annevankesteren.nl/



Re: ES6 and upgrading custom elements

2015-01-06 Thread Dimitri Glazkov
On Tue, Jan 6, 2015 at 10:38 AM, Anne van Kesteren  wrote:

> On Tue, Jan 6, 2015 at 7:06 PM, Dimitri Glazkov 
> wrote:
> > Yes to the first question. I wasn't planning on doing anything different
> > there.
>
> It seems simple prototype munging but not actually changing identity
> will fail for all but the basic cases of subclassing. E.g. if I
> subclass an HTMLInputElement I would expect it to have an internal
> [[value]] slot of sorts, but since the element created is a plain
> HTMLElement whose prototype is munged that will not be the case.
>

Right, that's why to create a valid custom element that subclasses
HTMLInputElement, you should use type extensions. With type extensions, the
HTMLInputElement is what's instantiated.

:DG<


Re: ES6 and upgrading custom elements

2015-01-06 Thread Anne van Kesteren
On Tue, Jan 6, 2015 at 7:06 PM, Dimitri Glazkov  wrote:
> Yes to the first question. I wasn't planning on doing anything different
> there.

It seems simple prototype munging but not actually changing identity
will fail for all but the basic cases of subclassing. E.g. if I
subclass an HTMLInputElement I would expect it to have an internal
[[value]] slot of sorts, but since the element created is a plain
HTMLElement whose prototype is munged that will not be the case.


-- 
https://annevankesteren.nl/



Re: ES6 and upgrading custom elements

2015-01-06 Thread Dimitri Glazkov
On Tue, Jan 6, 2015 at 9:56 AM, Anne van Kesteren  wrote:

> On Tue, Jan 6, 2015 at 6:13 PM, Dimitri Glazkov 
> wrote:
> > That section needs to be updated, because the ES6 spec had shifted a
> little
> > bit with regard to @@create. Filed
> > https://www.w3.org/Bugs/Public/show_bug.cgi?id=27769.
>
> Yeah, there's issues in general there, such as ES6 giving up on
> explaining all of DOM :-(
>
>
> > Conceptually, when I wrote it I'd imagined that the constructor will be
> > called only when you explicitly invoke it (new FooElement...). When
> parsing
> > or upgrading, the constructor would not be called. The createdCallback
> will
> > be invoked in either case.
>
> Would you do the prototype munging that is specified in
> "createdCallback" today? (I think it would be more clear if we made
> that prototype munging part of the upgrade algorithm by the way.) How
> else would that work? Pass a reference to the old element and let the
> developer handle it?
>

Yes to the first question. I wasn't planning on doing anything different
there. And yes, I would like to fix the munging clarity as part of
https://www.w3.org/Bugs/Public/show_bug.cgi?id=27437.

:DG<


>
>
> --
> https://annevankesteren.nl/
>


Re: ES6 and upgrading custom elements

2015-01-06 Thread Anne van Kesteren
On Tue, Jan 6, 2015 at 6:13 PM, Dimitri Glazkov  wrote:
> That section needs to be updated, because the ES6 spec had shifted a little
> bit with regard to @@create. Filed
> https://www.w3.org/Bugs/Public/show_bug.cgi?id=27769.

Yeah, there's issues in general there, such as ES6 giving up on
explaining all of DOM :-(


> Conceptually, when I wrote it I'd imagined that the constructor will be
> called only when you explicitly invoke it (new FooElement...). When parsing
> or upgrading, the constructor would not be called. The createdCallback will
> be invoked in either case.

Would you do the prototype munging that is specified in
"createdCallback" today? (I think it would be more clear if we made
that prototype munging part of the upgrade algorithm by the way.) How
else would that work? Pass a reference to the old element and let the
developer handle it?


-- 
https://annevankesteren.nl/



Re: ES6 and upgrading custom elements

2015-01-06 Thread Dimitri Glazkov
That section needs to be updated, because the ES6 spec had shifted a little
bit with regard to @@create. Filed
https://www.w3.org/Bugs/Public/show_bug.cgi?id=27769.

Conceptually, when I wrote it I'd imagined that the constructor will be
called only when you explicitly invoke it (new FooElement...). When parsing
or upgrading, the constructor would not be called. The createdCallback will
be invoked in either case.

:DG<


On Tue, Jan 6, 2015 at 7:21 AM, Anne van Kesteren  wrote:

> It's not clear to me from
> https://w3c.github.io/webcomponents/spec/custom/#es6 how the upgrade
> works. From the pre-ES6 setup you can work out through inference that
> upgrading is supposed to mutate the prototype of the element in
> question.
>
> But it seems that mutating the prototype is not sufficient for ES6. We
> want an element created through the constructor, no? (Let's leave
> aside the question for now as to how this subclassing would work,
> that's already discussed elsewhere.)
>
>
> --
> https://annevankesteren.nl/
>
>


ES6 and upgrading custom elements

2015-01-06 Thread Anne van Kesteren
It's not clear to me from
https://w3c.github.io/webcomponents/spec/custom/#es6 how the upgrade
works. From the pre-ES6 setup you can work out through inference that
upgrading is supposed to mutate the prototype of the element in
question.

But it seems that mutating the prototype is not sufficient for ES6. We
want an element created through the constructor, no? (Let's leave
aside the question for now as to how this subclassing would work,
that's already discussed elsewhere.)


-- 
https://annevankesteren.nl/