Jason Orendorff (2014-06-17T19:21:59.000Z)
dignifiedquire at gmail.com (2014-06-17T19:46:22.702Z)
Allen asked me to fill out what @@new would mean. Here it is. ## How `new X` works `new X(...args)` ==== `X[@@new](...args)` ## How it works for ES5 builtin constructors `Number(value)` is specified in one section. `Number[@@new](value)` is specified in another section. To support subclassing, `Number[@@new]()`, unlike ES5 [1], would set the new object's prototype to `this.prototype` rather than `Number.prototype`. Otherwise it all works just like ES5. The same goes for Object, Array, Function, Date, and the other builtins. ## How it works for regular functions `Function.prototype[@@new](...arguments)` is called. It works like this: 1. Let proto = `this.[[Get]]("prototype", this)`. 2. If proto is not an object, throw a TypeError. 3. Let obj = ObjectCreate(proto). 4. If the this value or any object on its prototype chain is an ECMAScript language function (not a class), then a. Let F be that object. b. Let result = `F.[[Call]](obj, arguments)`. c. If Type(result) is Object then return result. 5. Return obj. For regular functions, this behaves exactly like the `[[Construct]]` internal method in ES5 [2]. Step 4 is there to support regular functions and ES6 classes that subclass regular functions. ## How it works for ES6 classes 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; } } As in the current drafts, ES6 would have to do something mildly fancy (see [3] and step 8 of [4]) to perform the desugaring. If a class has no `constructor` method, it inherits the base class's static @@new method. The "super Arguments" call syntax in the ES6 drafts would be constrained to appear only at the top of a constructor, as in Java: class PowerUp { constructor(name, price) { ... } } class RocketPack extends PowerUp { constructor() { super("Rocket Pack", 1000); this.fuel = FULL_TANK; } } The RocketPack constructor would behave like this: static [Symbol.new]() { var obj = super[Symbol.new]("Rocket Pack", 1000); obj.fuel = FULL_TANK; return obj; } This has different runtime semantics compared the `super()` syntax in the current ES6 draft, but it serves the same purpose. And that's all. ## Benefits * As with Allen's proposal, we would drop [[Construct]] and the `construct` trap. * Instances of builtin classes are never exposed to scripts before their internal slots are fully initialized. * @@create can be dropped entirely, but we retain the benefit to implementers that all Maps (for example) can have the same in-memory layout, and other objects can't become Maps at runtime. * Base class constructors are always called. * The ES6 draft language in [5] step 5, and many other similar places, would be backed out. ("If Type(O) is Object and O has a [[NumberData]] internal slot and the value of [[NumberData]] is undefined, then...") * The current ES6 draft specifies new builtin constructors (Map, Set, WeakMap) to throw a TypeError if called without `new`. This new convention could be reversed to what ES5 does with Function and Array: `Map()` would be the same as `new Map()`. User-defined classes could work this way too. I think developers would appreciate this. * These productions would be dropped from the ES6 grammar: MemberExpression : new super Arguments NewExpression : new super If for whatever reason users want these, they can call `super[Symbol.new]()`. But I think they will no longer be needed. This would reduce the number of `super` forms to these 3: super.IdentifierName // allowed in all methods super[Expression] // allowed in all methods super(arguments) // only allowed in constructors [1]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-15.7.2.1 [2]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-13.2.2 [3]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-semantics-constructormethod [4]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation [5]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number-constructor-number-value