2018-07 の TC39 meeting
まとめ
決まったこと
Web compatibility issues / Needs Consensus PRs
Normative: Reduce the number of ticks in async/await
await すると必ず Promise でラップする仕様になっていたため無駄に時間をかけてしまっていたのを修正する PR が出された。承認されそう。
Atomics.notify
ES2017 から入っていた Atomics API の Atomics.wake が Atomics.wait と似てて紛らわしいから Atomics.notify に変わった。SharedArrayBuffer もまだ使えない状況だったし、この際に変えてしまっていいかみたいな判断だったっぽい。
Stage 3
New name for global
結局のところどうなったのかよくわからなかった。
Object.fromEntries
Object.entries の逆函数。特に反対意見もなく Stage 3 に入った。
Stage 2
Decorators
今まで class や methods に付けるような仕様だったが、class private fields が Stage 3 になり、それも decorator に取り込むためにもっと汎用的に使えるセマンティックになったっぽい。
method decorators
code: (js)
class Counter extends HTMLElement {
@bound
render() {
}
}
{
kind: "method",
key: "render",
placement: "prototype",
descriptor: {
value: function render() { ... },
writable: true,
configurable: true,
enumerable: false
}
}
class decorators
code: (js)
@defineElement(‘num-counter’)
class Counter extends HTMLElement {
render() {
}
}
{
kind: "class",
elements: [{
kind: "method",
key: "render",
placement: "prototype",
descriptor: {
value: function render() { ... },
writable: true,
configurable: true,
enumerable: false
}
}]
}
field decorators
code: (js)
class Counter extends HTMLElement {
@observed
x = 0;
}
{
kind: "field",
key: "x",
placement: "instance",
descriptor: {
value: undefined,
writable: true,
configurable: true,
enumerable: true
}
initializer: function() { return 0; }
}
private name decorators (仕様に入れてる途中)
code: (js)
class Counter extends HTMLElement {
@observed
}
{
kind: "field",
key: { PrivateName: /* */,
get() { }, set() { }, description: "x",
placement: "instance",
descriptor: {
value: function() { return 0; },
writable: true,
configurable: true,
enumerable: true
}
}
今のステータスとしては spec を整えている段階で、それが済んだら Babel, TypeScript の実装も新しい方の仕様に直される感じ。
また export の後か前かの議論がなされてて export の後になりそう。
ArrayBuffer#transfer
非同期処理中に ArrayBuffer が別のところから変更されないかどうかを保証する函数。昔提案されていたものとは別物っぽいので注意。
code: (js)
function validateAndWriteSafeAndFast(arrayBuffer) {
const transferred = arrayBuffer.transfer();
// 実行中に arrayBuffer が変更されたら validateAndWriteSafeAndFast が例外を投げる
await validate(transferred);
await fs.writeFile("data.bin", transferred);
}
同時に提案されていた ArrayBuffer#realloc は別の提案としてスプリットされた。
RegExp Match Offsets
RegExp の結果にマッチした位置を含めるようにする提案。RegExp#exec に第二引数を生やすみたいな感じっぽい。
code: (js)
const re1 = /a*(?<Z>z)?/;
// 第二引数に関数を渡して map できる
const s1 = "xaaaz";
const m1 = re1.exec(s1, (start, end) => {start, end});
s1.slice(...m11) === "z"; m1.groups"Z".start === 4; s1.slice(...m1.groups"Z") === "z"; code: (js)
// 以下の2つは同じ意味になる
re1.exec(text);
re1.exec(text, (start, end, input) => input.slice(start, end));
Intl.DateFormat#formatRange
Date を2つ受け取って文字列を構成するやつ。Stage 2 になった。
code: (js)
let date1 = new Date(Date.UTC(2007, 0, 10, 10, 0, 0));
let date2 = new Date(Date.UTC(2007, 0, 10, 11, 0, 0));
let date3 = new Date(Date.UTC(2007, 0, 20, 10, 0, 0));
// > 'Wed, 10 Jan 2007 10:00:00 GMT'
// > 'Wed, 10 Jan 2007 11:00:00 GMT'
// > 'Sat, 20 Jan 2007 10:00:00 GMT'
let fmt1 = new Intl.DateTimeFormat("en", {
year: '2-digit',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
});
console.log(fmt1.format(date1));
console.log(fmt1.formatRange(date1, date2));
console.log(fmt1.formatRange(date1, date3));
// > '1/10/07, 10:00 AM'
// > '1/10/07, 10:00 – 11:00 AM'
// > '1/10/07, 10:00 AM – 1/20/07, 10:00 AM'
Intl.NumberFormat Unified Feature
すでにある Intl.NumberFormat をアップデートする提案。特に単位を扱えるようにするっていうのが目玉っぽい。
code: (js)
(16).toLocaleString("en-GB", {
style: "unit", // 今までは "decimal", "percent", "currency" のみだった
unit: "volume-liter", // 体積(リットル)
unitDisplay: "long"
});
// ==> "16 litres"
Stage 2 になった。
Stage 1
Explicit Resource Management
using を使ってリソースの開放をする提案。モチベーションとしては各仕様でばらばらになっているリソースの開放をするメソッドを1つの書き方に統一させたいというのがあるっぽい。
code: (js)
// Iteratos 系
iterator.return();
// WHATWG Streams
reader.releaseLock();
// NodeJS FileHandle
handle.close();
code: (js)
function * g() {
using (const handle = acquireFileHandle()) { // critical resource
...
} // cleanup
}
using (const obj = g()) {
const r = obj.next();
...
} // calls finally blocks in g
仕様としては Symbol.dispose, Symbol.asyncDispose を用意するっぽい。
……これって WeakRefs があったら GC されるときに開放処理出来るけど、それとは別でリソースの開放をインスタンス側に持たせるインターフェースっぽい。
using のセマンティックが微妙っていうことになった。
Dynamic Modules
Source Text ベースじゃない新しい Dynamic Modules があれば Node.js において Native Addons とか JSON ファイルを扱ったりとかをわざわざラッパーの JavaScript のコードを生成せずに出来る……みたいなモチベーションっぽい。
Dynamic Modules 自体は依存を持てないので Wasm とか Binary AST とかとは違う系譜らしい。
JS Standard Library
確か Temporal を入れるところで提案されていた新しい仕様。ECMAScript で定義されてる函数をどんどんリッチにしていったときに果たしてグローバルオブジェクトにどんどん入れていっていいのかみたいな議論がなされていて、Modules を拡張しようかみたいな話があった。それが Stage 1 に入ったっぽい。
地味に polyfill を入れられるようにすることが仕様に盛り込まれてて良さげ。
code: (js)
import { Statistics } from "std:Statistics";
const median = stats.median(); // 6
const geoMean = stats.getmean(); // 4.4812040415131
const stdev = stats.stdev(); // 2.5549654437397
今回共有された Layered APIs とも関連してる。
詳しくはこちらの記事で↓
Temporal (stay)
Date が使いにくいからどうにかしよう的なやつ。Immutable。
CivilDate, CivilTime, CivilDateTime がタイムゾーンを考慮しないクラス、Instant, ZonedInstant がタイムゾーンを考慮してナノ秒まで扱えるクラス。
month が 1 から始まるところにエモさを感じる……。
First Class Protocol (stay)
Swift で言うところの protocol 的なやつ。実装も持てるので Rust の trait の方が近いかも。Symbol の key を使って実装する感じ。
code: (js)
protocol Foldable {
foldr;
toArray() {
(m, a) => a.concat(m), []); }
get length() {
m => m + 1, 0);
}
contains(eq, e) {
(m, a) => m || eq(a, e),
false);
}
}
すでに存在するクラスに適用するために inline implementation も準備するっぽい。
code: (js)
protocol Foldable {
// ...
implemented by Array {
foldr(f, memo) {
// implementation elided
}
}
}
新しくクラスを作るときにも使える。
code: (js)
class NEList {
constructor(head, tail) {
this.head = head;
this.tail = tail;
}
implements protocol Foldable {
foldr(f, memo) {
// implementation elided
}
}
}
動的に設定するのも一応出来る。
code: (js)
protocol Functor { map; }
class NEList {
constructor(head, tail) {
this.head = head;
this.tail = tail;
}
}
function (f) {
// implementation elided
};
// (NEList implements Functor) が true を返すようにするのに要りそう
Protocol.implement(NEList, Functor);
Partial Application (stay)
Function#bind で this を束縛せずに引数を束縛できるやつ。
Cancellation (stay)
結局 DOM API に AbortController が入っちゃったので、それを壊さないように Symbol.cancelSignal といった Wellknown-Symbol を入れる方向性っぽい。
その他
TC53 Smart wearable systems and sensor-based devices
TC53 っていうウェアラブル端末向けの API の仕様を策定する団体を作るらしい。ECMAScript 互換でやっていくとのこと。
Originals
グローバルオブジェクト上のオブジェクトは大体が上書き可能なので、ブラウザが最初に作ったオリジナルの函数などを取得できるようにするっていうやつ。
code: (js)
// before: Array.isArray は変更されているかもしれない
Array.isArray(arr);
// after: 安全!!
const oArrayIsArray = getOriginalStatic("Array", "isArray");
oArrayIsArray(arr);
総括
Decorators がとりあえず停滞せずに進んでそうで良かった。JS Standard Library が結構便利そうなので発展してほしいが、Modules との絡みもあってブラウザに入るのはいつのことになるのか……。