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

Feature request: Decorators support #104

Closed
fannheyward opened this issue May 11, 2020 · 64 comments · Fixed by #3754
Closed

Feature request: Decorators support #104

fannheyward opened this issue May 11, 2020 · 64 comments · Fixed by #3754
Labels

Comments

@fannheyward
Copy link

error: Decorators are not supported yet

Any plan to support decorators?

@Akimyou
Copy link

Akimyou commented May 12, 2020

https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/babel-preset-app#readme

Hope can support Decorators, then we can try it in vue project.

@evanw
Copy link
Owner

evanw commented May 12, 2020

The decorator spec unfortunately still seems like it's a long way off, both based on low activity and based on how many things it looks like they still have to figure out. The proposal has drifted pretty far from what the entire rest of the JavaScript ecosystem has been doing for many years. It also appears to be incompatible with a lot of the JavaScript ecosystem (e.g. no CommonJS support). So I'm not planning on supporting decorators based on the spec, at least not any time soon.

Separate from that, decorators in TypeScript have been around for a while behind the experimentalDecorators flag, and have found a lot of adoption in the web development community. I think esbuild would be useful to many more people if it had support for TypeScript-style decorators. So I'm planning to implement those at some point.

@wxs77577
Copy link

nest.js is a great web framework but it's extremely slow during compilation. There are over 20 modules in my project. :(

@evanw
Copy link
Owner

evanw commented Jun 8, 2020

An initial implementation of TypeScript decorators has been released in version 0.4.10. You can read more about this in the release notes. Please let me know if you encounter any issues.

@guoyunhe
Copy link

guoyunhe commented Jan 30, 2022

I have a JS project, not TS. When compiling decorators, it throws errors:

[vite:esbuild] Transform failed with 1 error:
/Users/guoyunhe/src/pages/aaa/components/bbb/index.jsx:13:0: error: Unexpected "@"
file: /Users/guoyunhe/src/pages/aaa/components/bbb/index.jsx:13:0

Unexpected "@"
12 |  
   |   ^
