Skip to content

Constructor specification is unclear #965

Closed
@jorendorff

Description

@jorendorff

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

  1. If NewTarget is undefined, throw a TypeError exception.
  2. 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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions