Skip to main content

7.17.0 Released: RegExp 'v' mode and ... 🥁 decorators!

· 4 min read

We just published Babel 7.17.0!

After years of iterations, rewrites and adjustments it looks like the decorators proposal has finally stabilized again on a new design! This release includes both parse and transform support for the new proposal.

We also implemented the RegExp v flag proposal and added parsing support for destructuring private fields, both currently Stage 2. Lastly, a new experimental implementation of @babel/register.

You can read the whole changelog on GitHub.

If you or your company want to support Babel and the evolution of JavaScript, but aren't sure how, you can donate to us on our Open Collective or GitHub Sponsors and, better yet, work with us on the implementation of new ECMAScript proposals directly! As a volunteer-driven project, we rely on the community's support to fund our efforts in supporting the wide range of JavaScript users. Reach out at team@babeljs.io if you'd like to discuss more!

Highlights​

Decorators (#14004, #13681)​

After receiving feedback from JavaScript developers, engine developers and language experts, the decorators proposal was rewritten to take into account multiple constraints and desires. We collaborated with the current proposal author, @pzuraq to implement the new Stage 2 proposal in Babel.

The new implementation also supports decorating private class elements, as well as the new "class auto accessors" syntax:

JavaScript
@defineElement("button")
class Button {
@reactive accessor enabled = true; // class auto accessors

@event("onClick") #handleClick() { // decorator on a private method
console.log("clicked!");
}
}

You can enable the new proposal by passing the "version": "2021-12" option to @babel/plugin-proposal-decorators:

babel.config.json
{
"plugins": [
["@babel/plugin-proposal-decorators", {
"version": "2021-12"
}]
]
}
caution

While the new decorators syntax is compatible with the previous proposal, the semantics are different: decorators already written for Babel "legacy", Babel older-but-not-legacy, or TypeScript will not work with the new proposal.

If you want to help move the proposal forward, you can try using it and leave feedback in their GitHub repository.

RegExp set notation and properties of strings (#14125)​

Babel now supports the RegExp set notation and properties of strings proposal, which introduces three new regular expression features behind a new v flag:

  • Extended set notation, which allows computing difference, intersection and union of characters or strings sets
    JavaScript
    /[\p{Decimal_Number}--[0-9]]/v; // Non-ASCII decimal digits
    /[\p{ASCII}&&\p{Letter}]/v; // ASCII letters
    /[[\p{ASCII}&&\p{Letter}]\p{Number}]/v; // ASCII letters, or any digit
  • Properties of strings, which allow using \p escapes with multi-codepoint properties
    JavaScript
    "Did you see the 👩🏿‍❤️‍💋‍👩🏾 emoji?".match(/\p{RGI_Emoji}/v). // ["👩🏿‍❤️‍💋‍👩🏾"]
  • Multi-codepoint strings in sets, using a new \q escape
    JavaScript
    /[\r\n\q{\r\n|NEWLINE}]/v; // Matches \r, \n, \r\n or NEWLINE

You can enable this proposal using the @babel/plugin-proposal-unicode-sets-regex plugin:

babel.config.json
{
"plugins": ["@babel/plugin-proposal-unicode-sets-regex"]
}

Babel relies on different third-party packages to transform regular expressions: we are grateful to the maintainers of regjsparser, regjsgen and regexpu-core who took time to review our pull requests!

@@ and ^^ topic tokens for Hack-style pipes (#13973)​

We are continuing to help the proposal authors evaluate different tokens for the pipeline operator proposal: one of the champions, J. S. Choi, added support for two new tokens that you can try with the topicToken option:

babel.config.json
{
"plugins": [
["@babel/plugin-proposal-pipeline-operator", {
"proposal": "hack",
"topicToken": "^^" // or "@@"
}]
]
}

You can read more about the supported variations in the @babel/plugin-proposal-pipeline-operator docs.

Experimental @babel/register rewrite (#13782)​

We plan to release Babel 8 as an ESM package. However, this poses a big problem: how to load and run it synchronously in CommonJS packages?

Usually most Babel consumers can run Babel asynchronously, or at least load it asynchronously. This isn't true for @babel/eslint-parser (which integrates Babel's parser with ESLint) and @babel/register (which can be used to transpile Node.js files on-the-fly), where we need to move parsing and transforming to a separate worker.

Babel 7.16.0 exposes the new experimental @babel/register implementation at @babel/register/experimental-worker: it internally runs Babel asynchronously, so it's compatible with .mjs configuration files and with .mjs Babel plugins. It will be enabled by default in Babel 8, and you can already use it as a replacement for @babel/register with a few caveats:

  • If you programmatically specify @babel/register options (using require("@babel/register")({ /* ... options */ })), you must make sure that they are serializable. This means that you cannot pass plugin functions defined inline, but you must move them to a separate ./my-plugin.js file or to a babel.config.js file.
  • The new implementation is still experimental: it should have the same features as the existing one, but there are a few improvements that we are exploring.

We already released the new experimental @babel/eslint-parser implementation in Babel 7.15.0, exposed at @babel/eslint-parser/experimental-worker.