OK, after reading Dominic's proposal [1], I'm a little confused. I thought that 
I understood how constructors should work, but there's some magic going on that 
I can't follow... I'm sure you folks can help.

```
class CustomElement extends HTMLElement {
   constructor() {
      super();
   }
}

Something magical happens here. The use of super() is supposed to call the 
constructor of the HTMLElement class-but that's not a normal JS class. It 
doesn't have a defined constructor() method [yet?]. Also, as has been pointed 
out, running the CustomElement constructor code _before_ instantiating the 
actual element (at parse-time for example) opens up a world of potential 
problems as have been explored:

*        Javascript classes are mutable-what if CustomElement's proto chain is 
mutated later?

*        What if the constructor throws?
...just to name a few.

I'm trying to rationalize the custom elements previous design with the use of 
constructors. Basically, I think it should still be a two-stage creation model:

1.      Native [internal] element is created with appropriate tag name, 
attributes, etc.

2.      JS constructor is called and provided the instance (as 'this')

#1 is triggered by the parser, or by a native constructor function. That 
constructor function could either be provided separately like it is returned 
from registerElement today, or in some other way (replacing the original 
constructor?). Since replacing the original constructor sounds weird and 
probably violates a bunch of JS invariants, I'll assume sticking with the 
original model.

This makes it much safer for implementations, since the native custom element 
can always be safely created first, before running JS code. It also means 
there's no magic super() at work-which seems to leave too much control up to 
author code to get right.

Basic example of what I'm thinking:

class XFooStartup extends HTMLElement {
   constructor(val1, val2) {
      this.prop = val1;
      this.prop2 = val2;
   }
}
window.XFoo = document.registerElement('x-foo', XFooStartup);

// (1)
var x1 = new XFooStartup("first", "second");
// (2)
var x2 = new XFoo("first", "second");

Calling (1) does not create a custom element. Extending from HTMLElement is not 
magical, it's just a prototype inheritance, as can be done today. super() would 
do whatever super() does when the super class has no defined method to invoke. 
x1 is a regular JS object with a .prop and .prop2.

Calling (2) runs the platform-provided constructor function which internally 
inits a new HTMLElement in the C++ (or could be Element if in XML document?). 
Then the platform immediately (synchronously) invokes the provided constructor 
function as if:
XFooStartup.apply(newHTMLElementInstance, argsPassedThroughFromCall);
so that XFooStartup's constructor operates on the 'this' being the instance 
created by the platform.


[1] 
https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Optional-Upgrades-Optional-Constructors.md

Reply via email to