2021-01 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
Runtime Semantics for MemberExpression do not conform to web reality (issue, PR) 仕様ではメンバ式で左辺に undefined と null を許容していないが、Web Reality としてはそれは許容されているので修正する提案。
code: (js)
'use strict';
undefined.foo = console.log('whoops');
承認された。
Stage 4 (ES2021)
2つの Date を受け取って範囲の文字列を作る Intl メソッド。Stage 4 になった 🎉
Stage 3
indexable なクラスに対して at メソッドを追加し、引数に負数を入れた場合に後ろから値が取れる提案。
Chrome 89, Firefox 85, Safari Tech Preview 118 で実装されたが、とあるサイトで配列をハッシュテーブルとして利用しており、at プロパティの有無チェックをしているため互換性の問題が出てしまった。
Chrome, Safari Tech Preview についてはすでに unship されている。
RegExp#exec の返り値に indices プロパティを追加し、マッチした位置を取得できるようにする提案。
以前は問答無用で indices プロパティを追加する話だったが、パフォーマンスの問題が指摘されていた。そこで RegExp に新たなフラグとして d を指定したときのみ indices プロパティを追加する話になった。
JSON modules for stage 3 (slides) | Myles Borins, Daniel Ehrenberg, Sven Sauleau, Daniel Clark ES Modules で JSON ファイルをオブジェクトとして読み込むことが出来るシンタックス。
code: (js)
import json from "./foo.json" assert { type: "json" };
レビュー途中だが、とりあえず条件付きで Stage 3 ということになった。
クラスの static 変数やメソッドを static initialization blocks シンタックスを使って定義することが出来るようにする提案。これによって static 変数、メソッドを定義するときに何らかの処理が必要な場合に即時函数などで括る必要がなくなる。
code: (js)
class C {
static x = ...;
static y;
static z;
static {
try {
const obj = doSomethingWith(this.x);
this.y = obj.y;
this.z = obj.z;
}
catch {
this.y = ...;
this.z = ...;
}
}
}
細かい仕様として new.target が undefined を返すことや、var のスコープが作られることが決まった。Stage 3 になった。
Stage 2
セキュリティのために Template Literal の Tag Functions として実行されたかどうかを判定することが出来る函数。この函数を追加することによってセキュリティを担保するというのが不十分という結論に至った。
細かな API の修正が進んでいるのと、Temporal.ZonedDateTime によって作られる文字列("1995-12-07T03:24:30.000003500+08:00[America/Los_Angeles]")を RFC3339 の拡張としてドラフトを書いているステータス。
3月の会議で Stage 3 にするとのこと。……やっとか。
ArrayBuffer をリサイズできるクラスの提案。
Realms updates (slides tbd) | Leo Balter, Caridy Patiño 別のグローバルオブジェクト、組み込み函数としてコードを扱えるようにする提案。基本的にプログラム単位でグローバル変数の競合などを防いで管理しやすくする目的。
code: (ts)
declare class Realm {
constructor();
readonly globalThis: typeof globalThis;
import(specifier: string): Promise<Namespace>;
}
Private fields に対してそのプロパティが存在するかどうかを判定することが出来るシンタックスの追加。
code: (js)
class Foo {
test(obj) {
}
}
Dynamic Imports や Web Workers, Worklets などで実行するコードは別ファイルとして用意しないといけないことになっているが、module blocks シンタックスを使うことでメインスレッドと同じファイルで容易に扱うことが出来る提案。
code: (js)
let moduleBlock = module {
export let y = 1;
};
let moduleExports = await import(moduleBlock);
assert(moduleExports.y === 1);
assert(await import(moduleBlock) === moduleExports); // cached in the module map
Stage 2 になった。
昔からほぼほぼ放置されていた Do Exporession の提案。変数の定義などのためにをブロックスコープ内でコードを実行することが出来る。
code: (js)
let x = do {
let tmp = f();
tmp * tmp + 1
};
return やループについての仕様の矛盾点が指摘された。
Locale に対しての情報を取得する Intl メソッドを追加する提案。週の情報や、文字の方向などを取得できる。
code: (js)
const he = new Intl.Locale("he");
he.weekInfo; // { firstDay: 7, weekendStart: 5, weekendEnd: 6, minimalDays: 1 }
const ar = new Intl.Locale("ar");
ar.textInfo; // { direction: "rtl" }
const ja = new Intl.Locale("ja")
もともと計測単位についても盛り込まれていたが、それを取り除いて Stage 2 になった。
ブラウザが持っている翻訳文字列を取得することが出来る Intl メソッドの拡張。新たにカレンダーと計測単位の文字列を取得できる。Stage 2 になった。
Stage 1
eval や Function コンストラクタに与える引数に Trusted Types の TrustedScript を許容するために仕様を更新する提案。
Do Expression に非同期を追加したもの。
code: (js)
let x = async do {
let res = fetch(x);
(await res).json()
};
x.then(console.log);
Stage 1 になった。
オブジェクトがそのクラスのインスタンスかどうか判定するのに instanceof がよく使われる。これは Symbol.hasInstance を使ってカスタムすることが出来るが、記述するには困難になってしまっている。
例えば以下のようなコードを書いてしまった場合これは無限ループになる。
code: (js)
class C {
return obj instanceof C;
}
}
よってインスタンスのプロトタイプについてチェックしたい場合は、自分でプロトタイプチェーンするコードを書く必要がある。
ここで新たにメタメソッドとして class.hasInstance を用意することで Symbol.hasInstance によって操作される前のデフォルトの instanceof の処理を扱うことが出来る。
code: (js)
class C {
return class.hasInstance(o);
}
}
これについては自分も考えたことがあるのでわかる。Stage 1 になった。
Intl.DateTimeFormat のオプションの timezone に新たに "shortGMT", "longGMT", "shortWall" そして "longWall" を追加する提案。
Stage 1 になった。
Intl.DateTimeFormat のオプションとして era を扱うことが出来る "eraDisplay" を追加する提案。
Stage 1 になった。
正規表現に対して差や交差のオペレーターを追加する提案。
code: (js)
// Ascii コードを除いた数値に一致する
/[\p{Decimal_Number}--0-9]/ // クメール語の Letter, Mark そして Number に一致する
Stage 1 になった。
文字列から RegExp を作るときのためのエスケープ用メソッドの追加。
code: (js)
RegExp.escape("Buy it. use it. break it. fix it.") // "Buy it\. use it\. break it\. fix it\."
Stage 1 になった。
新たに ES Modules のロードツリーに lazyInit フラグを付け、それから読み込んだモジュールは最初に実行されたタイミングで評価される提案。
code: (js)
import aModule from "a-module" with { lazyInit: true };
function reralyUsedA {
// 略
aModule(); // この函数の評価は初めて使ったときに行われる
}
Dynamic Imports のように非同期として扱うのではなく、ファイル自体は予め読み込むことが出来、モジュールから読み込んだものも同期的に扱われる。
……パフォーマンス目的とはいえ、依存の管理が難しい感じがするな……。Stage 1 になった。
Accept-Language HTTP ヘッダーのように要求された言語と、サイトが用意している言語のリストからマッチするものを選択してくれる Intl メソッドの追加。マッチの仕方のオプションとして "lookup" と "best fit" が用意されている。
code: (js)
配列の後ろから値を取るシンタックスとして arr[^1] を追加する提案。他の提案であるスライス構文にマージして進めていくらしい。
Array のミッシングピースとして後ろから find, findIndex することが出来る findLast, findLastIndex を追加する提案。
Stage 1 になった。
その他
Brand checking についての議論。将来的に仕様の形にまとめて Stage 1 にするつもりらしい。
The nature of protocols in JavaScript (issue, slides) (late addition) | Daniel Ehrenberg Temporal のカスタムカレンダーや TimeZone をどう定義するかの議論。クラス? Symbol メソッド?
Spec complexity and planning for future implementations (slides, discussion) | Shane F. Carr, Zibi Braniecki Intl を定義する ECMA-402 についての提案のコストを減らす議論。
総括
Temporal が Stage 3 にするする詐欺みたいな状況が長いこと続いていたがようやく Stage 3 になりそうでよかった。
また新しい提案として defer module import eval が気になった。モジュール周りはフロントエンドだと webpack や rollup などのバンドラーで対応する世界観になっているが、これはエミュレート出来ないけどどうするんだろうか……?
また正規表現に差や交差が提案されているのが面白い。