Skip to content
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

Double Emit of Contructor when using Getter Decorators #53448

Closed
Matchlighter opened this issue Mar 23, 2023 · 1 comment · Fixed by #53547
Closed

Double Emit of Contructor when using Getter Decorators #53448

Matchlighter opened this issue Mar 23, 2023 · 1 comment · Fixed by #53547
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@Matchlighter
Copy link

Matchlighter commented Mar 23, 2023

Bug Report

With the implementation of Stage 3 Decorators in TS 5, using a getter decorator can result in the content of the constructor being duplicated in the emitted code, for example:

            constructor() {
                this.computedVal;
                console.log("As will this");
                __runInitializers(this, _instanceExtraInitializers);
                this.computedVal;
                console.log("As will this");
            }

🔎 Search Terms

Constructor duplicate decorators getter

🕗 Version & Regression Information

Started seeing this when I updated a library from TS 5.0-beta to TS 5.0.2.

This changed between versions 5.0-beta and 5.0.2. Not applicable to prior versions.

⏯ Playground Link

Playground link with relevant code

💻 Code

function computed(target, ctx: ClassGetterDecoratorContext) {
    ctx.addInitializer(function () {
        console.log("INIT")
    })
    return target
}

class Bla {
    // Things seem to work as expected if a field or accessor is also defined,
    //   but additional getters/setters or methods continue to see the double emission
    // name: string = ""

    @computed
    get computedVal() {
        console.log("This will print twice")
        return 3
    }

    constructor() {
        this.computedVal
        console.log("As will this")
    }
}

new Bla()

🙁 Actual behavior

Constructor logic is duplicated:

            constructor() {
                this.computedVal;
                console.log("As will this");
                __runInitializers(this, _instanceExtraInitializers);
                this.computedVal;
                console.log("As will this");
            }

🙂 Expected behavior

Constructor logic should not be duplicated:

            constructor() {
                __runInitializers(this, _instanceExtraInitializers);
                this.computedVal;
                console.log("As will this");
            }
@rbuckton
Copy link
Member

The underlying issue is that the logic to inject __runInitializers() into a constructor incorrectly called addRange/visitNodes twice when a super() wasn't present. This only occurred for getters, setters, and methods because __runInitializers() is injected into the constructor when there are no fields present, but is injected into the first field initializer when fields are present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants