2024-12 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
ES2025 Iterator Helpers で引数のバリデーションエラー時にイテレーターを閉じるようにする Normative Change。承認された。
詳しくは Zenn に記事を書いた。
re-using IteratorResult objects in iterator helpers (PR) (slides) | Michael Ficarra ES2025 Iterator Helpers で take/drop/filter を使った際に IteratorResult オブジェクトを再利用する Normative Change。こっちは承認されなかった。
Stage 4 (ES2025)
Stage 4 になった 🎉
Stage 3
Stage 3 になった。
DOMException に対しても true を返すように(自分が)働きかけており Deno については対応した。Node.js はまだのようなので issue をたてた。
Stage 2.7
test262 待ちの状態。
前回 thenable (PromiseLike) のことを考慮して import.defer を辞める話になっていたが、やっぱり .then を特別扱いし、export に .then があっても無視することを決めた。
またモジュールを読み込むトリガーに変更がある。
https://gyazo.com/8ac409ee01a0b6076719f4f309bc178d
ShadowRealm の中でどのインターフェースを触れるようにするかまとめている。
Web 標準の仕様としては Web IDL の Exposed で * や ShadowRealmGlobalScope が指定されているものが使えるようになる。まだ議論中のようだが現状オブジェクトのやり取りが不可能なので MessageChannel か BroadcastChannel は入れて欲しい。 Igalia が頑張っているらしい。
URL とソーステキストを複合キーとしてキャッシュし、同じ ModuleSource オブジェクトを返したり、Realm 間での転送など細かい話がなされている。提案自体は概ね好評で、条件付きで Stage 2.7 になった。
またこの提案を元にした Compartments や、Web Workers に Import Maps を入れる話がなされている。
Stage 2
Web の EventTarget との統合について話されている。
前回 champion が引き継がれ、進められている。レビュワーが決まった。
Intl.NumberFormat の currencyDisplay オプションを追加し、何のドルかを詳しく表示出来るようにする提案。Stage 2 になった。
code: js
const formal = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencyDisplay: "formalSymbol",
});
formal.format(42); // "US$42.00"
const never = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencyDisplay: "never",
});
never.format(42); // "42.00"
WebKit に実装した sosukesuzuki さん曰く CLDR 側に必要な情報が不足しており、エンジンが実装するだけでは不十分とのこと。Chrome や Firefox では ICU が直接バンドルされているが、Safari は OS に入っている ICU を使っているため、ブラウザのバージョンと言うよりかは OS のバージョンが新しくなければならない。 Stage 1
Immutable な ArrayBuffer を作る提案。ArrayBuffer.prototype.transferToImmutable にオプショナル引数を導入する話や、ゼロコピーでスライスが作れる API について議論されている。
ECMA-262 側に単位換算の API を追加する提案。
code: js
const height = new Measure(180, { unit: 'centimeter' });
const myHeight = height.convertTo('foot-and-inch');
const uf = new Intl.NumberFormat('en-US', { style: 'unit' });
uf.format(myHeight); // '5 ft, 11 in'
Stage 1 にある Error.prototype.stack を標準化する提案。提案を大きく3つに分割して
Error.prototype.stack の存在だけ仕様に書く
別でスタックトレース文字列を取得する方法を提供する
スタックトレースを構造的に扱える API を提供する
の話が出ている。最後の構造的に扱う API については Chrome, Firefox がパフォーマンスなどの理由から反対気味。
Node.js の require(esm) と同じ機能を import.sync として入れる提案。依然として Node.js の require の需要があり、また Bun が好き勝手に独自拡張して標準との乖離が大きくなっても困るため入れたいという話になった。
Module Harmony 的な提案の立ち位置としては Import Defer に近い。ブラウザでは同期読み込み出来ないらしく、例外を出していいのではという話も上がっている。
Stage 1 になった。
現在オブジェクトの integrity levels は frozen, sealed, そして non-extensible がヒエラルキーとして存在している。
https://gyazo.com/72ebacb1e80cb1127668d17e12914a96
プロトタイプ汚染攻撃などを防ぐために Object.prototype などを frozen 状態にしたいが、Override mistake などのバグによってそれが叶わない状況にある。
代入演算子における Override mistake
code: js
Object.freeze(Object.prototype);
function Point(x, y) {
this.x = y; this.y = y;
}
// TypeError
Point.prototype.toString = function () {
return <${this.x},${this.y}>;
};
Object.prototype をフリーズして Object.prototype.toString を writable: false とした場合、新たに Point.prototype.toString を代入演算子で定義しようとすると例外が起きてしまう仕様バグがある。
ES2025 Iterator Helpers でこの問題を回避するためにハッキーなトリックが必要となった。
コンストラクタの return における Override mistake
code: js
class Trojan {
constructor(key) { return key; }
}
class PrivateTagger extends Trojan {
constructor(key, value) {
super(key);
this.#value = value;
}
}
// adds private field to %Object.prototype%
new PrivateTagger(Object.freeze(Object.prototype), '');
この挙動は Stage 2 Structs の足かせになってしまっている。
Proxy のリエントランシーハザード
code: js
import { isRecord } from "@endo/pass-style";
function foo(suspect) {
if (!isRecord(Object.freeze(suspect))) {
throw Error(...);
}
// ... suspend invariant ...
... suspect.bar ...
// ... restore invariant ...
}
foo(new Proxy({ bar: 3 }), {
get() { foo({}); }
});
しばしば引数にやってきたオブジェクトを最初にバリデーションして、それが通ったときに処理を進めるコードを書くことがある。しかし Proxy のトラップを悪用して、函数内の途中の行で別の函数を呼び出したり、オブジェクトの挙動を変えたりすることが出来てしまう。
ちなみにリエントランシーとはスマートコントラクトにおける攻撃方法らしい。
これらの問題を解決するため既存の integrity とは別に、新たに integrity "traits" を導入する提案。
https://gyazo.com/daaf6a663426674f909d83460dd7513e
fixed: コンストラクタの return における Override mistake が起きない。Structs は fixed かつ sealed となることが想定される。
overridable: 代入演算子の Override mistake が起きない。
non-trapping: Proxy にトラップされない。
no-new-props: 新しいプロパティが追加されない。
parmanent-inhertance: Object.setPrototypeOf 出来ない。
今のところ Object.stabilize などを追加する話になるのかな。Stage 1 になった。
Stage 0
N/A
Withdrown
N/A
その他
Process document fixes and corrections: #46 and #48 | Chris de Almeida プロセスドキュメントの細かい修正。
The importance of supporting materials (slides) | Daniel Minor 議題の締切を開催10日前から14日前にしたい。
Briefing on the formation and goals of TC55 (or, All About Moving the WinterCG into Ecma) (slides) | James M Snell WinterTC やっていき。
記事が出た。
Module Harmony: where we are (slides) | Nicolò Ribaudo 現在の Module Harmony の確認。
https://gyazo.com/4c2656f5d4c1aae06dcf4d0c49b32290
Vision for numeric types in ECMAScript (slides) | Shane F. Carr 数値計算をなんとかしたい。色々な案が出た。
総括
今回は Module Harmony 周りや AsyncContext そして ShadowRealm に進捗があった。新たな提案としては import.sync そして Stabilize が大きくエコシステムに影響を及ぼしそうなため注目していきたい。
Deno や Cloudflare ようなサーバー、エッジランタイム、Moddable XS のような IoT ランタイム、そして Web3 など幅広い分野からの提案が進んでおり、ブラウザ以外の影響力が増しているように思う。