2019-12 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
度々話題に上がる class Foo extends null {} を許容する話。もっと調査が必要ということになった。
super() を呼び出すときに、その引数の実行より前に例外を投げてしまうのを修正する提案。
code: (js)
class A extends (class {}) {
constructor() {
console.log(0);
super(console.log(1));
}
}
Object.setPrototypeOf(A, null);
// logs 0, and throws
new A();
コンセンサスが得られた。
Iterable を for-of で回したときに Iterator#next() が実行されるようになっているが、AsyncIterable の場合は AsyncIterable#next(undefined) が呼ばれるようになっているのを修正する提案。
code: (js)
const o = {
next(...args) { console.log("args", args); return { done: true }; },
};
// logs "args", []
for (const item of o) {}
(async () => {
const o = {
next(...args) { console.log('args', args); return { done: true }; },
};
// logs "args", [undefined]
for await (const item of o) {}
})();
コンセンサスが得られた。
Sloppy Mode における eval のスコープが実装依存になってしまっているのを修正する提案。
code: (js)
var z = 'outer';
(function (
x = (eval('var z = "param"; print(z)'), // "param"
print(z)), // "param", Chakra: "outer"
y = print(z)) { // "outer", JavascriptCore: "param"
print(z); // "outer", JavascriptCore: "param"
})();
print(z); // "outer", JavascriptCore: "param"
コンセンサスが得られた。
TypedArray を継承したときに [[Set]] の仕様が Web の実装に即していないため修正する提案。
code: (js)
// Set, integer index
const o = { __proto__: new Int32Array(10) }; o1 = 42; print(Object.getOwnPropertyDescriptor(o, 1)?.value); // 42
print(o.__proto__1); // 0 code: (js)
// Set, non-integer numeric index
const o = { __proto__: new Int32Array(10) }; o1.3 = 42; print(Object.getOwnPropertyDescriptor(o, 1.3)?.value); // 42
print(o.__proto__1.3); // undefined [[Get]] の方は Chakra と SpiderMonkey の実装がおかしそうなため、仕様側は変えずに実装を修正する。コンセンサスが得られた。
Object.keys, Object.values, Object.entries, JSON.parse, そして JSON.stringify で EnumerableOwnPropertyNames internal method を使うのをやめて Reflect.ownKeys と同じ順番にする提案。コンセンサスが得られた。
Stage 4 (ES2020)
1日前などのように、相対的な時間を表現できる Intl メソッド。
Firefox 65, Chrome 71 (Node.js 12) に実装されて 3 つの polyfill がある状況らしい。Stage 4 になった 🎉
for-in の順番を Reflect.ownKeys と同じように定義するやつ。Stage 4 になった 🎉
V8/JavaScriptCore で実装され、予定通り Stage 4 になった 🎉
V8/JavaScriptCore/SpiderMonkey で実装され、こちらも予定通り Stage 4 になった 🎉
Stage 3
Atomics.wait の非同期(同期的なブロックをしない)版の提案。Atomics.wait ほどハイパフォーマンスではないものの、グッドパフォーマンスらしい。
レビューによって Atomics.wait と Atomics.waitAsync を合わせて一つの FIFO キューに詰めて順番を管理するようになった。Stage 3 になった。
セキュリティのために Template Literals の Function Tags がちゃんとタグ付きで実行されたかどうかをチェックするメソッドの提案。どの時に true/false にするべきかが共有された。
code: (js)
Array.isTemplateObjecttext; // true
Array.isTemplateObject("text"); // false Object.freeze(arr);
Array.isTemplateObject(arr); // false
Array.isTemplateObject(crossRealmsTemplateObject); // false
eval(Array.isTemplateObject\`${ "text" }\`); // true
セキュリティまわりのため、Realm や Proxy など考慮することが多そうな感じで大変そう。
RegExp match indices performance feedback (slides) | Shu-yu Guo, Joshua Litt RegExp#exec にマッチ位置を含める提案。
すべての結果に indices プロパティが付与されてしまうので、パフォーマンスが悪くなってしまう懸念について話された。仮にプロパティを getter にしたとしてもキャッシュしておく必要があり、再度 RegExp#exec を実行するという方針にしたとしても今度はその RegExp オブジェクトの方を保持する必要が出てきてしまう。
とりあえずある程度の性能劣化は無視する方向になりそう。
Stage 2
スタックトレースなどで函数の実装を隠す提案。レビューで Stage 3 がブロックされている状態。
Function#{length, name} は触らない方針になった。後はライブラリを使った場合とセキュリティとを差別化して、これらの問題が分割できそうなら提案も分割する必要があるということで調査することになった。
Trusted Types のために Modules に手を加える提案。Stage 2 になった。
In the past Microsoft had a once: field on URL.createObjectURL that allowed a URL only to be loaded once.
この話題がちょっとおもしろかった。
Stage 1
今のところ一番需要がある UUID v4 をデフォルトとして提供することになっている。
CSPRNG についてブラウザでは Crypto#getRandomValues() によって、Node.js では crypto.getRandomBytes() によって定義されている状況で ECMAScript にも盛り込む必要がある。例えば Math.getSecureRandomValues() のようなものを ECMAScript に入れるとか。
UUID 以前に randomness を ECMAScript にしっかり定義する必要があるということになった。
3rd party のコードを実行する仕組み。かつての Frozen Realms の後続の扱いっぽい。
以前は古い Frozen Realms の提案に対してさらにメソッドを追加した提案だった。
code: (js)
class Realm {
// From the prior Realm API proposal
const global -> object // access this realm's global object
eval(stringable) -> any // do an indirect eval in this realm
// We expect the rest of earlier proposal to be re-proposed eventually in
// some form, but do not rely here on any of the remainder.
// New with this proposal
static immutableRoot() -> Realm // transitively immutable realm
spawn(endowments) -> Realm // lightweight child realm
}
今後は IoT 向けの実装環境である Moddable XS や Blockchain Platforms を開発している MetaMask と Agoric チームによる SES を考慮した変換ツール LavaMoat の知見をもとに Compartment, Evaluator, そして Module Loader をベースとした SES API を作るとのこと。 https://gyazo.com/781a6f1fc0b5a359acb240ced0b9f8ff
ヒープの枯渇や Stack Overflow によって Out Of Memory が起きた際の処理を定義する提案。JavaScript の VM の中でエラーが起きたときに terminate(err) によってホストにその理由を投げるといったことを OOM にも入れようという話になっているっぽい。
Zalgo Backons という言葉を初めて知った。
code: (js)
q~.bar = p~.foo = 8;
というコードがあったときにこれを
code: (js)
p.then(obj1 => obj1.foo = 8);
q.then(obj2 => obj2.bar = 8);
ではなく
code: (js)
const p2 = p.then(obj1 => obj1.foo = 8); // Promise<void>
q.then(obj2 => obj2.bar = p2);
と解釈される問題が共有された。
Trusted Types のために eval に手を加える提案。こちらは Stage 2 にならず次回に持ち越しになった。
Array#filter のエイリアスとして Array#select を追加し、第二引数の函数の結果が false なものをフィルターするメソッドとして Array#reject を追加する提案。
Array#rejectのみ Stage 1 になった。
ES Modules や Dynamic Imports に属性を追加する提案。
code: (js)
// Potential Syntax
import name from "module" as "json";
import name from "module" with attr: "value", attr2: "value2";
import name from "module" with { attr: "value", attr2: "value2" };
import("module", "json");
import("module", {
attr: "value", attr2: "value2"
});
Stage 1 になった。inline metadata まわりの活用ができないか調査するとのこと。
これが入ると今まで <link rel="{preload, modulepreload}"> のタイミングで SRI(integrity 属性)入れていたのが(参考PR)、JavaScript 内で記述できるようになりそうな気がする。 演算子オーバーロードの提案。スコープの中に注入する形になっている。
code: (js)
// Usage example
import { Vector } from "./vector.mjs";
with operators from Vector;
Strict Mode から使わなくなっていた with を使うのはなるほどといった感じ。
ブラケットでプロパティにアクセスする場合に整数のプロパティのみでオーバーロード出来るようにするらしくて面白い。Stage 1 になった。
もともと Object.map が欲しいという提案だったが、Object から IterableIterator を作るメソッドとして Object.iterate{Keys, Values, Entries} を追加する話になった。まあ Iterator Helpers がくるだろうし、Iterator に寄せるのはよさそう。
モチベーションとしてはわざわざ Array を作るよりかはメモリを使わなくてよいところにある。Stage 1 になった。
長いこと Stage 0 にあった Arrow Functions で Generator を作る提案。実際にどのような構文にするかが議論中。 code: (js)
// Irregular
() =*> ...
// not the same order as in regular generator functions
() =>* ...
// also wrong order
() *=> ...
// ASI hazard
*() => ...
code: (js)
generator function() {}
const foo = async generator function() {};
class Foo {
// No more ASI hazard!
generator foo() {}
}
Stage 1 になった。
その他
async-of grammar ambiguity | Waldemar Horwat 歴史的に async も of も ES2015 から追加されたものなので予約語ではなく識別子として利用することが出来る。そのため構文解析の曖昧さによって async of が許されてしまっている。例えば以下のようなコードがあったときにどう解釈するかが規定されていない。
code: (js)
for (async of => of+1; ...;) {}
これを解決するためには解析時に2つ先のトークンを先読みする必要があることが認識された。
JSExplain demo (code, demo) | Alan Schmitt 仕様をもとにステップ実行できるツールのプロトタイプ。仕様を読むのを手助けするために作ったとのこと。
code: (js)
var x = 1;
x++;
x
を 3039 ステップで見ることが出来るが、あまりにも細かすぎてむしろわからなくなるのではw
Topic Policy on published code/polyfills in proposal repos
公式の polyfill をどうしていこうかという議題。Temporal 辺りと関係してそう。とりあえずプロダクションとしては扱ってほしくないので 0.x みたいな形でリポジトリに入れることになりそう?
Standard Library のために毎週一時間といった短いサイクルでリモート会議するのはどうかといった提案。次回に持ち越しになった。
総括
色々な提案について話されていたが、Agoric チームの方によるセキュリティ周りの話が多かった。特に SES は活用できそうなので注目していこうと思った。