-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
class extends null with implicit constructor still broken #1036
Comments
In addition to the 10.a change, step 15 should be changed from
to
Basically after step 10, the appropriate test to determine whether we are defining a base class is whether constructorParent is %FunctionPrototype%. |
It's not just the default constructor that throws; an explicit construct also throws, at least as implemented in v8, JSC and SpiderMonkey: new (class extends null {}) // throws because of implicit constructor
new (class extends null { constructor() {} }) // throws because of missing super call
new (class extends null { constructor() { super() } }) // throws because of super call |
ChakraCore in MSEdge build 17063 allows the empty |
@Kovensky: It is possible to define a working constructor to a class extending null, provided that that constructor returns an explicit object, e.g.: class C extends null { constructor() { return Object.create(new.target.prototype) } } |
Can we make |
@claudepache Do you mean f3881fe ? You are probably right that they are observably equivalent. Probably because they both express my original intent. The intent was that the values present at ClassDefinitionEvaluation determined whether a base class or a derived class was created and the form of default constructor that is emitted when one is needed. A class that doesn't have an extends clause or whose extends clause evaluated to null should be created as a Base class. It isn't relevant whether whether after the class is created somebody uses SetPrototypeOf to modify either the [[Prototype]] of the constructor or the [[Prototype]] or the prototype. This was agreed upon during ES6 development. It was concluded that it was hacker beware if they type to play proto games with constructors created using class definitions. Given that, I think It was a bug ES2015 generated the wrong kind of default constructor and set extends null classes to derived. But it is by design that things are likely to break if you do proto hacking. It isn't clear to me why f3881fe need to be reverted. Or my not to use the fix I have above. As either gives the original intended behavior which of buggy in ES2015. It is kind of embarrassing that this feature has been broken for so long. It should really be fixed. I guess I think that this is the type of thing that the editor should be driving to resolution. |
Allowing |
@littledan Is this issue a blocker for the public/private fields proposal or is it acceptable if classes extending |
@anba You can get around this limitation with the following idiom: class X {
field;
}
X.__proto__ = null;
X.prototype.__proto__ = null; The constructor will not call For that reason, I'd say that this issue isn't a blocker. Still, I wouldn't mind seeing it resolved. |
@littledan I'd 👍 your response, but I just can't because... |
#781 reverted
class extends null {}
to the ES2015 semantics and says:but there does not appear to be an issue for that "future work".
The original problem in ES2015 is that
new class extends null {}
throws because the default constructor that is inserted does asuper()
call to %FunctionPrototype% which is not a constructor.The guards in ES2015 to prevent inserting that
super()
call were wrong and other subsequent attempts to correct that did things that cause other problems (see #781).I believe there is actually a simple spec. fix for this problem (referencing the ES2015 spec so things don't change out from under. Step 10.a currently is:
a. If ClassHeritageopt is present, then
the fix is:
a. If constructorParent is not the intrinsic object %FunctionPrototype%, then
Previous "fixes" tried to condition the implicit constructor choice on a null superclass value and/or other more global changes to the construction process. The new fix is a localized change that fixes the actual bug: generating a 'super()
call to %FunctionPrototype% which we know will fail because it is not a constructor. Also note that the above change is safe because:
class extends Function.prototype ()` will independently throw.The text was updated successfully, but these errors were encountered: