Add ECMAScript 2020 features?
rdmurphy opened this issue · comments
@babel/plugin-proposal-nullish-coalescing-operator
and @babel/plugin-proposal-optional-chaining
were just added to @babel/preset-env
with the release of 7.8.0
— should they also make an appearance here?
I updated our preset to 7.8, in consequence remove those two plugins manual inclusion. When the preset-modules
is used, optional chaining and nullish coalescing are not transformed anymore.
@rdmurphy I think these make more sense to be handled via preset-env. Currently, preset-modules transforms only syntax that is broken in modern browsers, not syntax that has varying degrees of support. This is the same reason preset-modules doesn't currently include transforms for class fields.
That being said, if we're looking to bridge the gap until preset-env landing the modules fixes, perhaps it'd be worth bringing in these transforms. If you'd be up for PR'ing this (and maybe those class transforms?) I think we could merge.
(edit: looks like @babel/plugin-proposal-class-properties
output would be suboptimal as it uses an inline polyfill. Maybe worth a custom plugin!)
Note that the inline helper (it's not a polyfill) it's just an optimization: it will make your code shorter if you use 3-4+ class fields, and uses [[Set]]
instead of Object.defineProperty
(which is more expensive) when it's not observable.
Anyway, the proposal is not standard yet so I don't think that it should be included here.
Optional chaining and nullish coalescing are standard / stage 4.
Class fields are stage 3, and shipping in browsers, which is a more important milestone for Babel imo than the stage.
Alright, spent an hour putting together a dedicated plugin for class fields. Not sure what I'll end up doing with it, but for those interested here it is:
For me this solves an issue where including plugin-proposal-class-properties
produces ES5 class output since I'm not using preset-env
.
@nicolo-ribaudo good point about the helper being a helper and not a polyfill. I've included a somewhat naive compile-time version of that logic in this alternative plugin, curious to have folks poke holes in that approach. It fails for assignment to this
in inherited classes, as well as for dynamic property assignment (this[window.whatever]=2
).
Class fields are stage 3, and shipping in browsers, which is a more important milestone for Babel imo than the stage.
preset-env
has the shippedProposals
option, for proposals which are not part of the specification yet but are already shipped in at least one browser/node. We should probably add class-fields
to that option.
@developit Looking at your plugin, I think that you misinterpreted the reason for using the optimized [[Set]] in the plugin.
Object.defineProperty
is unrelated to this.bar = 2
in the constructor: it's needed when there is a setter on the prototype of the class (almost always coming from a superclass or a subclass, but could also come from Object.prototype
or from the class itself) because the setter shouldn't be triggered. This isn't statically analyzable, because almost always the base and derived classes are in two different files.
Also, the descriptor you pass to defineProperty
must have the enumerable: true, configurable: true, writable: true
properties. If you replicate this descriptor a bunch of times (for different properties), then it's longer than using the helper.
I don't think that it's possible to make a spec-compliant version of the plugin smaller than the current one, and if someone isn't concerned with spec compliancy in the [[Set]] vs [[Define]] case they can already enable loose mode, which produces this output:
class A extends B {
x = 2;
}
// ->
class A extends B {
constructor(...args) {
super(...args);
this.x = 2;
}
}
@nicolo-ribaudo indeed, the approach in my link is over-simplified.