tc39 / proposal-rm-builtin-subclassing

Remove ES6 built-in subclassing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clarify or fix derived class constructors in the examples

jandem opened this issue · comments

In the type II and IV examples, the constructor must call super() or an exception will be thrown when returning from the constructor.

Or maybe I'm missing the point of the // intentionally empty constructor, not calling super(); comments?

Yeah, I wondered about those too. I think the goal was rather to avoid overriding constructor at all?

Ah hm, yeah those are indeed wrong. I think @domenic's original suggestion here I think was to highlight that allowing everything to be a virtual functions like "exec" isn't particularly useful even in the context of subclassing: it's overly generic. That is, you can "subclass" a RegExp without going through RegExp's constructor logic that installs the necessary internal fields, and still override "exec". Upshot is, it seems exceedingly unlikely anyone actually wants to do that. Ditto for other constructor with this genericity like Promise.

A more correct example might be manual/ES5-era "subclassing" of built-ins, like

function MyRegExp() { }
Object.setPrototypeOf(MyRegExp, RegExp);
Object.setPrototypeOf(MyRegExp.prototype, RegExp.prototype);
MyRegExp.prototype.exec = function myExec() { };

Ah, nope, it's worse:

function R() { }
Object.setPrototypeOf(R, RegExp);
Object.setPrototypeOf(R.prototype, RegExp.prototype);
R.prototype.exec = function() { console.log("overridden"); return null; };
// Define a new .global because RegExp#global will throw on non-RegExp-branded objects
Object.defineProperty(R.prototype, "global", { value: false });
console.log("some string".match(new R("foo")))     // "overridden"

The basic question is basically: like, why support this level of genericity in built-ins?

Type II was supposed to call super(); something got lost in translation I think.

For type IV, I was always under the impression that the reason RegExp was so generic was so that you could subclass it without calling super(). If that's not true, and the subclassing has to be done using super-esoteric methods, then that's even weirder...

Maybe return {} as a constructor body was what the designers of RegExp's excessive genericity had in mind?

Maybe return {} as a constructor body was what the designers of RegExp's excessive genericity had in mind?

That's also weird, because while that gets around the TypeError arising from not calling super(), you'd end up creating a object literal without the subclass's overrides.

I certainly don't know what the original spec authors had in mind. I can see an argument for @@match and friends, since they form a protocol for RegExp-likes.

But "exec" and "flags" being treated as virtual by all the built-in RegExp methods is just weird.

@syg This may be a tangent, but I agree completely about RegExps. I kind of wonder if we could fix just that part, even if we can't get consensus on the rest of this proposal. See the notes from when I previously presented this. (Note, Allen and I never got around to making the tweaks we said we would.)

I kind of wonder if we could fix just that part, even if we can't get consensus on the rest of this proposal.

Yep, that's been brought up several times. I am happy to split Type IV off if there's a lot of resistance to Type II and III but not IV. That said, I'd like to seek consensus for the high-risk high-reward combination of all three types first.