Skip to content

fix(transformer/typescript): parameter property assignments before conditional super() - #20529

Open
lenstr wants to merge 1 commit into
oxc-project:mainfrom
lenstr:fix/transformer-parameter-property-conditional-super
Open

fix(transformer/typescript): parameter property assignments before conditional super()#20529
lenstr wants to merge 1 commit into
oxc-project:mainfrom
lenstr:fix/transformer-parameter-property-conditional-super

Conversation

@lenstr

@lenstr lenstr commented Mar 19, 2026

Copy link
Copy Markdown

Closes #20527

get_super_call_position only looked for super() as a direct top-level ExpressionStatement. When super() was inside an if/else or switch, it was not found, so parameter property assignments (this.x = x) were inserted at position 0 — before super(). This causes a runtime ReferenceError.

The fix makes get_super_call_position walk into top-level control flow statements (if, switch, try, labeled, blocks) to find the containing statement, and inserts assignments after it.

@github-actions github-actions Bot added A-transformer Area - Transformer / Transpiler C-bug Category - Bug labels Mar 19, 2026
@lenstr
lenstr force-pushed the fix/transformer-parameter-property-conditional-super branch from bfda110 to e2ca96f Compare March 19, 2026 22:09

fn statement_contains_super_call(stmt: &Statement<'a>) -> bool {
match stmt {
Statement::ExpressionStatement(stmt) => stmt.expression.is_super_call_expression(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Statement::ExpressionStatement(stmt) => stmt.expression.is_super_call_expression(),
Statement::ExpressionStatement(stmt) => match &stmt.expression {
Expression::SequenceExpression(seq) => {
seq.expressions.iter().any(Expression::is_super_call_expression)
}
expr => expr.is_super_call_expression(),
},

Thanks for working on this! I hit a closely related case that this PR doesn't cover yet (super() inside a SequenceExpression).

@babel/plugin-proposal-decorators generates code like this:

export class A extends B {
    constructor(private s: any) { super(), initExtra(this); }
    x = init(this, 1);
}

Output (both with current main and with this PR applied):

export class A extends B {
      constructor(s) {
              this.s = s;
              this.x = init(this, 1);
              super(), initExtra(this);
      }
      x;
}

The ExpressionStatement branch of the new statement_contains_super_call only matches when the expression is the super call, so the sequence expression falls through and the assignments get inserted at position 0.

Here as test case:

class MyError3 extends Error {
  constructor(
    public code: string,
  ) {
    super(code), init(this);
  }
}
// to
class MyError3 extends Error {
  constructor(code) {
    super(code), init(this);
    this.code = code;
  }
}

Would you mind including this in this PR?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. super() inside a sequence expression is now detected, so parameter-property assignments are emitted after the complete expression statement. Added the suggested regression case; the focused conformance test passes.

@camc314 camc314 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you run just coverage?

I would expect

* class/parameter-properties-late-super/input.ts
x Output mismatch
to be fixed, if it's not, I don't think this is a full fix

@lenstr
lenstr force-pushed the fix/transformer-parameter-property-conditional-super branch from e2ca96f to 83da050 Compare July 26, 2026 21:04
@lenstr

lenstr commented Jul 26, 2026

Copy link
Copy Markdown
Author

@camc314 Ran just coverage. parameter-properties-late-super now emits the assignments immediately after super() in both if/else branches.

@lenstr
lenstr force-pushed the fix/transformer-parameter-property-conditional-super branch from 83da050 to 600474d Compare July 26, 2026 21:30
…nditional super()

When `super()` is inside a top-level control flow statement (if/else,
switch, try, labeled), parameter property assignments were inserted at
the start of the constructor body — before `super()`.

Fixes oxc-project#20527

Amp-Thread-ID: https://ampcode.com/threads/T-019f9fdf-7db3-700c-a022-472ecfe7119d
@lenstr
lenstr force-pushed the fix/transformer-parameter-property-conditional-super branch from 600474d to 4a253d0 Compare July 26, 2026 21:48
@lenstr

lenstr commented Jul 26, 2026

Copy link
Copy Markdown
Author

@camc314 I initially misunderstood your point: you expected the fixture itself to be removed from the coverage failures, not just the assignment placement to be fixed. I added the standard Oxc override for the intentional p; field output. class/parameter-properties-late-super now passes, has been removed from babel.snap.md, and just coverage passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-transformer Area - Transformer / Transpiler C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

transformer: parameter property assignments inserted before conditional super()

3 participants