Description
Is subclassing supposed to work?
class SpamStream extends ReadableStream {
constructor() {
let stream;
super({
pull(controller) {
controller.enqueue("spam");
stream.spamCount++;
}
});
this.spamCount = 0;
stream = this;
}
hasSpammed() { return this.spamCount > 0; }
}
new SpamStream().hasSpammed()
The standard currently says:
We prefix section headings with
new
to indicate they are defining constructors; when doing so, we assume that NewTarget will be checked before the algorithm starts.
What it doesn't say is how this gets initialized. Mozilla's current implementation ignores NewTarget and always creates an object whose [[Prototype]] is the original value of ReadableStream.prototype. So the above code would fail; hasSpammed
would not be on that object's prototype chain.
I think we want something like
- If NewTarget is undefined, throw a TypeError exception.
- Let this be ? OrdinaryCreateFromConstructor(NewTarget, the name of the per-realm intrinsic object that is this class's original prototype, the List of this class's internal slots).
(Technically, this doesn't quite work, because OrdinaryCreateFromConstructor step 1 effectively asserts that it is being called from inside ECMA-262 and not from other standards. But I think it's an improvement anyway.)