13 |  @connect(({ aaa, bbb }) => ({
   |  ^
14 |    aaa,

@evanw
Copy link
Owner

evanw commented Jan 30, 2022

Decorators are not a JS feature, so esbuild doesn't support them in JS. Nothing in the JS specification mentions decorators: https://262.ecma-international.org/12.0/. But they are a TS feature, so esbuild supports them in TS. You can tell esbuild to compile your JS as TS if you like: --loader:.jsx=tsx.

@guoyunhe
Copy link

guoyunhe commented Feb 3, 2022

Decorators are not a JS feature, so esbuild doesn't support them in JS. Nothing in the JS specification mentions decorators: https://262.ecma-international.org/12.0/. But they are a TS feature, so esbuild supports them in TS. You can tell esbuild to compile your JS as TS if you like: --loader:.jsx=tsx.

Thanks. I am now moving my project to TS and it works very well.

@UndiedGamer
Copy link

Looks like decorators but without the metadata has moved to stage 3 and i am sure typescript will implement this in a while, what are your plans for javascript decorators support, @evanw

@evanw
Copy link
Owner

evanw commented Apr 15, 2022

My plans are to implement it after it has shipped in a browser, in node, or in TypeScript. This is the same thing that I do for all other syntax features.

@rluvaton
Copy link

TypeScript implemented this on 5.0 beta

https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#decorators

@kibertoad
Copy link

@evanw 30bed2d doesn't mean that decorators are already supported? Is there something missing?

@Obiwarn
Copy link

Obiwarn commented Apr 4, 2024

The behavior of JavaScript decorators continues to be adjusted. I just became aware of this additional (potential) change: pzuraq/ecma262#12. Tracking it here as I will need to take it into consideration. See also microsoft/TypeScript#56606.

The issues linked by @evanw seem to be fixed in the meantime. Is there anything else holding back an implementation?

@ssalbdivad
Copy link

ssalbdivad commented May 3, 2024

@evanw Any updates on this? TS has been moving heavily away from legacy decorators in favor of the standard.

I've been using esbuild viatsx which has been so great in general- zero issues with source maps or transpilation. That said, the lack of decorator support alone is enough that I'd probably end up investigating other options soon if there's not a solution, which would honestly suck.

@cayter
Copy link

cayter commented May 3, 2024

@evanw Any updates on this? TS has been moving heavily away from legacy decorators in favor of the standard.

I've been using esbuild viatsx which has been so great in general- zero issues with source maps or transpilation. That said, the lack of decorator support alone is enough that I'd probably end up investigating other options soon if there's not a solution, which would honestly suck.

Our saviour has been working hard in the past 2 weeks. Let's give him some space.

https://github.com/evanw/decorator-tests

@ssalbdivad
Copy link

ssalbdivad commented May 3, 2024

@cayter Amazing, thanks for the update!

It's a fine line between highlighting the relative importance of an issue (helpful) and adding undue stress on an issue the maintainer has already prioritized or is working on (unhelpful).

I'm very sorry if my comment came across as the latter. @evanw I deeply appreciate your work and just seeing this is actively being worked on alleviates my primary concern.

@alex3683
Copy link

alex3683 commented May 3, 2024

@ssalbdivad While waiting on this to be finished I'm successfully using this vite plugin as workaround to precompile typescript: https://github.com/herberttn/vite-plugin-typescript-transform
I don't know whether you are using plain esbuild or as part of vite, so it may help or not, but maybe it helps others.

@evanw
Copy link
Owner

evanw commented May 5, 2024

I'm still making progress on this. However, progress is slow because decorators are very complicated. Some things I did recently:

@evanw
Copy link
Owner

evanw commented May 7, 2024

Ok version 0.21.0 is out and now supports the JavaScript decorators proposal. Please try it out and let me know what you think.

@justinfagnani Code size definitely isn't optimal but it shouldn't be that bad I think. I made a trade-off that generates accessor methods at run-time instead of compile-time. It would be interesting to see where esbuild's implementation ends up in your size comparison (is it public somewhere perhaps?).

@cayter
Copy link

cayter commented May 7, 2024

Ok version 0.21.0 is out and now supports the JavaScript decorators proposal. Please try it out and let me know what you think.

@justinfagnani Code size definitely isn't optimal but it shouldn't be that bad I think. I made a trade-off that generates accessor methods at run-time instead of compile-time. It would be interesting to see where esbuild's implementation ends up in your size comparison (is it public somewhere perhaps?).

This is crazy. I thought this would take few more months to ship. Thanks a lot!

Note that I couldn't get the example in the release working, have to do it like this:

function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
	const originalMethod = descriptor.value;
	descriptor.value = function (...args: any[]) {
		console.log(`before ${propertyKey}`);
		const result = originalMethod.apply(this, args);
		console.log(`after ${propertyKey}`);
		return result;
	};
}

class Foo {
	@log
	static foo() {
		console.log("in foo");
	}
}

Foo.foo();

@evanw
Copy link
Owner

evanw commented May 7, 2024

Note that I couldn't get the example in the release working

Here's an example of it working: link. That logs this when run:

before foo
in foo
after foo

@cayter
Copy link

cayter commented May 7, 2024

Note that I couldn't get the example in the release working

Here's an example of it working: link. That logs this when run:

before foo
in foo
after foo

Ah I didn't specify target. Thanks man!

@Obiwarn
Copy link

Obiwarn commented May 7, 2024

image

The grind was real.

image

Thank you so much @evanw!

I will test this thoroughly with our internal ORM.

@evanw
Copy link
Owner

evanw commented May 13, 2024

What do people think? Does it work with existing code that uses the JavaScript decorators proposal? Any feedback?

@alex3683
Copy link

alex3683 commented May 13, 2024

EDIT: Just found out you released a new version and this seems to have fixed the issue I had. So from me absolute positiv feedback, since it's also really fast!

Previous comment:

I tried it in our product but got an error with MobX and thus had to return to the transformer workaround. I then tried to make a small reproduction by using your online esbuild tranformer and putting it in a jsfiddle, but there it runs without problems. I'll just post the error and what I found out so far where it goes wrong, but I guess it's not easy to debug.

MobX just throws this: Uncaught TypeError: Cannot convert undefined or null to object (but only for us, not in the fiddle). This is in an initializer of an accessor, where this is undefined. I tried to trace the bug and how esbuild transforms the code, but I didn't really grog the flags parameter that goes in. The only thing I understand is, that when its even, this is undefined, and when it's odd, its set correctly. MobX however is called with an even flag in our production code. I tried to find out what drives the decision within esbuild, but it was too hard for me in a few hours and reverted. I can only offer you to have remote look at my code via teams or something in case you are interested. Or make adjustments that may lead to the cause of this. I guess when this is solved, I'd give you a fully positive feedback :-D

This was my reproduction attempt:

Just to clarify: This may sound like a rant, but is not meant as such. I think you are doing a great job and I assume the cause of the problem could be in our code, but it's hard to find for me and maybe solving this could provide valuable feedback.

@hrishikeshs
Copy link

Wow! I was literally trying to write a decorator yesterday to add logging to datadog to our common logger utility. Can't wait to try this out 👍 thank you so much!

@marvinruder
Copy link

marvinruder commented May 14, 2024

What do people think? Does it work with existing code that uses the JavaScript decorators proposal? Any feedback?

Works great! I was able to migrate my decorators from the legacy Typescript implementation to the TC39 proposal without problems. The only issue I encountered was that class field decorators have no access to the class itself, but this is a limitation of the specification and already discussed there. – nevermind, this is possible after the fix in 0.21.2 using this (although one needs to return a function from the decorator for this to work, in an arrow function, this is undefined).

@justinfagnani
Copy link

@evanw I tried the Lit decorators, but it looks like metadata isn't implemented yet, which is a blocker for us. I'll be able to test again when metadata support is implemented.

@evanw
Copy link
Owner

evanw commented May 15, 2024

Initial support for decorator metadata has been released in version 0.21.3.

@b3nten
Copy link

b3nten commented May 15, 2024

Evan you rock!

@justinfagnani
Copy link

Awesome @evanw!

I ran all of Lit's decorator tests after an esbuild compile and they all pass! I'll check those tests in so if you ever want to check changes against them you can do:

git clone https://github.com/lit/lit.git
cd lit
npm ci
npm link esbuild
npm run test:dev -w @lit/reactive-element

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

Successfully merging a pull request may close this issue.