Generalize spec internal slots as private fields? · Issue #17 · tc39/proposal-private-fields (original) (raw)

It would be ideal if private slots could be a strict generalization of the internal slots used by the ES spec for the private state of built-in objects. Unfortunately, making this happen would require a breaking change to ES6.

To see why, consider this example:

class B extends A { constructor() { super(); } }

// OK, now let's change the prototype chain to make it a Map subclass! Object.setPrototypeOf(B, Map); Object.setPrototypeOf(B.prototype, Map.prototype);

// Now let's create an instance! let b = new B(); // Everything works OK b.set("a", 1);

That example works in ES6 because the Map constructor creates an object with a [[MapData]] internal slot. The internal slot list of the allocated object is not affected by NewTarget.

For this proposal, the user-defined private slot list is determined by NewTarget, so you cannot swap constructor prototypes and expect things to work.

class B extends A { constructor() { super(); } }

class C { #foo; constructor() { this.#foo = 1; } }

// OK, now let's change the prototype chain to make it a C subclass! Object.setPrototypeOf(B, C);

// Now let's create an instance! let b = new B(); // Nope, that that fails because the object isn't allocated with a #foo slot...

I would prefer to remove this incongruence and re-spec all built-in internal slots using the same semantics as user-defined private slots, but that would be a breaking change.

Thoughts?

@wycats
@littledan
@allenwb