2025-11 の TC39 meeting
https://gyazo.com/d0fb331dbb4a0a3d80f108b2ade4a4d5
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
Intl.NumberFormat は notation: "compact" のときのみ compactDisplay オプションの効果が反映されるが、Intl.PluralRules はそのチェックなしに compactDisplay が反映されるようになっている仕様バグの修正。承認された。
export * from で同じ識別子を参照する場合、その束縛先が曖昧で決定できない場合にエラーになるようになっている。
https://gyazo.com/5a8f663e2fa4c3a726dc22ed657d0d0a
https://gyazo.com/a49382b8aca94e7c47692e14e7e644d2
ここで export * as ns from でネームスペースエクスポートする際に、export { ns }; の有無でエラーになるかどうかが変わる不整合がある。
https://gyazo.com/a37dc3d353a8718f875d66d514c38042
https://gyazo.com/2975db39e72dafbae8c19dbf7bf8c6cf
この不整合を解決する Normative Change が承認された。その後12月に JavaScriptCore と SpiderMonkey に実装されたが、V8 はまだらしい。
Stage 4 (ES2026)
Stage 4 になった 🎉
Iterator.concat の提案。Stage 4 になった 🎉
Stage 4 になった 🎉
Stage 3
Chrome 144 で ship 予定。
https://gyazo.com/8f0e4d84b1ce89f3a521ff0bd9f4d770
JavaScriptCore への実装は Igalia の Tim Chevalier さんが頑張っているらしい。
Iterator.zip{Keyed} の提案。test262 がマージされ、Stage 3 になった。
Stage 2.7
Intl.NumberFormat と Intl.PluralRules の末尾ゼロの扱いを変える提案。
文字列として渡したときに末尾ゼロの扱いが変わる。
code: js
const nf = new Intl.NumberFormat('en', { maximumFractionDigits: 1 });
nf.format('2.00') // now: '2', proposed: '2.0'
nf.format('2.03') // now: '2', proposed: '2.0'
nf.format('1.96') // now: '2', proposed: '2.0'
nf.format(2n) // now: '2', proposed: '2'
nf.format(2.03) // now: '2', proposed: '2'
nf.format(1.96) // now: '2', proposed: '2'
また、新たに trailingZeroDisplay: "stripToMinimum" を追加する議論も起きている。
code: js
const nf = new Intl.NumberFormat('en', {
maximumFractionDigits: 1,
trailingZeroDisplay: 'stripToMinimum'
});
nf.format('2.00') // '2'
nf.format('2.03') // '2'
nf.format('1.96') // '2'
Iterator.prototype.join の提案。
無限イテレーターに対する懸念があったが、無事 Stage 2.7 になった。
Promise.allKeyed の提案。前回の会議で Promise.allSettledKeyed もやることになっている。
Stage 2.7 になった。
Stage 2
Deffed re-exports の提案。バレルファイルを言語仕様として承認しているような提案となっていることに懸念が出ている。
このパターンの是非について共通認識が持てないということで Stage 2.7 にならなかった。
非 ISO 8601 カレンダー(中国暦、和暦、ユダヤ暦など)のために era, eraYear, monthCode の詳細を規定する提案。
CLDR で余分なエイリアス扱いとなっているものを提案仕様から取り除く Normative Change などがあった。
ヒジュラ暦のフォールバック挙動など、Stage 3 にする前に必要な課題について共有された。
クリーンアップ処理のために onTeardown 相当の機能が必要なのではという議論がなされている。
アクセサプロパティの setter に文字列以外を渡すと例外を投げることが決まった。
HTML 仕様との整合性チェック(DOMException 周り?)が必要ということで、Stage 2.7 にはならなかった。
任意のオブジェクトに stack プロパティを付与する Error.captureStackTrace の提案。もともと V8 にのみ独自実装されていたが、2023年8月に JSC に、2024年3月に SpiderMonkey にも実装されており、事実上標準のような扱いになっている。
Stage 2 になった。
import text from "./file.txt" with { type: "text" }; の提案。
Stage 2 になった。
オブジェクトのプロパティ数をカウントする函数を追加する提案。Object.keys(obj).length とは違い、配列を生成しないためパフォーマンスが改善される。
以前はオプションで symbol をカウントするかどうかを指定する形式だったが、カウントしたい対象を函数で分けることとなった。
Object.keysLength(target) — counts own enumerable string-keyed properties (including array indices), mirroring Object.keys.
Object.getOwnPropertyNamesLength(target) — counts all own string-keyed properties, mirroring Object.getOwnPropertyNames.
Object.getOwnPropertySymbolsLength(target) — counts all own symbol-keyed properties, mirroring Object.getOwnPropertySymbols.
Stage 2 になった。
Stage 1
if 分の中で変数宣言できるようにする提案。
code: js
let foo = new Foo;
if (let data = foo.data) {
for (let item of data) {
// ...
}
} else {
// ...
}
実装するにあたりもっと調査が必要となり Stage 2 にならなかった。
(メートルからフィートなど)単位変換機能が再導入される議論が行われた。入れるべき単位について「SI 単位はすべて入れるべき」や「表示する単位のみで十分」という意見が出たが、単位変換機能については支持された。
Intl.NumberFormat にエネルギーに関する単位を追加する提案。電気自動車で欲しいらしい。具体的には watt, kilowatt, kilowatt-hour が追加される。Stage 1 になった。
Stage 2 にするために他に導入する単位も定める必要があるということになった。
現状 Intl.NumberFormat には単位をコンストラクタで渡す必要があるが、format メソッドの方でも渡せるように拡張する提案。
code: js
// Today:
let formatter = new Intl.NumberFormat(locale, {
style: "currency",
currency,
});
let result = formatter.format(number);
// With the protocol:
let formatter = new Intl.NumberFormat(locale, {
style: "currency",
});
let result = formatter.format({
number,
currency, // or unit: currency? (to be discussed)
});
モチベーションとして Intl.MessageFormat の提案では format メソッド側で単位を渡す必要があるため、それに合わせた仕様を入れたい。
code: js
const message = "You are {$distance :unit usage=road} from your destination";
let formatter = new Intl.MessageFormat("en", message);
formatter.format({
distance: /* what goes here? */
})
Stage 1 になった。
Async Iterator Helpers から派生した Concurrency Control の提案。
https://gyazo.com/862ad52f712e6b0480f8268eaeff4112
Governor を継承したクラスを作ることでカスタムすることが出来る。また Governor を継承した CountingGovernor クラスも提供される。
https://gyazo.com/d0f9048ec9e2db2aa37981a0afe34bc3
この Governor は AsyncIterator クラスの forEach, some, every, find, reduce そして toArray にオプションとして渡すことが出来る。数値を渡した場合は CountingGovernor を渡した場合と同じ扱いになる。
Composites の提案で、方針について議論されている。
Unique Object
code: js
let c1 = new Composite({ x:1, y:4 });
let c2 = new Composite({ x:1, y:4 });
c1 === c2; // false
Composite.equal(c1, c2); // true
通常のオブジェクトと同じ生成コストの代わりに Map や Set のキーや Array.prototype.indexOf などの仕様を変更する必要がある。
Interned Objects
code: js
let c1 = Composite({ x:1, y:4 });
let c2 = Composite({ x:1, y:4 });
c1 === c2; // true (everywhere)
生成コストがかかり、GC のセマンティクスを追加する必要があるが、その他の仕様を変更する必要がない。
Interned Objects を選んだ場合、WeakSet, WeakMap のキーにそのオブジェクトを入れた場合にメモリリークを起こす恐れがある。
code: js
let c = Composite({ x: 1, y: 4 });
let ws = new WeakSet();
ws.add(c); // 1 ?
ws.has(c); // 2 ?
c = null;
await time(); // 💤
c = Composite({ x: 1, y: 4 });
ws.has(c); // 3 ?
https://gyazo.com/59b5addd6c5e80b1da3ee71c104a700a
温度感チェックの結果、WeakSet, WeakMap のキーに入れようとした場合に例外をなげることとなり、Interned Objects の方針が支持された。
should we throw on leaky weakmap insertion?
Temperature Check | Strong Positive ❤️: 17, Positive 👍:2, Following 👀: 4, Confused ❓: 0, Indifferent 🤷: 3, Unconvinced 😕: 1
Do we lean towards interning?
Temperature Check | Strong Positive ❤️: 10, Positive 👍: 4, Following 👀: 1, Confused ❓: 4, Indifferent 🤷: 2, Unconvinced 😕: 2
%TypedArray%.concat の提案。Node.js の Buffer.concat と同じように TypedArray を結合する。
Stage 1 になった。
TypedArray で一致するバイト列を検索する API の提案。Next.js が同等の函数を実装しているため、ユースケースがありそう。
Stage 1 になった。
ArrayLike の "0", "1", ... のようなインデックス文字列でないプロパティを取得する提案。ライブラリ開発者からのユースケースの調査をすることを条件に Stage 1 になった。
Stage 0
TypedArray byteOffset Mistake for Stage 1 (Slides) | James Snell %TypedArray%.prototype.subarray にオプションとして clamped: true を指定することで、ArrayBuffer をコピーすることなく限定された範囲の ArrayBuffer を作れるようにする提案。
Immutable ArrayBuffer 文脈で進めていく話になった。
2つの変数を比較する compare 函数の提案。assert.deepEqual の中で使われることが想定される。
code: js
const bar = Symbol('bar');
compare(
{ foo: { bar: 'b', qux: 'c' } }, {
mode: 'all',
},
);
// Iterator => Iterable(2) {
// expected: 'a',
// actual: 'b',
// reasons: { equality: true, … },
// },
// expected: undefined,
// actual: 'c',
// reasons: { missing: true, … },
// },
// }
言語仕様に入れるモチベーションが認められず、Stage 1 にならなかった。
クラスのメソッドなどを spread syntax でコピーできるようにする提案。
code: js
class RegularPolygon {
constructor (sideLength, sides) {
this.sideLength = sideLength;
this.sides = sides;
}
getArea () {
const {sideLength, sides} = this;
return sides * sideLength ** 2 /
(4 * Math.tan(Math.PI / sides));
}
}
class EquilateralTriangle extends Triangle {
sides = 3;
constructor (sideLength) {
super(sideLength, sideLength, sideLength);
this.sideLength = sideLength;
}
...RegularPolygon;
}
(new EquilateralTriangle(4)).getArea(); // 6.93
カプセル化の破壊や、private の扱いに懸念が出され Stage 1 にならなかった。
クラスの fields で定義されるプロパティを Well-known Symbol を使って取得できるようにする提案。
code: js
class A {
bar = 2;
static baz = 3;
}
// [
// { name: "foo", initializer () { return 1; }, static: false, private: true },
// { name: "bar", initializer () { return 2; }, static: false, private: false },
// { name: "baz", initializer () { return 3; }, static: true, private: false },
// { name: "qux", initializer () { return 4; }, static: true, private: true },
// ]
こちらも Stage 1 にならなかった。
Withdrown
N/A
その他
Decorators proposal status update? | Jacob Smith
Stage 3 Decorators の実装が膠着状態にある。Test262 のカバレッジが低いことが課題としてあげられ、まずそちらからやる方針となった。
Spec-defined or Implementation-defined limits? (slides) | Shane F Carr 配列の長さや bigint のサイズなどの制限を仕様で定義するべきか、実装に委ねるべきかが議論された。結論として「最小限の制限は仕様で定め、最大限の制限は実装に委ねる」こととなった。
WHATWG Stages (slides) | Chengzhong Wu WHATWG も提案を Stage Process で進めようとしている話。
総括
今回は議題が多かった。
Iterator.concat や JSON.parse source text access などが Stage 4 になった。
既存の提案としては Composite がコンストラクタをやめて、函数として進むこととなった。また Intl 周りで単位変換やエネルギーに関する単位を入れる提案で CLDR を土台として議論されていて興味深い。
新しい提案として Stage 2 Import Text が入った。Message Format で文字列を取得するのに必要だと issue を出していたため、個人的にこれが進んでくれて嬉しい。