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

fix: runtime decorators #6076

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

johnjenkins
Copy link
Contributor

@johnjenkins johnjenkins commented Dec 7, 2024

With the introduction of #3614, Stencil started removing @State / @Prop class fields during transpilation only to re-add them later, during bundling, as constructor initialised values.

This was due to a new behaviour with JS classes, given tsconfig:

target: 'es2022'

A typical Stencil component:

@Component({
  tag: 'cmp-a'
})
export class MyComponent {
  @Prop() prop1 = 'value1';
}

Compiled output went from:

class MyComponent {
   constructor() {
     this.prop1 = 'value1';
  }
}

to:

class MyComponent {
  prop1 = 'value1';
  // ^^ statically initialised, class fields override Stencil's accessors originally set on the prototype...
  // no-more keeping Element / class instance in-sync. No-more re-renders :(( 

 // ** Stencil, therefore started stripping them out then
// re-adding them to the CTOR like the good old days **
}

A side-effect this behaviour is user-defined, run-time decorators targeting @State / @Prop would be stripped out during transpilation and break expected behaviour.

Within the attached issue, the Stencil dev (at-the-time) outlined the reason for the broken behaviour and also stated their reticence to fix it; a preference to move away from Stencil's statically-analysed decorators for real-life, run-time decorators. Getting class fields working again within Stencil would just be layering-on more tech-debt when the ultimate goal should be to remove it.

Whilst I am completely on-board with the dev's reasoning - the more magic that Stencil can remove, the more Stencil can 'get-out-of-the-way' of native behaviour and expectations - the better. However, I also believe:

  1. Something popularly used by the user community probably shouldn't be broken for over 2 years
  2. Messing around with the compiler's default output is Stencil 'getting-in-the-way'
  3. The undertaking to re-write Stencil - transitioning to run-time decorators whilst taking into account experimentalDecorators and / or the not-yet supported ECMA compliant decorators - will not be small and will take time.

What is the current behavior?

GitHub Issue Number: #3831

What is the new behavior?

Fixes #3831

  • Re-allows Stencil decorated class members (thank you @louis-bompart ! - fix(decorator): preserve stencil decorated class members #4772 ) to flow through transpilation and stops their re-addition during bundling.
  • Re-wires the @State / @Prop decorated fields with the original Stencil get / set during run-time only if it finds modern class static initialisers (during build time we detect them and switch on a new modernPropertyDecls build flag)

Documentation

Does this introduce a breaking change?

  • Yes
  • No

Testing

  • New unit tests for the addition of a new build time flag modernPropertyDecls
  • New component tests for target: "es2022" combined with dist, dist-custom-elements and run-time decorators

Other information

@johnjenkins johnjenkins requested a review from a team as a code owner December 7, 2024 01:42
@johnjenkins johnjenkins marked this pull request as draft December 7, 2024 01:42
@johnjenkins johnjenkins marked this pull request as ready for review December 14, 2024 01:08
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

Successfully merging this pull request may close these issues.

bug: custom decorators are not invoked for state properties
1 participant