エクスポートされた WebAssembly 関数は WebAssembly 関数が JavaScript でどのように表現されるのか、この記事では、もう少し詳しく説明します。
エクスポートされた...とは?
エクスポートされた WebAssembly 関数は WebAssembly 関数を表現する JavaScript ラッパーです。それらを呼び出したときにバックグラウンドでいくつかの動作を行います。引数を wasm で使える型に(例えば、JavaScript の数値を Int32 に)変換し、wasm モジュール内の関数に渡し、実行し、結果を変換して JavaScript 側に戻します。
エクスポートされた WebAssembly 関数は次の 2 つの方法で取得できます:
- 既存のテーブルの
Table.prototype.get()
を呼び出す。 - wasm モジュールインスタンスの
Instance.exports
を通してエクスポートされた関数にアクセスする。
いずれにしても、同じ種類の内在する関数のラッパーを取得できます。JavaScript からみると、すべての wasm 関数は JavaScript 関数のようにみえます。しかし、これは wasm 関数オブジェクトインスタンスによってカプセル化されており、アクセスする方法は限られています。
例
物事を明らかにするために例を見ていきましょう(例は GitHub の table-set.html と 動作例、wasm の テキスト表現 を参照してください):
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
WebAssembly.instantiateStreaming(fetch('table.wasm'))
.then(function(obj) {
var tbl = obj.instances.exports.tbl;
console.log(tbl.get(0)()); // 13
console.log(tbl.get(1)()); // 42
otherTable.set(0,tbl.get(0));
otherTable.set(1,tbl.get(1));
console.log(otherTable.get(0)());
console.log(otherTable.get(1)());
});
ここでは、WebAssembly.Table
コンストラクタを使用して JavaScript からテーブル(otherTable
)を作成し、WebAssembly.instantiateStreaming()
ユーティリティ関数を使用して table.wasm をページに読み込みます。
そのあと、モジュールからエクスポートされた関数を取得し、関数の参照を tbl.get()
を通して取り出し、それぞれを実行した結果をコンソールに出力します。次に、 set()
を使用して、tbl
テーブルと同じ関数への参照を otherTable
テーブルに含まれるようにします。
確認するために、otherTable
から参照を取得し直し、その結果もコンソールに出力します(同じ結果が得られます)。
それらは本当の関数です
前の例で、Table.prototype.get()
のそれぞれの返り値はエクスポートされた WebAssembly 関数でした。まさに私達が話していたことです。
これらは WebAssembly 関数のラッパーであるのに加えて本当の JavaScript 関数 であることに注意してください。上の例を WebAssembly をサポートするブラウザーでロードして、コンソール上で実行すると:
var testFunc = otherTable.get(0);
typeof testFunc;
結果として関数が返されます。この関数は他の JavaScript の他の 関数 と同じように扱うことができます(call()、
bind()、その他
)。testFunc.toString()
は興味深い結果を返します:
function 0() {
[native code]
}
これはラッパー型の性質のアイデアの多くを提供します。
エクスポートされた WebAssembly 関数について他の注意事項は: