lit-element: Decorators currently don't work with Babel
May be related to #205.
Essentially, given:
@property({ type: String })
prop = 'foo';
Babel configured with:
It seems that one of the two results in this babel helper overwriting our property descriptor, so we lose the getter/setter and lit no longer is aware of changes.
I don’t think it is a lit bug but it is something we need to track. I’m not sure which of the two babel plugins causes this as it needs a little more investigation (it looks to be used in the decorators plugin but specifically for class properties).
edit:
after further investigation it does look like #205, because it will return decorator(...) || descriptor. meaning as long as we return, it will be fixed.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 5
- Comments: 28 (7 by maintainers)
Here’s the solution (after wasting hours on this):
In your babel config, set
decoratorsBeforeExport: trueOr just calling
this.requestUpdate(). But again, that entirely beats the purpose of using the decoratorThere’s two issues here with babel’s output in reality. #206 doesn’t seem to fix it…
I was asking how to do it in general, but now I also inspected lit-element’s:
After doing some research these past few days, it turns out there’s actually not just two, but six configurations that decorator authors should ensure their decorators work in:
experimentalDecoratorswithuseDefineForClassFieldsset tofalseexperimentalDecoratorswithuseDefineForClassFieldsset totruelooseset totrueand proposal-decoratorslegacyset totruelooseset totrueand proposal-decoratorslegacyset tofalse(since Babel 7.1)looseset tofalseand proposal-decoratorslegacyset totruelooseset tofalseand proposal-decoratorslegacyset tofalse(since Babel 7.1)I started writing a list of differences between Babel and TypeScript legacy decorators at https://github.com/babel/babel/issues/8864#issuecomment-688535867. If you know any more details to add, please do comment there.
I do see lit-element’s decorators support both legacy and newer decorators (“newer” because there’s even newer decorators that no tools support yet and plus the proposal has been put on pause in order to come up with a fourth form of decorators), but I haven’t specifically tested it in all 6 of the above scenarios.
From a quick glance at
https://github.com/Polymer/lit-element/blob/2de92b532b8adad540b91f208063b2e15777029f/src/lib/updating-element.ts#L313-L334
it seems that lit-element decorators may fail in scenario 2, and possibly also in 5 and 6 because I think
loose: falseis basically equivalent to TypeScript’suseDefineForClassFields: true, so the decorator accessors get overridden by new property descriptors onthis(a.k.a. [[Define]] semantics).Did I overlook if lit-element has an alternative for that case?
Lit-element’s decorators don’t return anything, so they won’t run into the problem of [[Define]] semantics being used on class fields when legacy decorators return descriptors regardless of
loosebeing set totrue(tracked in https://github.com/babel/babel/issues/12040).I’m not sure if Babel is correct (always use [[Define]] semantics if legacy decorators return a descriptor, regardless of the class-properties
looseoption) or if TypeScript is correct (never use [[Define]] semantics even if a legacy decorator returns a descriptor, whenuseDefineForClassFieldsisfalse).The problem with supporting both TypeScript and Babel 7 legacy decorators is that they have a number of differences.
What’s the solution for writing a legacy decorator that work in both TypeScript and Babel?
EDIT: I removed some details from this comment (see my next comment for a link to a list of difference between Babel and TypeScript decorators)
It is definitely correct to return a descriptor, no question there. This is how it’ll be going forward.
But there is still a slight issue in babel’s class properties plugin as you can see here.
This helper gets called in the constructor of our class. It’ll modify the existing descriptor (which is why your fix works) but causes some strangeness because of it adding a
value.Anyhow i will review your PR as there’s a few comments.