io.js v3.0.0 がリリースされました。

io.js v3.0.0. がリリースされました。めでたい!

f:id:yosuke_furukawa:20150807002243p:plain
iojs.org


さらにめでたいことに、次のv4.0.0リリースはとうとうお待ちかねの Node.js との converged されたバージョンになります。

既にコアメンバーは v4.0.0 のリリースに向けて動き出しています。
今回の v3.0.0 は v4.0.0 、つまり converged される Node.js のアルファ版という位置づけです。

v2.0.0 から v3.0.0 がリリースされるまでに作られた機能を振り返っていきましょう。

--trace-sync-io オプションが追加される (v2.1.0)

--trace-sync-io オプションが追加されました。これは、fs.readFileSyncやexistSync といった 同期的に動作するコードを見つけてwarnings を出すオプションです。

Nodeに慣れていない人がうっかり同期のコードを書いてしまった時などに使います。もちろん、Syncのメソッドも使いどころは沢山あるので、慣れている人は今更かもしれませんが、チームで開発していて習熟度に差がある時などは便利です。

単純にwarnings を出すのではなく、tickが回ってから出るような仕組みになっているのでトップレベルで取った時には出ない。非同期実行中に同期を混ぜると出るような作りになっている。

const fs = require('fs');
const data = fs.readFileSync('file.js'); // ここじゃ警告は出ない
console.log(data.toString());
fs.readFile('file.js', function(err, data){
  fs.writeFileSync('file.js', data.toString()); // NG ここでは警告が出る
  console.log(data.toString());
});
WARNING: Detected use of sync API
    at fs.openSync (fs.js:549:18)
    at fs.writeFileSync (fs.js:1155:15)
    at /private/tmp/test/file.js:3:6
WARNING: Detected use of sync API
    at fs.writeSync (fs.js:663:20)
    at fs.writeFileSync (fs.js:1164:24)
    at /private/tmp/test/file.js:3:6
WARNING: Detected use of sync API
    at fs.closeSync (fs.js:518:18)
    at fs.writeFileSync (fs.js:1172:8)
    at /private/tmp/test/file.js:3:6

requireの高速化 (v2.2.0)

requireが内部的にfs.statSyncとfs.readFileSyncを使ってファイル読み込みを頻繁に行っていた箇所を特定し、性能を改善しました。これにより、requireが50倍高速になりました。

fs.statSyncやfs.readFileSyncは中でエラーオブジェクトやStatオブジェクトをメモリ中に持つんですが、メモリ中に持っても requireの時はエラーを無視して別なパスを探索する事が多いので実装上に無駄が多く、またGCフレンドリーでもないという話で内部的にエラーやオブジェクトを保持しないメソッドが作成され、それを使って高速化されました。

https://github.com/nodejs/io.js/pull/1801

os.homedir メソッドの追加 (v2.3.0)

osのホームディレクトリを返すためのメソッドが追加されました。

const os = require('os');
console.log(os.homedir()); // /User/yosuke

Buffer が TypedArray で再実装される (v3.0.0)

Node.js の至るところで使われている Buffer オブジェクトがこれまで独自機構で作成されていたものが TypedArray で再実装されました。これは v8 で使っていたAPIが消えたことの影響を受けて修正されたものです。これに伴い、 Buffer の コンストラクタ関数に TypedArray がそのまま受け付けられるようになりました。

const Buffer = require('buffer').Buffer;
const ab = new ArrayBuffer(16);
var buf = new Buffer(ab); // Buffer constructor accepts ArrayBuffer.

console.log(buf instanceof Uint8Array); // true
console.log(buf instanceof Buffer); // true

buf.writeUInt32BE(0x61626364, 0);

console.log(buf.toString()); //abcd

unicode 文字列 (v3.0.0)

ES2015の unicode escapedな文字列が許可されるようになりました。これでunicode文字を \u{xxxxx} で表現できるようになります。

console.log('\u{1F363}'); // 🍣
console.log('\u{1F4A1}'); // 💡

これでサロゲートペアの表現でわざわざ2文字として扱う必要がなくなります。

console.log('\uD867\uDE3D'); // 𩸽 (ES5で表現)
console.log('\u{29E3D}'); // 𩸽 (ES6から)

余談ですが

今、 io.js collaborators summit のためにSanFranciscoに来ています。 今から行ってきます!

github.com