概要
node v8.0.0 がリリースされました。このバージョンからWebAssemblyがデフォルトで使用できるようになったので、試しにnode module(re2のvalidateするだけ)を作ってみました(re2-validator)。
準備
submoduleにre2を引っ張ってきてre2をconfigure makeします。
$ cd re2
$ emconfigure ./configure
$ make
コンパイル
emccで普通にコンパイルします。
$ emcc -Ire2 --bind -o dist/re2.js re2_binding.cc re2/obj/libre2.a -s WASM=1 --llvm-lto 1 --llvm-opts 3 -s NO_FILESYSTEM=1 -s EXPORTED_RUNTIME_METHODS="[]" --closure 1 -Oz --pre-js pre.js --post-js post.js
ここでre2本体以外にre2_binding.cc、pre.js、post.jsという自作のファイルを使用しています。それぞれ説明すると、
re2_binding.ccで関数をModule._validate
から使えるようにします。
#include "re2/re2/re2.h"
#include <emscripten/bind.h>
using namespace emscripten;
using std::string;
bool validate(const string& str) {
RE2 re(str, RE2::Quiet);
return re.ok();
}
EMSCRIPTEN_BINDINGS(_re2_) {
function("_validate", &validate);
}
pre.jsでModule.wasmBinaryFile
を設定して、正しいパスを指すようにします。これをやらないとパスがずれます。
var Module = {};
if (typeof __dirname === "string") Module["wasmBinaryFile"] = __dirname + "/re2.wasm";
post.jsで実際にJavaScriptから使いやすいように加工します(emccからclosure compilerのオプションを設定する方法がわからなかったので、es5的な感じで)。validate
関数で文字列をutf8のUint8Array
に変換してModule._validate
に渡します。ready
はModule._validate
の準備が完了するまで待つPromise
です。emscripten内部ではWebAssembly.instantiate
を使用して非同期にwasmモジュールがコンパイル、インスタンス化されるので必要です(対話環境だったら、あんまり気にしないですけどね)。
var re2_buffer = new Uint8Array(1024);
module.exports['validate'] = function(s) {
var size = stringToUTF8Array(s, re2_buffer, 0, 1024);
return Module['_validate'](re2_buffer.subarray(0, size));
};
module.exports['ready'] = new Promise(function(resolve) {
var intervalId = setInterval(function() {
if (!Module['_validate']) return;
clearInterval(intervalId);
resolve();
}, 1);
});
動作確認してみます。
$ node
> var re2Validator = require('./dist/re2');
> re2Validator.validate('(?!hello)'); // false
publishしたライブラリを使用する
すでに、node moduleとしてpublishしたものとします。npm i
して、まぁ、動作確認でやったことなんですが、動かしてみます。
$ npm i --no-save @ukyo/re2-validator
$ node
> var re2Validator = require('@ukyo/re2-validator');
> re2Validator.validate('(?!hello)'); // false
これでWebAssemblyを使用したnode moduleを公開できましたね!
まとめ
node v8.0.0で動作する、WebAssemblyを使用したnode moduleを作ってみました。node環境では特に問題なく動くことが確認できました。ブラウザ環境でwasmのパスどうするんだっていう課題はありますね(wasmを配列とかbase64にして埋め込むしかないのかな?)。