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

[Bug] 2022-03 decorator initialise class instance in wrong order #9669

Open
jzhan-canva opened this issue Oct 22, 2024 · 3 comments
Open

[Bug] 2022-03 decorator initialise class instance in wrong order #9669

jzhan-canva opened this issue Oct 22, 2024 · 3 comments
Labels
Milestone

Comments

@jzhan-canva
Copy link
Contributor

jzhan-canva commented Oct 22, 2024

Describe the bug

As per tc39/proposal-decorators [Adding initialization logic with addInitializer]
Method and Getter/Setter decorators should be initialised before any class fields are initialised

Input code

const myDecorator = (value, context) => {
  context.addInitializer(() => {
    console.log("init")
  })
  return value
}

class A {
  value = this.getNumber();
  value2 = this.getNumber();
  
  @myDecorator
  getNumber() {
    console.log("getNumber")
    return 1
  }
}

const a = new A()

Config

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "decorators": true,
      "tsx": true
    },
    "transform": {
      "decoratorVersion": "2022-03"
    },
    "target": "es2021",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    }
  },
  "module": {
    "type": "es6"
  },
  "minify": false,
  "isModule": true
}

Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.7.39&code=H4sIAAAAAAAAA3WQzwrCMAzG732KsFMLMtCrTBx48eI71C7MQtdCm%2FmXvbtdYGUHhRBIvi%2FJj5jgE8HwOqEJUVOI0IC8azfiBkzwhE9S0BzgI2Cpa911Z2%2FJamffGKUsBrak4LB2oZeVzaZK5f40p4g0Rg%2B8W0xCGKdTgpYHuZkv082muke6jMM1b1b7Rdv9EXMcV%2FC5XBl%2BMRWZwQrVdqZkKv6Hzuc8PqCV6gsyc1fOIQEAAA%3D%3D&config=H4sIAAAAAAAAA1VQQQ6DMAy78wqU8yYxJu2wP%2By6ewUBdaJNlRRpCPH3tVA6uCW2E1uei7KEjzTwLOcwhsUpFuS8B0Qm69U3IOAnh9Kwdh4uO9tiQ6w8sQSF5xEz4%2BWboBVZNgI8KysdsTl65C9vZNFko1td1fW1usP5WnGPPtIoQXBLQWAgEgxwpwZJEcBoq7vpaNOQcYwiZ2GUKtsP%2BX5zLJIrGGrHlUwVxRq2BA%2F4i3az%2FBi0vPbLtYXlByFGoz9uAQAA

SWC Info output

No response

Expected behavior

When I run output code, I should see console log

init
getNumber
getNumber

This is tsc playground link, and if I run the output code, it's as expected
image

Actual behavior

Wehn I run output code, I see console log

getNumber
getNumber
init

image

Version

1.7.39

Additional context

No response

@magic-akari
Copy link
Member

Investigating

The current implementation of the constructor is as follows:

constructor() {
    _define_property(this, "value", this.getNumber());
    _define_property(this, "value2", this.getNumber());
    _initProto(this);
}

Problem: The order of operations is incorrect. The _initProto function should be called at the top of the constructor to ensure proper prototype initialization before any instance properties are assigned.

Our inject_after_super functionality is working as intended. However, the decorator pass executes first, leading to the following transformation:

constructor() {
    _initProto(this);
}
value = this.getNumber();
value2 = this.getNumber();

And during the ES2022 pass, class fields are inserted into the constructor before the _initProto call, resulting in the undesired behavior.

@magic-akari
Copy link
Member

Possible Solution

Insert initProto in the class field instead.

class A {
  #_ = _initProto(this);
  value = this.getNumber();
  value2 = this.getNumber();
}

@kdy1 kdy1 added this to the Planned milestone Oct 25, 2024
@jzhan-canva
Copy link
Contributor Author

have a solution
check if this is used in any filed initialisation, find the first one, for example value = this.getNumber()
if found: replace this with _initProto(this) (make sure _initProto returns this), so the code will become value =(_initProto(this)).getNumber()
if not found: use inject_after_super

then run es2022 pass as usual

I will try create a pr

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

No branches or pull requests

6 participants
@magic-akari @jzhan-canva @kdy1 and others