New.initialize
For Stage 1
Daniel Ehrenberg
Igalia, in partnership with Bloomberg
January 2019 TC39
Motivation
Stable prototype chains
ES6 subclasses
class A {� constructor() { this.x = 1; }�}�class B extends A {� constructor() { super(); this.y = 2; }�}��const instance = new B();�console.log(instance.x); // 1�console.log(instance.y); // 2
Dynamic prototype chains
class A {� constructor() { this.x = 1; }�}�class B extends A {� constructor() { super(); this.y = 2; }�}�B.__proto__ = class {� constructor() { this.z = 3; }�};�const xx = new B();�console.log(xx.x); // undefined!�console.log(xx.y); // 2�console.log(xx.z); // 3!
A strong defense: Freezing the constructor
class A {� constructor() { this.x = 1; }�}�class B extends A {� constructor() { super(); this.y = 2; }�}�Object.freeze(B)�B.__proto__ = class {� constructor() { this.z = 3; }�}; // TypeError
const instance = new B();�console.log(instance.x); // 1�console.log(instance.y); // 2
A subtle defense: Reflect.construct instead of super()
class B extends A {� constructor() {� const instance = Reflect.construct(� A, [], new.target);� instance.y = 2;� return instance;� }�}�B.__proto__ = class { };�const instance = new B();�console.log(instance.x); // 1!�console.log(instance.y); // 2
How does this work with private fields?
Similar issues occur with private fields
class C {� #v = 1;� get v() { return this.#v; }�}�class D {� #w = 2;� get w() { return this.#w; }�}�const instance = new D();�console.log(instance.v); // 1�console.log(instance.w); // 2�D.__proto__ = class {};�const broken = new D();�console.log(broken.v); // TypeError!�console.log(broken.w); // 2
Applying Reflect.construct
class D {� #w = 2;� get w() { return this.#w; }� constructor() {� const instance = Reflect.construct(� C, [], new.target);� new.initialize(instance);� return instance;� }�}��D.__proto__ = class {};�const fixed = new D();�console.log(fixed.v); // 1!�console.log(fixed.w); // 2
FAQ
check to disable calling new.initialize twice?
<small>
private symbols without reification doesn't solve this issue
</small>
Stage 1?