2025-07 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
Intl.Segmenter.prototype.segment の返す Segments オブジェクトの Symbol.iterator メソッドの name プロパティが仕様になかったのを修正する Normative Change。承認された。
Spec/implementations divergence on module evaluation promises settlement order (tc39/ecma262/#3589, slides) | Nicolò Ribaudo Top-level await のある非同期モジュールを Dynamic Import した際の解決順が仕様と実装で乖離している。
https://gyazo.com/a6219b60a5be8ca4e64392b0627e5b3f
仕様を実装に合わせ、fulfilled と rejected で解決順を変えず、子モジュールから親モジュールの順で実行される方針となった。
F.p.toString incompat for builtin accessors (issue) | Keith Miller 以前 Function.prototype.toString の変更でアクセサプロパティを文字列化した際に get と set を追加することが決まったが、Safari に(sosukesuzuki さんが)実装したときに eval ができなくなることにより2度 Break the Web を起こしたことによって諦めた。
破壊的変更になってしまうことから文字列を追加するのを諦める方針。
TypedArray copyWithin inconsistently responds to midstream shrinking (issue, PR) | Richard Gibson %TypedArray%.prototype.copyWithin の引数に valueOf を持つオブジェクトを渡すことによって、引数の処理をしている間に ArrayBuffer の長さを変更することができる。
code: js
const buffer = new ArrayBuffer(4, { maxByteLength: 4 });
const bytes = new Uint8Array(buffer);
bytes.copyWithin(0, 2, {
valueOf() {
buffer.resize(2);
return 4;
},
});
範囲外アクセスを検知するとコピーループを抜けるようになっているが、逆順にコピーしている際に valueOf で ArrayBuffer のサイズが小さくなったときに、まだコピーするべきところを途中で抜けてしまう仕様漏れがある。web reality に合わせて仕様を修正する Normative Change(実装は LibJS のみが仕様通りになっているがゆえに挙動がおかしくなっている)。
承認された。
Stage 4 (ES2026)
Stage 4 になった 🎉
Stage 4 になった 🎉
ストリーム処理の明示的な対応はされないことになったが、提供される API を使って容易に実装することができる。
Stage 3
今まで Temporal API に渡すオプションのプロパティを1つずつ [[GET]]、キャスト、バリデートするようになっていたが、先に全プロパティに対して [[GET]] し、その後キャスト、バリデートするようにする Normative Change。これによって発生する例外がユーザーフレンドリーになる。
https://gyazo.com/809aafb4e18785d246021171debc0c15
承認された。
Iterator.concat の提案。Stage 3 になった。
{,Weak}Map.prototype.getOrInsert{,Computed} の提案。Stage 3 になった。
Stage 3 になった。今後は Web IDL 側での対応も必要になってくる。
Stage 2.7
Stage 1 Stabilize Integrity の提案から派生した Non-extensible オブジェクトに新たに Private State を追加できなくする提案。Web 互換性的に問題なさそうなのが確認された。 https://gyazo.com/971b7a71b0346f019fbdce9c9ec4e127
test262 を進めることとなった。
ECMA-402 に ISO8601 以外のカレンダーについて明記する提案。
Stage 2.7 になった。
Stage 2
Mozilla の DOM チームから反対されていたが、Igalia により Web Engines Hackfest でセッションが設けられたことにより懸念点はあるものの一定のユースケースを認めてもらえた。Cecko でプロトタイプ実装をしている最中とのこと。
前回の会議で Iterator.prototype.windows で要素数が足りない場合にどうするかが議論され、新たに Iterator.prototype.slideing を追加したらどうかという提案があった。
結果的にはメソッドを新しく作るのではなく、Iterator.prototype.windows にオプションを追加する方が支持されている。結論は特に決まっていない。
code: js
import foo from "./foo.png" with { type: "bytes" };
console.log(foo); // Uint8Array
今回が会議として初の提案だったがすぐに Stage 2 になった。
Stage 1
Chrome の独自実装だった Error.captureStackTrace が JavaScriptCore や SpiderMonkey にも実装されたため標準化する提案。
現状 stack プロパティが各実装でデータプロパティ、アクセサプロパティで揺れていて、結論が出ていない。TG3 で引き続き議論することとなった。
Intl.NumberFormat と Intl.PluralRules で末尾のゼロを保持する提案。
Stage 2.7 になった。
数値の単位、有効数字を扱う提案。
以前 Measure クラスだったのが Amount クラスになり範囲が狭まった。単位変換(メートルからヤードに変換するなど)機能は Stage 1 smart units の提案に譲られスコープ外となった。Amount クラスはイミュータブルで、値、単位、有効数字を扱う。 code: ts
interface AmountOptions {
unit?: string;
fractionDigits?: number;
significantDigits?: number;
roundingMode?: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven";
}
interface AmountToStringOptions {
displayUnit?: "always" | "auto" | "never";
}
class Amount {
constructor(value: bigint | number | string, options?: AmountOptions);
toBigInt(): bigint;
toNumber(): number;
toString(options?: AmountToStringOptions): string;
toLocaleString(locale?: string, options?: object);
}
言語仕様に入れるべき十分な動機づけがあるかどうかという懸念が出され、Stage 2 にはならなかった。
Import Hook はかつての Compartments から切り出した提案で、ModuleSource を作る際に Import Hook を追加できるようにする提案。
code: ts
interface ModuleHandler {
importHook?: ImportHook,
importMetaHook?: ImportMetaHook,
// ...
};
interface ModuleSource {
constructor(source: string | ModuleSource, handler?: ModuleHandler);
}
そして new Global は新たにグローバルオブジェクトを作れるようにする提案。
code: ts
interface Global {
constructor({
keys?: string[],
importHook?: ImportHook,
importMetaHook?: ImportMetaHook,
})
Global: typeof Global,
eval: typeof eval,
Function: typeof Function,
// Consequently, internal slots for
// AsyncFunction, GeneratorFunction, AsyncGeneratorFunction
// ... and properties copied from globalThis filtered by keys
}
基本的に元のグローバルと Intrinsic(プロトタイプなど)を共有するので、ShadowRealm のようなサンドボックス環境をつくるというよりかは、ユニットテスト環境を作りやすくするなどの目的の方が近そう。
code: js
globalThis.x = {};
const newGlobal = new globalThis.Global();
newGlobal.Object === globalThis.Object;
newGlobal.x === globalThis.x;
コンストラクタに key を指定することでコピーされるグローバルプロパティを制限できる。
code: js
globalThis.x = {};
globalThis.y = {};
const newGlobal = new Global({
});
newGlobal.x === undefined;
newGlobal.y === globalThis.y;
newGlobal.Object === undefined;
eval に依存する設計であることや、サンドボックスを作るように見えるが実際はそうではない API になっているという懸念が出されたが、新たに Module Global という提案として Stage 1 になった。懸念点は Stage 2 までに解消するとのこと。
オブジェクトのプロパティの数を数えるときによく Object.keys(obj).length が使われているがこれはパフォーマンスがよくないため、新しく専用のスタティックメソッドを追加したい提案。
code: ts
interface PropertyCountOptions {
keyType: "string" | "symbol" | "all";
enumerable: true | false | "all";
}
interface Object {
propertyCount(target: object, options: PropertyCountOptions): number;
}
全体的な API 削減を考慮するべきということで Stage 2 にならなかった。
JavaScript の配列にはインデックスプロパティ ("0", "1", ...) に加えて非インデックスな文字列プロパティを付与することができる。例えば RegExp.prototype.exec などが lastIndex などのプロパティが追加された配列を返す。
この非インデックス文字列プロパティを列挙する方法が提供されていないため Array.getNonIndexStringProperties として追加したい提案。Stage 1 になった。
Object.getOwnPropertySymbols に新たにオプションを追加し、enumerable フィルターを追加する提案。
code: ts
interface GetOwnPropertySymbolsOptions {
enumerable: true | false | "all";
}
interface Object {
getOwnPropertySymbols(target: object, options: GetOwnPropertySymbolsOptions): number;
}
Object.keys に対して Object.getOwnPropertyNames があるように、非列挙可能なプロパティのみを取り出す別メソッドにしたほうがいいという意見が出たが、とりあえず Stage 1 になった。
thenable の仕様によって、Promise が解決されるときに同期的にユーザーコードが実行されてしまい、セキュリティの問題が度々出ている。それを解決するために以下の案が出された。
Object.prototype をエクゾチックオブジェクトとし、then を追加できなくする
Promise.resolve に thenable を受け付けないオプションを追加する
新たに [[InternalProto]] 内部スロットと GetNonInternal を定義し、プロトタイプチェーン探索時に[[InternalProto]] を持つオブジェクトに遭遇すると即座に undefined を返す
また他にも危険なユーザーコードを非同期にする extra ticks を入れたらどうかという案も上がっている。
ただし Svelte の Rich Harris 氏が then プロパティをゲッタープロパティでリアクティブを実現しているため、extra ticks の方法では既存コードが壊れるという指摘がされた。
どういう方針にするか特に結論は出なかった。
個人的には Object.prototype をエクゾチックオブジェクトにするか [[InternalProto]] を導入するのに賛成で、同様に toJSON などに対しても同じ機構を入れてほしいと思う。
Stage 0
配列が穴あきかどうかを判定する提案。
code: js
console.lof(Array.isSparse(arr); // true
ArrayLike に対して必ず false を返すことや、パフォーマンスの懸念から Stage 1 にならなかった。
Withdrown
N/A
その他
Freezing the Array Iterator (slides) | Kevin Gibbons %ArrayIterator%.prototype.next をフリーズしたい話。
正直以前の議論の繰り返しになっている感が否めない。
Proposed code of conduct addition: "write your own comments" (issue / slides) | Kevin Gibbons LLM によるコメントを許容しない話(typo チェックや翻訳など補助する役割に使う分には問題ない)。ISO や ACM がすでにポリシーを定めているらしい。
CoC とは別で AI_policy.md で記述することになった。
Preparing Summary and Conclusions (slides) | Samina Husain & Aki Rose Braun 会議で発表するときに事前に要約と結論を用意しておくこと。
複数の Source map を参照するときに、それが同一かどうか判定できるようにするハッシュを追加することでパフォーマンスを改善する提案。
code: json
{
"version": 3,
"file": "bundle.js",
"sources": [
"src/foo.ts",
"src/bar.ts"
],
"sourcesHash": [
"sha256-abc123...",
"sha256-def456..."
],
"mappings": "...",
"names": []
}
総括
今回は Math.sumPrecise と Uint8Array の basea64/hex メソッド追加が Stage 4 になった。
個人的には Stage 2 に入った Import Bytes が進むことによって、今まで各バンドラーが独自に拡張していたアセットファイルの読み込みを、言語仕様から提供されるようになることに期待している。