-
Notifications
You must be signed in to change notification settings - Fork 795
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: custom decorators are not invoked for state properties #3831
Comments
Hello @jgroth, thanks for filing the issue and for providing a reproduction case! I just checked this out and was able to confirm that this is an issue, custom decorators worked great in 2.18.x but the 2.19.0 release broke them because of this change: #3614 In short, in order to support emitting ES2022+ we needed to change some parts of how we support the built-in Stencil decorators, and unfortunately due to some oversight on our part that change stepped on custom decorator support. This is a problem we plan to fix, and something the team is actively looking into. I'm going to label this so we can ingest it into our internal backlog and prioritize it going forward. Thanks again for filing the issue, and stay tuned for updates soon! |
Thanks for the quick reply! Any estimate on a timeline when it might be fixed? class MyComponent {
@State()
@SelectCurrentUser()
private currentUser: User;
} |
@jgroth ah sorry that it broke a common pattern you all are using. Part of the sticky bit with this issue is that we need to do some discovery work to figure out exactly the right way to address this — this doesn't mean that it will take eons to address, but just that at present I don't have a clear roadmap of exactly how we'll fix it in my head, so I can't commit to a specific timeline at present. However! That said, the ticket for doing this work has been pulled in to our next sprint, so we will start work on it relatively soon. |
Hello @alicewriteswrongs, thanks for your attention in this subject. |
Hey @Dayvisson, thanks for following up on this and keeping the fire burning here. We're currently doing the discovery / research work I mentioned about about how Stencil should handle decorators going forward. The recent inclusion of ECMAScript standard-compliant decorators in TypeScript 5.0 has increased the urgency of addressing this, as we need to determine how we can 1) support upgrading to TypeScript 5.0 2) support Stencil's current built-in decorator behavior and 3) support user-defined custom decorators. The wrinkle is that Stencil's built-in decorators are essentially implemented using custom TypeScript transformers (transformations on the TypeScript syntax tree that run during the compilation process) and they aren't directly compatible with either the decorators that TS developers have been able to use for a few years with the So we're evaluating what to do here. Once we have a firmer idea of what we think the right path forward is here I will make sure to get your feedback on it, as we do want to make sure that using custom decorators is supported in Stencil in a way that jibes with the community's existing workflows. Thanks again for pinging, and apologies that this has been open a while! |
Any updates on this? 🙂 |
Hey @jgroth unfortunately I don't have anything specific to share at present as far as a timeline for addressing this or more on our specific thinking on how to allow for custom decorators in Stencil going forward. At present the loose plan is to refactor how Stencil's current decorators are implemented by the Stencil compiler, basically re-implementing them as standards-compliant decorators which can be used without any custom compiler support (or possibly with more minimal support than is needed right now). That rough idea hasn't really been proven out yet though, so definitely subject to change. Right now I can also say we're close to clearing a few big things off of our plates which will free us up to look at the decorator issue more closely in general. I know it's been a while without any updates, but we do still want to support custom decorators! |
This is honestly a mess. I was going to try and see if we could update our code to use the new decorator syntax from TypeScript 5, but that does not seem to be supported either. The code does compile even if VSCode gives a lot of errors and complains about the Stencil decorators when I remove |
The issues impacts both stencil/src/compiler/transformers/decorators-to-static/convert-decorators.ts Lines 356 to 372 in a1ab21b
And stencil/src/compiler/transformers/decorators-to-static/convert-decorators.ts Lines 190 to 197 in a1ab21b
Essentially, when Stencil found out a Prop or State decorator, it removes it from the class members declarations, and instead declare it in the constructor. This has the adverse effect of removing all decorators, including the customs one. I think stencil/src/compiler/transformers/decorators-to-static/convert-decorators.ts Lines 199 to 207 in a1ab21b
After that, instead of passing the filteredMembers to I'll open a PR later today/this week to proposes theses changes after running more tests |
Hey @louis-bompart, thanks for investigating this a bit more! It's a bit of a tricky situation with decorators in Stencil at present. One of the limitations that we have here which makes the situation for custom decorators unfortunate at the moment is that for fields which are decorated with That runtime bit happens here in the stencil/src/runtime/proxy-component.ts Lines 32 to 83 in 9a92ad1
You can see that the function loops through the component's members and uses The problem here is that if you want to use You can try this for yourself by running the following code: const defineFoo = (klass) => {
Object.defineProperty(klass.prototype, "foo", {
get() {
return "defined by `Object.defineProperty`!"
}
})
}
class WithProp {
foo;
}
class WithoutProp {}
defineFoo(WithProp);
defineFoo(WithoutProp);
let withProp = new WithProp();
let withoutProp = new WithoutProp();
console.log("withProp:", withProp.foo);
console.log("withoutProp:", withoutProp.foo); Because the This unfortunately means we cannot allow props like I know that's kind of a lot so let me know if that doesn't make sense! But that's why, pending a larger refactor, we unfortunately at present cannot support custom decorators and why the change you proposed ends up breaking the The team does want to fix this and we are planning to do an overhaul of how Stencil's decorators are implemented to get them to a place where they can happily coexist with custom user-defined decorators but we just aren't there yet. I know this isn't a great answer to hear, but that's the state of the project right now. Hopefully that all helps clarify some of what's going on here, and why for now we unfortunately need to remove fields from the class declaration if they are decorated with a Stencil decorator. |
Hey @alicewriteswrongs thanks for the detailed answer, that's much appreciated. I replicated your test with a Moreover, I know we have an extensive E2E test suite in our component library, and if the tests pass with this patch, it may indicate we have a gap in our tests, and I would very much like to patch this hole 😅 |
aha well as always I did forget one detail! In order to get TypeScript to emit fields like class Foo {
foo = "bar";
} You need to have the With those two options, if we leave |
Ah, gotcha thanks! I reproduced the issue ✅ Now, pretty sure you must have seen it coming but then, assuming we want to fix the custom decorators without embarking on the big overhaul, how about disallowing this typescript option? That would not be a first I reckon, and would alleviate the issues about custom decorators. What do you think? |
Those are indeed viable options for getting custom decorators to work again in Stencil given where the project is at now. The Stencil team has evaluated both options (disallowing Right now we think the "right way" is to migrate Stencil's decorators over from the compile-time constructs they are right now to be actual, standards-compliant decorator functions exported by the Now that ECMAScript decorators as standardized by the TC39 are being implemented in TypeScript we have the pieces in place to do this work as far as Stencil's external dependencies are concerned, and further investigation and experimentation in this regard is on the team's roadmap. At present I can't share an exact timeline for when that will be, but this problem is a priority for us and something we definitely, 100% plan to fix. I know that's disappointing if you're trying to use custom decorators right now in a Stencil project, but we're in a bit of a difficult spot right now. Custom decorators used to work in Stencil somewhat by accident until TypeScript started emitting different code with |
Thanks for the transparency on the question, that's really appreciated. I understand the decision, it's definitely the best for the long term 💯. One final thing, can we expect the move from the experimental decorator to the TC39 decorator to be part of a major release of Stencil? |
Yeah I think you're right on that point, we'll need to basically convert over 100% because supporting, in an ongoing way, a mix of transformer-implemented decorators (what we have now) and what I call "TypeScript decorators" (basically decorator functions as enabled by the |
I am experimenting with integration of Preact signals into Stenciljs, just for fun: https://github.com/RunOpenCode/stencil-signal This could be interesting if allowed:
Why? Well, I could just modify prop and set get/set for it to write value into signal. Than, this signal can be detected as dependency of computed and effect under the hood, in example:
Or even better, if used standard TC39 decorator - I could expand its behaviour and have only one decorator for signaling prop. |
Hi, @alicewriteswrongs 👋 I noticed that some Issues and PR are starting to get tagged with the Stencil v5 label. To chime in on what kind of decorators to support for the upcoming versions, ECMA-compliant decorators are not yet the way to go (sadly). While the https://github.com/tc39/proposal-decorators progressed in February, it didn't reach Stage 4. Even if it were to achieve it shortly, it would take several years for the feature to be considered Widely Available by Baseline standard. So the three choices left, I think, are:
Even if I dislike the last option, I think this issue should strive toward a conclusion and not live on after the release of Stencil v5. The gain in insight for the users is still a boon and would prevent user errors. |
Sorry if I am missing something, but how is that an issue for a compiler-based framework like Stencil? TypeScript already supports the new decorators standart and can emit code with the necessary polyfills: If Stencil is to add support for decorators, it should be the new spec, rather than the older, experimental decorators that, while had some DX advantages, may be deprecated in a future TS version. |
Both approaches have their pros and cons. One of the cons I see with the new spec is that it is sadly not mature yet, as the recent and substantial changes show tc39/proposal-decorators@c39254c...a81149f. However, recent developments happened on this spec's implementation side. For example, the Chromium bug has been assigned on February 7th, and some prototyping was done last month. I don't have a strong opinion on any options. However, it would be healthy to have a decision taken on the matter, even the 'no support' one, for the upcoming major release, as it 'solves' how Stencil's users should do things moving forward in the medium or even long term. |
@louis-bompart @maxpatiiuk definitely agree it is a good idea to resolve a way forward of some kind for this issue. While we aren't ready to put something out about it yet the team has been doing a good deal of internal investigation and experimentation on this front. We will have something to share soon! |
We have thousands of unique web applications that rely heavily on custom decorators. Upgrading to the latest version of Stencil is a priority for us due to its new features and improvements. However, the lack of support for custom decorators is a significant blocker. Could you please share your plans regarding custom decorators? Will support for them be reintroduced in future releases? Alternatively, should we consider other solutions and start working towards removing our decorators, which we would prefer to avoid as they greatly simplify our applications? |
Prerequisites
Stencil Version
2.19.0
Current Behavior
If a property is decorated with both
@State
and another decorator, the code for the other decorator will never be invoked.In the following component nothing will be logged to the console with Stencil
2.19.0
. It works perfectly in2.18.1
. Probably introduced in #3614After inspecting the compiled javascript files, the TypeScript
__decorate
helper function is missing for the component in2.19.0
, and is present in2.18.1
Expected Behavior
Decorators added to properties also decorated with
@State
should be invokedSteps to Reproduce
Create a new component with a property decorated with both
@State
and something else. The other decorator will not workCode Reproduction URL
https://github.com/jgroth/stencil-decorator-bug
Additional Information
No response
The text was updated successfully, but these errors were encountered: