エクスポートされた WebAssembly 関数

エクスポートされた 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 });

fetchAndInstantiate('table.wasm').then(function(instance) {
  var tbl = instance.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)を作成し、fetchAndInstantiate() ユーティリティ関数を使用して 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 関数の注意する事項は:

  • length プロパティは wasm 内の関数シグネチャで宣言されている引数の数です。
  • name プロパティは toString() の結果で見えている wasm モジュール内での関数のインデックスです。
  • i64 型の値を受け取る、または返すエクスポートされた wasm 関数を呼び出そうとすると、現在 JavaScript 上で i64 を表現する的確な方法がないためエラーをスローします。これは将来的に変わる可能性があります。新しい int64 型が将来の標準で検討されており、wasm によって使用される可能性があります。

ドキュメントのタグと貢献者

 このページの貢献者: syu_kato
 最終更新者: syu_kato,