Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Class private fields can't be used with extends null #288

Closed
ExE-Boss opened this issue Jan 5, 2020 · 6 comments
Closed

Class private fields can't be used with extends null #288

ExE-Boss opened this issue Jan 5, 2020 · 6 comments

Comments

@ExE-Boss
Copy link
Contributor

ExE-Boss commented Jan 5, 2020

📝 See tc39/ecma262#1036 and tc39/ecma262#1321.


With public fields, you can at least do:

class Foo extends null {
	foo;
	constructor(foo) {
		return Object.create(new.target.prototype, {
			foo: {
				configurable: true,
				enumerable: true,
				writable: true,
				value: foo,
			},
		});
	}
}

But with private fields, you can’t use the Object.create work‑around.


It’d be so much easier if:

class Foo extends null {};
new Foo;

and

class Foo extends null {
	constructor() {}
};
new Foo;

didn’t throw.


That would allow class fields to also be used with extends null:

class Foo extends null {
	#foo;
	constructor(foo) {
		this.#foo = foo;
	}
}
new Foo;
@ljharb
Copy link
Member

ljharb commented Jan 6, 2020

This is a result of classes themselves not properly supporting null. You can, however, extend a class that extends null and uses your workaround.

@rdking
Copy link

rdking commented Jan 6, 2020

What's the glitch in the null support?

@ExE-Boss
Copy link
Contributor Author

ExE-Boss commented Jan 6, 2020

The issue is that a constructor that extends null ends up with its [[ConstructorKind]] internal slot set to derived instead of base, which results in the implicit constructor being constructor(...args) { super(...args); } and the this binding being uninitialized instead of OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").

This is being fixed in issue tc39/ecma262#1036 (PR: tc39/ecma262#1321).

@rdking
Copy link

rdking commented Jan 6, 2020

I get it. Now just out of curiosity, why was class designed that way? It seems like it would've made things cleaner for there to never be a [[ConstructorKind]], for all actions to happen as if "derived" were the only kind, for the class base to always be either Object, null, or user specified, and for super() to be an internal function that automatically handles the special case of a null base. So why split the situation into something that requires 2 different constructor types?

@rdking
Copy link

rdking commented Jan 6, 2020

Just thought about it. That's questions better targeted on es-discuss...

@littledan
Copy link
Member

Yeah, classes extending null is sort of generally broken, unfortunately. See tc39/ecma262#1321 for some further discussion. Closing this issue, as it's not about class fields.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants