ECMAScriptの最新動向 2021年12月版

Published on

TC39 の 87 回目のミーティングが 12月14日 ~ 12月15日に開催されました。このミーティングで議題に上がった提案とそのステージの移動について紹介します。

For Stage 4

For Stage 4 の提案はありませんでした

For Stage 3

Array Grouping

Stage 3 になりました

Array Grouping は Array.prototype.groupByArray.prototype.groupByToMap を追加するプロポーザルです。

2021 年 10 月のミーティングで Stage 2 になったばかりですが、今回のミーティングで Stage 3 になりました。

また、今回から Array.prototype.groupByToMap が追加されています。

これは groupBy の結果が Map になったものです。

const array = [1, 2, 3, 4, 5];
const odd  = { odd: true };
const even = { even: true };
const map = array.groupByToMap((num, index, array) => {
  return num % 2 === 0 ? even: odd;
});
console.log(map); // Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

For Stage 2

Array.fromAsync

Stage 2 になりました

Array.fromAsync は非同期イテラブルから配列を生成するためのスタティックメソッドを追加するプロポーザルです。

JavaScript では Array.from を使ってイテラブルから配列を生成できます。しかし、非同期イテラブルから配列を生成することはできません。

このプロポーザルによって追加される Array.fromAsync メソッドを使うと次のようにして非同期イテラブルから配列を生成できます。

async function * asyncGen (n) {
  for (let i = 0; i < n; i++)
    yield i * 2;
}
const arr = await Array.fromAsync(asyncGen(4));

RegExp \R escape

Stage 2 になりませんでした

RegExp \R escape は以前 RegExp Language Features として提案されていた正規表現の機能群の1つで、正規表現内で line terminator とシンプルにマッチングさせるために新しく \R を導入する提案です。

この機能は u もしくは v フラグが有効になっているときのみ有効になります。そして、大まかには次のパターンと等価です。

(?>\r\n?|[\x0A-\x0C\x85\u{2028}\u{2029}])

この正規表現の機能は Perl をはじめとする多くの正規表現エンジンに実装されていて、TC39 においてもそのユースケースは認められているようです。

しかし、RegExp Set Notation Proposal の sequece properties によって同等の機能が実現できる可能性があるためその方向で調査しなおすべきだという結論になり Stage 2 には到達しませんでした。

RegExp Modifiers

Stage 2 になりました

RegExp Modifiers は \R escape と同じようにもともと RegExp Language Features の機能の1つでした。

この提案は正規表現パターン内でのフラグの変更を可能にします。

例を示します。

次の例中の正規表現パターン全体には i フラグが適用されてます。しかし2つめの [a-z]?-i: という RegExp Modifiers の構文を使って i フラグを無効にしてます。このとき一文字目では大文字小文字が無視されるものの、二文字目では大文字小文字が無視されません。

したがってこのパターンは "ab""Ab" にはマッチし "aB" にはマッチしません。

const re1 = /^[a-z](?-i:[a-z])$/i;
re1.test("ab"); // true
re1.test("Ab"); // true
re1.test("aB"); // false

RegExp Buffer Boundaries

Stage 2 になりました

RegExp Buffer Boundaries も RegExp Language Features の機能の1つでした。

この提案は、それぞれ入力の最初と最後にマッチする \A\z を導入します。m フラグの影響を受けないことを除けば ^$ に似ています。

^$ はそれぞれ最初と最後にマッチしますが、m フラグが有効になっているときは行頭と行末にマッチします。しかし RegExp Buffer Boundaries が導入する \A\z は、たとえ m フラグが有効であっても入力の最初と最後にマッチします。

例を示します。

const re = /\Afoo|^bar/um;

このパターンでは foo\A がついています。したがって入力の最初が foo の文字列にマッチします。

re.test("foo"); // true
re.test("foo\n"); // true

しかし入力の最初ではなく行頭が foo の文字列にはマッチしません。

re.test("\nfoo"); // false

bar には ^ がついています。パターン全体で m フラグが有効になっているので、入力の先頭と行頭が bar の文字列にマッチします。

re.test("bar"); // true
re.test("bar\n"); // true
re.test("\nbar"); // true

For Stage 1

Updates

ステージの移動はないものの、アップデートがあった提案です。

Temporal

いくつかの仕様上の軽微な修正がありました。修正箇所について説明したスライドが公開されています。

Decimal

Decimal は現在 Stage 1 ですが、2022 年に Stage 2 に到達することを目指しているそうです。進捗を共有するためのスライドが公開されています。

Destructuring Private Fields

Destructuring Private Fields が提案された当初は小さな修正で十分だと考えられていました。しかし真剣に検討してみるといくつかの仕様上の難しい問題が明らかになったそうです。そこで再度レビュワーを募りレビューをやり直すことが決定しました。

Shadow Realms

いくつかの仕様上の重要な変更があったようです。詳しくはスライドに記載されています。

Records and Tuples

Record と Tuple の中で通常のオブジェクトを扱う方法について議論されました。その方法とその懸念についての Decision Tree がスライドとして公開されています。

Normative Changes

import.meta[Symbol.toStringTag] の追加

合意は得られませんでした

Symbol.toStringTag という Well-known Symbol があります。 この Symbol は Object.prototype.toString() によって表示される文字列の決定に使われます。

具体的な例を示します。

オブジェクト foo[Symbol.toStringTag]"I'm foo" という文字列をセットしておくと、foo.toString()[object I'm foo] になります。

const foo = {
  [Symbol.toStringTag]: "I'm foo"
};
console.log(foo.toString()); // "[object I'm foo]"

今回のミーティングでは import.meta[Symbol.toStringTag]"ImportMeta" という文字列を設定するという修正について議論されました。

この挙動についての Issue は import.meta の策定時にも存在しましたが、そのときすでに import.meta が Stage 4 を達成していたことからクローズされました。

そして今回のミーティングでもこの仕様の修正についての合意は得られませんでした。この修正のための Pull Request が作成された時点で以下のような懸念が公開されていました。

  • import.meta は、ECMAScript の範囲では HostGetImportMetaProperties というホスト定義の abstract operation によって中身が決定されるオブジェクトであるということしか決まっておらず、ホストにとって必要であればホスト側で import.metaSymbol.toStringTag を定義できる。
  • 仕様内で作成される他のオブジェクトとは異なり、import.meta はホストのデータによって生成されるものであり、ECMAScript の範囲でプロパティを生成することを考慮したものではない。

参考リンク

ツイート

記事に関する報告などはこちらから
;