ES2024 と Stage 3 propsals


こんにちは。新年明けましておめでとうございます。気づけば 3 月になってました。

2024年は健康的な精神・肉体を育むため、十分な睡眠・バランスの良い食事・過度な運動に取り組んでいこうと思います。先日インフルエンザで 5 日間 39 度の発熱を経験した時には、「これが死ぬということか」とさえ思いました。30代つらい。

さて、2022, 2023, 2024 と新しい年になったときに、気になるものはありませんか?

えぇ、そうです、 ECMAScript ですよね。 ECMAScript は 2015 年以降、毎年 6 月に新バージョンを公開していて、バージョニングは ES6 のような Edition の数字を用いるパターンと ES2015 のように年を用いるパターンがあり、最近では後者の方が主流になっています(体感)

ECMAScript の仕様策定

ECMAScript の仕様策定は GitHub で行われており、TC39 というグループがプロジェクトの進行をしています。

TC39 は ECMA International の中にある一つのグループで、他にも TC50 や TC41 といったグループが存在します。

ECMAScript の仕様策定プロセスを追っていく上で重要なのがプロポーザルとステージです。プロポーザルの意味はそのままで、ECMAScript に対する提案・意見や企画であり、ステージはそのプロポーザルの検討段階を表します。

プロポーザルは 6 つのステージで構成されており、以下がそのステージごとの役割です。

  • Stage 0: アイデア。 TC39 によって検討されていないステージ。
  • Stage 1: 検討が開始され、このプロポーザルの目的や解決できることについて整理するステージ。
  • Stage 2: ある程度設計が完了し、セマンティクス、シンタックス、API 等が定義されるステージ。
  • Stage 2.7: 仕様が承認され、仕様に則って検証が行われるステージ。
  • Stage 3: 検証が終わってほとんど完成し、フィードバックを求めるステージ。
  • Stage 4: リリースに向けて本格的に動き出すため、tc39/ecma262 または tc39/ecma402 に仕様を取り込むステージ。

Stage 2.7 は 2024 年の頭に追加されました。 2.7 が追加されるにあたってどのような議論が行われたかは、 jxck さんの記事がわかりやすいです。

ES2024 でリリースされるもの

さて、そんな ECMAScript 2024 でリリースされるものを少し観ていきましょう。

Stage 4 Finished Propsals はこちらから確認できます。

Well-Formed Unicode Strings

ECMAScript の整数値の仕様は 2 byte ( 16 bit )の符号なし整数でなければならないこと以外に制約を持たないため、上位サロゲート・下位サロゲートのコードが対になって順番に現れているかどうかは判定していません。

そのため ECMAScript で何らかの文字列を扱う場合は、与えられた整数値がペアになっておらず浮いている、あるいは順序が正しくないサロゲートを含んでいるかどうか検証する必要があります。

本プロポーザルでは、その課題を解決するために与えられた文字列が整形式かどうかを判別する String.prototype.isWellFormed と整形式に変換する String.prototype.toWellFormed を追加します。

特に WebAssembly Component Model で整形式を必要とするため、WebAssembly を扱う人にとっては関心の強いアップデートかもしれません。

Atomics.waitAsync

Atomics.wait の非同期バージョンですね。そもそも Atomics.wait が Int32Array の値を検証する関数であるため、その処理を非同期で行う感じです。

Atomics.wait の本来の役割としては Int32 Array の検証ですが、その関数の特性からスレッドをスリープする時にも用いられるケースがあります。

Atomics.wait(new Int32Array(new ArrayBuffer(128)), 0, 0, time)

RegExp v flag with set notation + properties of strings

既存の RegExp u flag について新たに v flag を追加し、差/減算( A だが B でない )・交差( A と B の両方 )・ネストされた文字に関する操作のシンタックスとセマンティクスを追加するプロポーザルです。

ただでさえ正規表現のシンタックスを覚えられないのに、これ以上増やさないでほしい(小声)

Resizable and growable ArrayBuffers

Well-Formed Unicode Strings と同様に、こちらも WebAssembly を扱う人にとっては朗報かもしれません。プロポーザルにも記載されているこちらの Issue がわかりやすい例ですね。

