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
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 "ES5 new Number ( [ value ] )" [2]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-13.2.2 "ES5 [[Construct]]" [3]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-static-semantics-constructormethod "ES6 Static Semantics: ConstructorMethod" [4]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation "ES6 Runtime Semantics: ClassDefinitionEvaluation" [5]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-number-constructor-number-value "ES6 Number ( [ value ] )"