Your proposal is appealing but I haven't convinced myself it works. There are a 
couple bits I haven't quite grokked.

> The special `constructor` method in ClassDeclaration/ClassExpression syntax
> would desugar to a static @@new method. This class:
> 
>    class Point {
>        constructor(x = 0, y = 0) {
>            this.x = x;
>            this.y = y;
>        }
>    }
> 
> would amount to this:
> 
>    class Point {
>        static [Symbol.new](x = 0, y = 0) {
>            var obj = super[Symbol.new]();
>            obj.x = x;
>            obj.y = y;
>            return obj;
>        }
>    }

You're inlining the method body into the @@new body, but I want to make sure I 
understand what the specification of the Point function itself would be. You've 
said Point !== Point[@@new] but calling Point(...args) should behave the same 
as new Point(...args). So then would the specification of the Point function's 
behavior just be to delegate to Point[@@new](...args)?

> The "super Arguments" call syntax in the ES6 drafts would be constrained to
> appear only at the top of a constructor, as in Java:

This part is what I'm the most unclear about. What invariant are you trying to 
maintain? It seems like you're using this to attempt to guarantee that all 
superclasses have had the chance to initialize their internal fields before 
user code starts running, so that built-in classes can have consistent internal 
representations and not have to worry about guarding against reading from 
uninitialized internal slots. But this is a tricky invariant to guarantee. 
First of all I think you'd have to put syntactic restrictions in place to 
disallow referring to `this` in the super call, to avoid e.g.:

  class Sneaky extends Date {
    constructor(x) {
      super((console.log(this.valueOf()), x));
    }
  }

But that's not enough, because you also have to worry about the superclass 
constructors calling overloaded methods:

  class Dupe extends Date {
    constructor(x) {
      super(x);
      initDupe();
    }
    initDupe() { ... }
  }

  class Sneaky extends Dupe {
    constructor(x) { super(x); }
    initDupe() {
      console.log(this.valueOf());
      super.initDupe();
    }
  }

(These are common pitfalls in languages that try to provide hard guarantees 
about field initialization. They come up, for example, in typed OO languages 
that try to provide guaranteed non-nullable fields.)

But maybe I'm misunderstanding what invariant you're aiming at?

> *   Base class constructors are always called.

Are you saying you would not only restrict the super call to the top, but 
require one to always be there? Or would an absence of a super call imply an 
implicit `super()`?

> *   These productions would be dropped from the ES6 grammar:
> 
>        MemberExpression : new super Arguments
>        NewExpression : new super

Clearly with your design `super[Symbol.new](...args)` is equivalent to `new 
super`. Is it also emulate-able in the @@create semantics also? If so it seems 
like the question of whether to keep or drop the `new super` syntax is 100% 
orthogonal to your proposal.

Dave

_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to