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

Reference to self within decorated class refers to undecorated class #3968

Open
bawjensen opened this issue Nov 7, 2024 · 1 comment
Open

Comments

@bawjensen
Copy link

TL;DR: Should a decorated class referencing itself in a method refer to the decorated class or undecorated? Currently it does the latter - which feels broken, but admittedly that may just be due to quirky code patterns.

To be honest, despite having done my best to read the proposal and spec, I cannot be certain whether esbuild is behaving incorrectly in this matter. However, I could not be certain that esbuild is deliberate in its current behavior since I could not spot a relevant case in the tests (https://github.com/evanw/decorator-tests/blob/main/decorator-tests.ts). The only case(s) that seemed similar also seemed distinct enough to not quite be relevant (i.e. the complexities involved with things like accessor might mean it's irrelevant to my simpler situation).

esbuild.github.io/try link

Running the built code via node (20.12.1 in case it matters) results in

[class Bar] { [Symbol(Symbol.metadata)]: [Object: null prototype] {} }
[class Foo]

Notably, if I change one line near the bottom to var _Foo = class _FooInner { (so as to not reuse the _Foo identifier for the class expression itself), then I get the result I had expected:

[class Bar] { [Symbol(Symbol.metadata)]: [Object: null prototype] {} }
[class Bar] { [Symbol(Symbol.metadata)]: [Object: null prototype] {} }
@hyrious
Copy link

hyrious commented Nov 7, 2024

I think it should be the latter case which seems more expected if you "desugar" the decorator:

class A {
  f() { return A }
}

const foo = x => class B {
  f() { return new x().f() }
}

// unlike `function A` which behaves like `var A` (with a bit different),
// `class A` behaves like `let A = class A` which means it could be reassigned.
A = foo(A)

console.log(A)
console.log(new A().f())

Outputs:

[class B]
[class A]

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

No branches or pull requests

2 participants