ArrayBuffer は固定長であるため、もし別の長さの ArrayBuffer が欲しい場合は改めて ArrayBuffer を new する必要がありましたが、今後はそのままリサイズできるようになります。

Array Grouping

プロポーザルの名前の通り、配列の要素をグルーピングする関数 Object.groupBy / Map.groupBy が追加されます。

配列の操作であることから Array.prototype.groupBy が直感的だと感じますが、互換性の問題から Object に紐づく関数で定義されています。

わりとプロダクトの開発において日常的に使いそうではあるものの、実はそこまでグルーピングしたいシーンないんじゃないかと勝手に感じてます。

Promise.withResolvers

イベントリスナーと Promise を組み合わせて使う場合、 resolve と reject がコールバックの引数として渡されることからネストが深くなってしまいます。

そういった背景から resolve と reject を返すユーティリティ関数を人類は繰り返し書いてきましたが、この定型的なコードを静的メソッドとして定義しようというプロポーザルです。

function withResolvers() {
  let resolve = () => { };
  let reject = () => { };
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise resolve, reject}; 
}

ArrayBuffer transfer

上で紹介した Resizable and growable ArrayBuffers からスピンアウトしたプロポーザルです。

私自身がこの課題に直面したことないため解像度の高い話はできないのですが、 WebAssembly が抱える課題を解決するプロポーザルが多いですね。

Stage 3 の Proposals

近いうちにリリースされるであろう、特に注目しているプロポーザルを見ていきましょう。

Temporal

JavaScript で Date を扱ったことある人はわかるかもしれませんが、Date めちゃくちゃ使いにくいですよね。

提供されている API も貧弱ですし、タイムゾーンがサポートされていないし、凝ったことをやろうとすると date/fns や moment.js に頼らざるを得ません。

そんな使いにくい Date を一新するのが Temporal です。日付と時刻の操作を簡単に行える API やタイムゾーンのサポートによってより正確な時刻の取り扱いを実現しています。

こちら のドキュメントが普通に読みやすいので、ここで語るよりもこのドキュメントを読んで欲しいです。

Shadow Realm

Shadow Realm を理解する前に、 ECMAScript の Realm を理解するとよいでしょう。とても概念的ではありますが、 Realm とは ECMAScript においてロードされるコードおよびそれに関連する状態とリソースを指します。

そして、 Shadow Realm を使うことによって新しい Realm を作成でき、 ShadowRealm の evaluate で任意の ECMAScript コードを評価することができます。

一応、 iframe 等でも Realm は作れるので「新たに Realm を作れるようになった」と認識するのは間違いです。より手軽に Realm を作れるようになった、くらいですね。

Realm および Shadow Realm の使い道としては、ブラウザベースのエディタ(プレイグラウンド等)でユーザーが入力した JavaScript のコードを評価する、といったものが想定されますね。


そのほか、デコレータのプロポーザルが取り込まれることを長らく期待されていましたが、TypeScript が先んじて実装して experimental フラグを外したので、少しニューフェイス感なくなりましたね。このように TypeScript 側で先んじて実装するケースが多くなってきています。

また、トレンドとしては WebAssembly 関連・正規表現・モジュール関連のプロポーザルが熱いです。

ECMAScript の今後

モジュールという観点では ES Modules がデファクトスタンダードになりつつありますので、今後も ECMAScript の仕様は存続しますし、他のモジュール仕様は淘汰されていくんじゃないかな、と感じます。

2015 年から急激に進んでいる TC39 主体の仕様策定で言語としての機能は十分に揃ったと思いますが、他の高級言語に比べると痒いところに手が届いていない印象で、今後はそういった細かいアップデートが増えていくと想定しています。

Nullish coalescing Operator や Optional Chaining のような JavaScript による開発体験を一新する、目が覚めるようなアップデートが個人的には好きなんですけどね。

おわりに

2015 年以前の ECMAScript の歴史を一から説明していると人類が滅びかねないため、この記事では省略しましたが、興味のある方は調べてみてください!

そこには、人と人との血みどろの戦いが描かれているかもしれません。