2024-07 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
Normative: Intl.DurationFormat Display negative sign on leading numeric-style zeroes (PR) (slides) | Ben Allen 特定の条件下でマイナスが表示されないバグの修正。
code: js
new Intl.DurationFormat('en', {hours: "numeric"}).format({minutes: -1, seconds: -2});
// currently: 0:01:02
// should be -0:01:02
Math.sqrt を implementation-approximated でなくする変更。
2014年の議論で全ての Math 函数の誤差を最大で 1 ULP にするべきという話が上がり合意されたが仕様変更はされなかった。その後アプリケーションからの報告によって何度か議題に上がり、2015年末に crlibm によって正しい丸めを実装できるかもしれないと期待されたが、当時フォローアップ調査の結果実用的でないとされた。今日ではまた状況が変わっているかもしれないとのこと。 Math.sqrt については WebAssembly 側にも命令があることもあって、implementation-approximated でなくしていいだろうということでこの話が上がった。承認された。
implementation-approximated については uhyo さんの記事が詳しい。
Normative: pretend primitives aren't iterable (PR) | Michael Ficarra 今後 Iterable を受け取る API はオブジェクトを期待するという合意が得られた。既に string には String.prototype[Symbol.iterator] が仕様の中に存在しており Iterable となっているが、これは失敗だったと捉えるようになったらしい。
Stage 3 Iterator Helpers では Iterator.from で string を受け入れるものの、Array.prototype.flatMap のコールバック函数の返り値が string な場合は例外を投げているらしい。
NB: This convention is new as of 2024, and most earlier parts of the language do not follow it. In particular, positional destructuring (both binding and assignment), array spread, argument spread, for-of loops, yield *, the Set and AggregateError constructors, Object.groupBy, Map.groupBy, Promise.all, Promise.allSettled, Promise.any, Promise.race, Array.from, the static from methods on typed array constructors, and Iterator.from (Stage 3 at time of writing) all accept primitives where iterables are expected.
今後追加される API としては Web Streams API の ReadableStream.from が AsyncIterable を受け入れるが、オブジェクトに限る方がいいのではないかと議論されている。
Deno に一度プリミティブの string で TypeError を投げる実装が入ったが、現状の仕様だとプリミティブラッパーオブジェクトの String を渡したときに AsyncIterable に変換されることがわかった。これは考慮されていなかったためリバートされ、再度議論することとなった。
WICG で提案されている Observable もまだ議論中。
Normative: Avoid capturing lexical context in indirect eval (PR, slides) | Nicolò Ribaudo 前提として Dynamic Imports はその実行箇所が (classic) script か module かによって相対パスのベース URL が異なっている。
現在の仕様だと indirect eval 内で Dynamic Imports を使用した場合、通常の eval と同様にダイナミックスコープを作るようになっている。これにより indirect eval の実行箇所が (classic) script か module かどうかが伝播されている。しかしブラウザによって実装が異なっている。
Firefox: 仕様通りに実装されている
Chrome: eval や Function では実装されているが、setTimeout では実装されていない
Safari: 実行箇所の (classic) script/module が伝播されておらず、実装されていない
そもそも実行箇所によって挙動が変わるのがどうなのかという話になり、現在の HTML のイベントハンドラの仕様同様に (classic) script/module の情報を伝播させないよう evalContext の ScriptOrModule に null を設定する Normative Change。つまり Safari の挙動を採用し、パス解決のベース URL は Realm のトップレベルによって決まることになる。
Stage 2.7 として進めることとなった。
Normative: Propagate active ScriptOrModule with JobCallback Record (PR) (slides) | Chengzhong Wu HTML の HostEnqueuePromiseJob の仕様が ECMA262 が要求する制約に合っていない状態になっており、仕様として正しい挙動というものがない状態になっている。それにより Promise.prototype.then の中で iframe など別の Realm の location.href を変更したときのパス解決がブラウザによって異なっている。
https://gyazo.com/4875962058f219bbc6df4c2ad97625cc
Stage 2 として進めることになった。TG3 でレビューし、WPT を用意した後に Stage 3 にするとのこと。
Add text about locale installation in browser implementations as fingerprinting vector (PR/Discussion) (slides) | Ben Allen フィンガープリント対策として、ユーザーの操作によってユーザーエージェントにロケールが追加されたとしてもそれが JS からわからないようにするべきとする項目を追加する話。
Normative: Make DefaultNumberOption in ECMA-402 truncate options before validating range (PR) (slides) | Ben Allen ECMA402 で数値をオプションで受け取る函数が ECMA262 と異なり、先にバリデーションチェックした後に小数点以下切り捨てなどをしている。これを ECMA262 に合わせる Normative Change。
結論としては挙動に一貫性を持たせるよりも先にバリデーションを通す方が価値があり、更に変更する労力に見合わないということで PR はクローズされた。
Stage 4 (ES2025)
N/A
Stage 3
Source phase imports update (slides) | Luca Casonato WebAssembly に対する ES Modules の提案は通常の読み込みと、この Source Phase Imports がある状態にある。
code: js
// Wasm 内部に依存する JS モジュールへのパスが直接書いてある
import { fib } from "fib.wasm";
code: js
// Wasm には依存する函数のみが書かれており、JS など実行環境で指定してあげる(今まで通り)
import source fibModule from "fib.wasm";
const fibInstance = new WebAssembly.Instance(fibModule, options);
const { fib } = fibInstance.exports;
WasmCG で Phase 3 となり、HTML Integration では Gecko と WebKit から承認されている状況。Chromium はまだ。
なお通常の Wasm の読み込みに type: "wasm" を指定しない方針。また今のところ Wasm 自身には Import Attrubutes を入れない仕様のため JSON は読み込めない。
V8 が Import Attribute から assert キーワードを取り除いたことにより、仕様からも deprecated として記述されていた assert キーワードが取り除かれた。
細かい修正があった。
こちらも細かい修正があった。
Stage 3 になった。
Stage 2.7
引数に number でイテレーションの回数を渡すことに対して懸念があった。
Stage 3 にならなかった。
Iterator.prototype.zipToObject が Iterator.prototype.zipKeyed にリネームされた。
Stage 2
Array.isArray は Proxy でラップされた Array を渡しても true を返すようになっているが、Error.isError からはその機能をなくし false を返すようにする変更が入った。
次回 Stage 2.7 にしたいとのこと。
Stage 2.7 にはならなかった。
次回 Stage 2.7 にしたいとのこと。
Stage 1
細かい話がなされた。
前回の会議で Stage 2 Async Iterator Helpers で並行処理に関する提案を切り出して Stage 1 としてやっていきたいという話があった。それが Concurrency Control と Unordered Async Iterator Helpers に分離されたらしい。
https://gyazo.com/b3201df4a463eb4c927a4569781924c4
新たに Governor プロトコルを導入して CountingGovernor (Semaphore) クラスを導入する。
https://gyazo.com/5de12800801d5d5186235ded39b9df06
Stage 1 になった。
AsyncIterator.prototype.unordered を追加し、UnorderedAsyncIterator インスタンスを作る提案。
https://gyazo.com/3bbc488e659c0107eaf7b418836a2d70
https://gyazo.com/6a6923bcfdd46ab7b02a3f2b90e62eee
https://gyazo.com/647060aaf004013b62ea72ceb03708da
この提案は Concurrency Control に依存する。
Stage 1 になった。
Stage 0
N/A
Withdrown
N/A
その他
Stage 2 の提案の棚卸し。
Updates from TypeScript: deferred and immediate (slides) | Daniel Rosenwasser TypeScript でコールバックが遅延されて実行される deferred と即座に実行される immediate を追加したい話。
code: ts
declare function setTimeout(deferred callback: () => void): number;
interface Array<T> {
forEach(immediate callback: (el: T, index: number) => void): void;
}
総括
今回は Normative Change の話題が多かった。個人的には WebAssembly のモジュール周り、そして Unorderd Async Iterator Helpers が気になった。Governor プロトコルが難しそうで、順番が保証されない Pull ストリームを Async Generator Functions で書くのは大変そうな気がする……。