archives

« Bugzilla Issues Index

#4429 — 14.5.14 invalid default constructor for class extends null


The spec says that

class Foo extends null {}

sets Foo.[[Prototype]] to %FunctionPrototype% and defines the default constructor body as: constructor(...args) {super(...args);}

This causes a runtime error for
new Foo
because %FunctionPrototype% is not a constructor

The problem is in line 10.a where the test
if ClassHeritage-opt is present, then

is such to determine the default constructor body. Instead the 10.a test should be
if ClassHeritage-opt is present and SameValue(constructorParent,%FunctionProtoype) is false, then


(thanks to Brian Terlson for spotting the problem)


Does that mean the resolution from [1] is going to be revised?

[1] https://github.com/rwaldron/tc39-notes/blob/master/es6/2015-01/jan-27.md#conclusionresolution-2


(In reply to André Bargull from comment #1)
> Does that mean the resolution from [1] is going to be revised?
>
> [1]
> https://github.com/rwaldron/tc39-notes/blob/master/es6/2015-01/jan-27.
> md#conclusionresolution-2

It seems that it must.

Unfortunately, the resolution described there (which is what is in the ES2015 spec) just doesn't work for:

new class extends null {}

Because %FunctionPrototype% is not a constructor and hence the `super(...args)` call in the default constructor body will fail when it does %FunctionPrototype%.[[Construct]]()


(In reply to Allen Wirfs-Brock from comment #2)
> Unfortunately, the resolution described there (which is what is in the
> ES2015 spec) just doesn't work for:
>
> new class extends null {}
>
> Because %FunctionPrototype% is not a constructor and hence the
> `super(...args)` call in the default constructor body will fail when it does
> %FunctionPrototype%.[[Construct]]()


Erik Arvidsson (cc-ed) already described that issue during the meeting:

> EA: If you have an extends clause, the default constructor calls super. If the
> extends expression evaluates to null then the super() call will throw. So you
> have to provide your own constructor


(In reply to Allen Wirfs-Brock from comment #0)
> The spec says that
>
> class Foo extends null {}
>
> sets Foo.[[Prototype]] to %FunctionPrototype% and defines the default
> constructor body as: constructor(...args) {super(...args);}
>
> This causes a runtime error for
> new Foo
> because %FunctionPrototype% is not a constructor
>
> The problem is in line 10.a where the test
> if ClassHeritage-opt is present, then
>
> is such to determine the default constructor body. Instead the 10.a test
> should be
> if ClassHeritage-opt is present and
> SameValue(constructorParent,%FunctionProtoype) is false, then
>
>
> (thanks to Brian Terlson for spotting the problem)

In addition, step 15 needs to also add a
and SameValue(constructorParent,%FunctionProtoype) is false
clause to its predicate


It was actually discovered here: https://github.com/Microsoft/TypeScript/issues/3696.

I think it's clear that `extends null` shouldn't need to provide its own constructor to avoid errors. From the notes it seems like Erik raised the concern and it was not addressed at all. Maybe no one realized the severity of the issue? Or maybe I'm overlooking why Allen's proposed solution is a bad idea.