BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Babel 7.3: Smart Pipelines, Private Instance Accessors and More

Babel 7.3: Smart Pipelines, Private Instance Accessors and More

This item in japanese

The recently released Babel 7.3 can now parse and compile private instance accessors and the ‘smart’ pipeline operator. Babel 7.3 additionally supports named capturing groups in regular expressions, and much more.

Developers can now use the syntax defined for getters and setters of private instance fields (private instance accessors) by adding @babel/plugin-proposal-private-methods to their babel config. The proposal gives the following example of a custom element’s implementation:

class Counter extends HTMLElement {
  #xValue = 0;

  get #x() { return #xValue; }
  set #x(value) {
    this.#xValue = value; 
    window.requestAnimationFrame(this.#render.bind(this));
  }

  #clicked() {
    this.#x++;
  }

  constructor() {
    super();
    this.onclick = this.#clicked.bind(this);
  }

  connectedCallback() { this.#render(); }

  #render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter);

get #x and set #x are respectively private getter and setter functions which will respectively retrieve and update the private field xValue. #render is a private method for the class Counter.

Previous Babel releases already implemented private fields and methods for class instances. Static private fields was also already implemented in Babel 7.1, while static public fields and static private methods will be addressed in future Babel releases. Private fields, methods and accessors, whether static or for class instances, are ECMAScript stage 3 proposals. As such they are not considered yet as part of the JavaScript language.

Babel 7.3 also implements the Smart Pipeline Operator proposal’s main proposal. The additional features of the mentioned proposal are not supported in this release. Developers can enable the new syntax with adding the @babel/plugin-proposal-pipeline-operator plugin in their .babelrc config:

{
  "plugins": [
    ["@babel/plugin-proposal-pipeline-operator", { "proposal": "smart" }]
  ]
}

The pipeline operator offers a syntax for computations which can be defined as a flow of data through a pipeline of functions. The details of the pipeline syntax are currently unsettled. There are three proposals for the pipeline operator. The Minimal Pipeline Proposal allows to express function composition such as in:

let newScore = boundScore( 0, 100, add(7, double(person.score)) )

more concisely as follows:

let person = { score: 25 };

let newScore = person.score
  |> double
  |> (_ => add(7, _))
  |> (_ => boundScore(0, 100, _));

newScore //=> 57

The Minimal Pipeline Proposal does not support await syntaxes in the pipeline. |> await f will result in an early error.

The F# Pipelines Proposal supports await use cases. The proposal illustrates how the following code:

console.log(
  await stream.write(
    new User.Message(
      capitalize(
        doubledSay(
          await promise,
          ', '
        )
      ) + '!'
    )
  )
);

can be flattened with the proposed syntax:

promise
  |> await
  |> (x => doubleSay(x, ', '))
  |> capitalize
  |> (x => x + '!')
  |> (x => new User.Message(x))
  |> (x => stream.write(x))
  |> await
  |> console.log;

The proposal illustrates typical use cases which would benefit from the proposed syntax.

The Smart Pipelines Proposal is a ECMAScript stage-0 proposal. As such, its syntax may see considerable changes in the future. An important alleged advantage of the ‘smart’ proposal is to offer unambiguous semantics. The following code:

input |> await object.method(x, y);

could reasonably mean any of these lines:

await object.method(input, x, y);
await object.method(x, y, input);
await object.method(x, y)(input);
(await object.method(x, y))(input);

In those situations, the ‘smart’ proposal would force an explicit syntax, using # as a placeholder for the piped-in argument:

input |> await object.method(#, x, y);
input |> await object.method(x, y, #);
input |> await object.method(x, y)(#);
input |> (await object.method(x, y))(#);

The Minimal Pipeline Proposal is already supported by in the previous Babel minor release. The F# Pipeline Proposal is not supported yet.

Babel 7.3 implements the RegExp Named Capture Groups proposal, which has been approved as a part of ES2018. The new syntax can be enabled with adding the corresponding plugin @babel/plugin-transform-named-capturing-groups-regex to the Babel config. Alternatively, it is by default included as part of a Babel config including @babel/preset-env.

RegExp named capture groups allow to refer to certain portions of a string that a regular expression matches by name. For instance:

let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';

// result[0] === '2015-01-02';
// result[1] === '2015';
// result[2] === '01';
// result[3] === '02';

The Babel 7.3 release also comes with a host of bug fixes and other improvements, including better TypeScript parsing.

Babel is available under the MIT open source license. Contributions are welcome via the Babel GitHub organization and should follow Babel’s contribution guidelines and code of conduct. Donations to support the project may also be made via Open Collective.

Rate this Article

Adoption
Style

BT