fix(transformer/decorator): transformed decorators should be injected after class-properties has run#12418
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
CodSpeed Instrumentation Performance ReportMerging #12418 will not alter performanceComparing Summary
|
6151a37 to
01c7eb0
Compare
44a1c97 to
5ebd4b0
Compare
01c7eb0 to
479484a
Compare
5ebd4b0 to
c4a2d79
Compare
479484a to
d7a33a2
Compare
d7a33a2 to
0feb179
Compare
|
@Dunqing I've amended the diff in PR description. Before the diff showed no change. I think what I've changed it to is what you were intending to say, but can you please check my change and confirm? |
Thanks! Yes, it is good now. |
overlookmotel
left a comment
There was a problem hiding this comment.
It feels a bit hacky to have 2 exit_class methods for the same transform, but I see why it's necessary.
The interaction between TS, decorators, and class props transforms feels a bit fragile, but I'm not sure how to improve it...
Merge activity
|
… after class-properties has run (#12418) * close rolldown/rolldown#5374 Example: Input: ```ts function myPropertyDecorator() { return (target: any, propertyKey: number) => { console.log(target.constructor.modelName, propertyKey); }; } class Test { public static modelName = 'Test'; @myPropertyDecorator() public myProperty = 1; } const instance = new Test(); export default instance; ``` Output diff: ```diff function myPropertyDecorator() { return (target, propertyKey) => { console.log(target.constructor.modelName, propertyKey); }; } class Test { constructor() { babelHelpers.defineProperty(this, "myProperty", 1); } } -babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0); -babelHelpers.defineProperty(Test, "modelName", "Test"); +babelHelpers.defineProperty(Test, "modelName", "Test"); +babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0); const instance = new Test(); export default instance; ``` The cause is that we transform class fields and decorators in two different plugins, and the decorator plugin should be transformed first, and then run the class-properties plugin, because class-properties might erase some decorator information. However, this cause transformed decorators injected before transformed class fields. This PR fixes this problem by collecting all transformed decorators that wait for injection, and injecting them in batch after the `class-properties` plugin has run.
0feb179 to
986c48e
Compare
Yes, I am either. Dealing with decorators around these three plugins is quite error-prone. I would consider your suggestion to add more tests that enable these three plugins. |

Example:
Input:
Output diff:
function myPropertyDecorator() { return (target, propertyKey) => { console.log(target.constructor.modelName, propertyKey); }; } class Test { constructor() { babelHelpers.defineProperty(this, "myProperty", 1); } } -babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0); -babelHelpers.defineProperty(Test, "modelName", "Test"); +babelHelpers.defineProperty(Test, "modelName", "Test"); +babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0); const instance = new Test(); export default instance;The cause is that we transform class fields and decorators in two different plugins, and the decorator plugin should be transformed first, and then run the class-properties plugin, because class-properties might erase some decorator information. However, this cause transformed decorators injected before transformed class fields.
This PR fixes this problem by collecting all transformed decorators that wait for injection, and injecting them in batch after the
class-propertiesplugin has run.