babel / preset-modules

A Babel preset that targets modern browsers by fixing engine bugs (will be merged into preset-env eventually)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

https://astexplorer.net/#/gist/31dbcb25cfb4b322ce10591a3cd2daaf/3bb90ae34957cee457f862de6beb54864d483392

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.