From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../ja/webassembly/loading_and_running/index.html | 112 +++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 files/ja/webassembly/loading_and_running/index.html (limited to 'files/ja/webassembly/loading_and_running') diff --git a/files/ja/webassembly/loading_and_running/index.html b/files/ja/webassembly/loading_and_running/index.html new file mode 100644 index 0000000000..4950607fc2 --- /dev/null +++ b/files/ja/webassembly/loading_and_running/index.html @@ -0,0 +1,112 @@ +--- +title: WebAssemblyコードのロードと実行 +slug: WebAssembly/Loading_and_running +tags: + - Fetch + - JavaScript + - WebAssembly + - XMLHttpRequest + - バイトコード +translation_of: WebAssembly/Loading_and_running +--- +
{{WebAssemblySidebar}}
+ +

JavaScript で WebAssembly を使用するには、まずコンパイル/インスタンス化の前にモジュールをメモリにプルする必要があります。この記事では、WebAssembly バイトコードをフェッチするために使用できるさまざまなメカニズムのリファレンスと、それをコンパイル/インスタンス化して実行する方法について説明します。

+ +

何が問題なの?

+ +

WebAssemblyは <script type='module'> または ES2015 の  import 文とまだ統合されていないため、インポートを使用してブラウザでモジュールをフェッチする組み込みの方法はありません。

+ +

以前の {{jsxref("WebAssembly.compile")}}/{{jsxref("WebAssembly.instantiate")}} メソッドでは、生のバイトをフェッチした後 WebAssembly モジュールのバイナリを含む {{domxref("ArrayBuffer")}} を作成し、コンパイル/インスタンス化する必要があります。これは文字列(JavaScript ソースコード) をバイトの配列バッファ (WebAssembly ソースコード)で置き換えることを除いて、new Function(string) に似ています。

+ +

新しい {{jsxref("WebAssembly.compileStreaming")}}/{{jsxref("WebAssembly.instantiateStreaming")}}  メソッドは、より効率的です。ネットワークからの生のバイトストリームに対して直接アクションを実行し、 {{domxref("ArrayBuffer")}} ステップの必要性がなくなりました。

+ +

では、どのようにバイト列を配列バッファに読み込んでコンパイルするのでしょうか? 次の章で説明します。

+ +

Fetchを使用する

+ +

Fetch はネットワークリソースを取得するための便利でモダンな API です。

+ +

wasm モジュールをフェッチする最も簡単で効率的な方法は、新しい {{jsxref("WebAssembly.instantiateStreaming()")}} メソッドを使用することです。このメソッドは最初の引数として fetch() を呼び出すことができ、1つのステップでフェッチ、モジュールをインスタンス化し、サーバからストリームされる生のバイトコードにアクセスします。

+ +
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
+.then(results => {
+  // Do something with the results!
+});
+ +

直接ストリームでは動作しない古い {{jsxref("WebAssembly.instantiate()")}} メソッドを使用した場合、フェッチされたバイトコードを {{domxref("ArrayBuffer")}} に変換する必要があります。次のようにです:

+ +
fetch('module.wasm').then(response =>
+  response.arrayBuffer()
+).then(bytes =>
+  WebAssembly.instantiate(bytes, importObject)
+).then(results => {
+  // コンパイルされた結果(results)で何かする!
+});
+ +

余談: instantiate() のオーバーロード

+ +

{{jsxref("WebAssembly.instantiate()")}} 関数は2つのオーバーロードを持ちます — 1つ目 (上の例を参照)はバイトコードを受け取ってプロミスを返します。解決されたプロミスでコンパイルされたモジュールと、それをインスタンス化したものを含むオブジェクトとして受け取ります。オブジェクトの構造は以下のようになります:

+ +
{
+  module : Module // コンパイルされた WebAssembly.Module オブジェクト,
+  instance : Instance // モジュールオブジェクトから生成された WebAssembly.Instance
+}
+ +
+

: 通常はインスタンスのみを気にしますが、キャッシュする場合や、postMessage() を使用して別のワーカーやウィンドウと共有する場合や、インスタンスをさらに作成したい場合に備えて、モジュールを用意すると便利です。

+
+ +
+

: 2番目のオーバーロードフォームは {{jsxref("WebAssembly.Module")}} オブジェクトを引数としてとり、結果としてインスタンスオブジェクトを直接含む Promise を返します。2番目のオーバーロードの例を参照してください。

+
+ +

WebAssembly コードを実行する

+ +

JavaScript 内で WebAssembly インスタンスが 有効になったら {{jsxref("WebAssembly.Instance/exports", "WebAssembly.Instance.exports")}} プロパティを通してエクスポートされた機能を使い始める事ができます。コードは以下のようになるでしょう:

+ +
WebAssembly.instantiateStreaming(fetch('myModule.wasm'), importObject)
+.then(obj => {
+  // Call an exported function:
+  obj.instance.exports.exported_func();
+
+  // or access the buffer contents of an exported memory:
+  var i32 = new Uint32Array(obj.instance.exports.memory.buffer);
+
+  // or access the elements of an exported table:
+  var table = obj.instance.exports.table;
+  console.log(table.get(0)());
+})
+ +
+

: WebAssembly モジュールからのエクスポートの仕組みの詳細については WebAssembly JavaScript APIを使用する と WebAssemblyテキストフォーマットを理解する を参照してください。

+
+ +

XMLHttpRequest を使用する

+ +

XMLHttpRequest は Fetch よりやや古いですが、引き続き型付き配列を取得するために適切に使用することができます。繰り返しますが、モジュール名は simple.wasm とします:

+ +
    +
  1. {{domxref("XMLHttpRequest()")}} インスタンスを生成して、{{domxref("XMLHttpRequest.open","open()")}} メソッドでリクエストをオープン、リクエストメソッドを GET に設定し、フェッチするためのパスを宣言します。
  2. +
  3. キーは {{domxref("XMLHttpRequest.responseType","responseType")}} を使用してレスポンスタイプを 'arraybuffer' にすることです。
  4. +
  5. 次に {{domxref("XMLHttpRequest.send()")}} を使用してリクエストします。
  6. +
  7. そのあと、ダウンロードが終了したときに {{domxref("XMLHttpRequest.onload", "onload")}} イベントハンドラから関数を実行します — この関数内で {{domxref("XMLHttpRequest.response", "response")}} プロパティから array buffer を取得し、Fetchで行ったように {{jsxref("WebAssembly.instantiate()")}} メソッドに渡します。
  8. +
+ +

最終的なコードは以下のようになります:

+ +
request = new XMLHttpRequest();
+request.open('GET', 'simple.wasm');
+request.responseType = 'arraybuffer';
+request.send();
+
+request.onload = function() {
+  var bytes = request.response;
+  WebAssembly.instantiate(bytes, importObject).then(results => {
+    results.instance.exports.exported_func();
+  });
+};
+ +
+

: 動作例は xhr-wasm.html を参照してください。

+
-- cgit v1.2.3-54-g00ecf