Get to know MDN better
このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。
これまでに Emscripten などのツールを使用して他の言語からモジュールをコンパイルしたり、自分自身のコードを読み込んでして実行したりしました。次のステップは他の WebAssembly JavaScript API の使い方について学ぶことです。この記事では知る必要があることを説明します。
メモ: もし、この記事で説明している基本的な概念がよくわからない場合、 WebAssembly の概要を先に読んでからこの記事に戻ってきてください。
WebAssembly JavaScript API の使用方法と、Wasm モジュールを読み込んでウェブページ内で使用する方法を、ステップバイステップの例を通して実行してみましょう。
メモ: サンプルコードは webassembly-examples GitHub リポジトリーから参照してください。
まずは、 Wasm モジュールが必要です! simple.wasm をコピーしてローカルマシンの新しいディレクトリーの中に保存してください。
次に、 Wasm ファイルと同じディレクトリーに index.html という名前でシンプルな HTML ファイルを作成しましょう(簡単に利用できるテンプレートを持っていないのであれば、単純なテンプレートが利用できます)。
ここで、何が起こっているのか理解しやすくするために、 Wasm モジュールのテキスト表現を見てみましょう(WebAssembly 形式から Wasm への変換も参照してください)。
2 行目で 2 階層の名前空間を持つインポートの宣言があります。 — 内部関数 $i は my_namespace.imported_func からインポートされています。wasm モジュールにインポートするオブジェクトを記述するときに、この 2 階層の名前空間を JavaScript に反映させる必要があります。 <script></script> 要素を HTML 内に作成して、次のコードを追加してください。
Firefox 58 の新機能として、 WebAssembly モジュールを基礎となるソースから直接コンパイルおよびインスタンス化する機能があります。これは WebAssembly.compileStreaming() と WebAssembly.instantiateStreaming() メソッドを使用して実現します。これらのメソッドは、バイトコードを直接 Module/Instance インスタンスに変換することができるので、Response を ArrayBuffer に別途格納する必要がないため、ストリーミングではない対応するメソッドよりも簡単になっています。
この例(GitHub の instantiate-streaming.html デモや、ライブ版も参照してください)では、 instantiateStreaming() を使って Wasm モジュールを取得し、そこに JavaScript 関数をインポートしてコンパイルしてインスタンス化し、そのエクスポート関数にアクセスするまで、すべて一度に行っています。
スクリプトに以下の 1 ブロックを加えてください。
この結果、エクスポートした WebAssembly の exported_func 関数を呼び出し、インポートした JavaScript の imported_func 関数を呼び出し、WebAssembly インスタンスの中で提供した値 (42) をコンソールに記録することになりました。サンプルのコードを保存して、WebAssembly に対応しているブラウザーで読み込むと、これが実際に動作しているのがわかります。
メモ: これは複雑で長い例のほんの一部ですが、ウェブアプリケーション内で WebAssembly をどのように JavaScript と組み合わせて動作させることができるかを説明しています。別の場所でも言及していますが、 WebAssembly は JavaScript の置き換えを目指しているわけではありません。両方が協力して、お互いの強みを活かすことができます。
上記のようなストリーミングメソッドを使用できない、または使用したくない場合は、代わりにストリーミングメソッドではない WebAssembly.compile() / WebAssembly.instantiate() を使用することができます。
これらのメソッドはバイトコードに直接アクセスしないので、 Wasm モジュールをコンパイル/インスタンス化する前にレスポンスを ArrayBuffer に変換する余分な手順が必要になります。
同等のコードは次のようになります。
Firefox 54 以降では、開発者ツールのデバッガーパネルでウェブページに含まれる Wasm コードのテキスト表現を表示する機能があります。これを表示するためには、デバッガーパネルに移動して、 "wasm://" 項目をクリックしてください。
WebAssembly をテキストとして表示するだけでなく、 WebAssembly のテキスト表現を使用してすぐにデバッグを開始することができます(ブレークポイント、コールスタックの検査、ステップ実行など)。
WebAssembly の低レベルのメモリーモデルでは、メモリーは線形メモリーと呼ばれる型のない連続したバイト列として表現され、モジュール内のロード、ストア命令を使用して読み書きされます。このメモリーモデルでは、任意のロード、ストア命令は線形メモリー全体の任意のバイトにアクセスすることができます。これはポインターなどの C/C++ の概念を忠実に表現するために必要なものです。
しかし、利用可能なメモリー範囲がプロセス全体に及ぶネイティブの C/C++ プログラムとは異なり、特定の WebAssembly インスタンスがアクセスできるメモリーは、 WebAssembly Memory オブジェクトが含む特定の(潜在的に非常に小さな)範囲に制限されています。これにより、単一のウェブアプリで複数の独立したライブラリー(それぞれが内部で WebAssembly を使用している)を使用し、互いに完全に分離された個別のメモリーを持つことができます。さらに、新しい実装では共有メモリーを作成することもでき、これは postMessage() によってウィンドウとワーカーコンテキスト間で転送して複数の場所で使用することが可能です。
JavaScript では、Memory インスタンスはリサイズ可能な ArrayBuffer (または共有メモリーの場合は SharedArrayBuffer) とみなすことができます。ArrayBuffer と同様に、単一のウェブアプリケーションで多くの独立した Memory オブジェクトを作成することができます。Memory オブジェクトは初期サイズと最大サイズ (省略可) を指定して、WebAssembly.Memory() コンストラクターから作成することができます。
簡単な例を見ながら、探索を始めましょう。
もう 1 つのシンプルな HTML ページを(単純なテンプレートをコピーして)作成し、 memory.html という名前を付けてください。このページに <script></script> 要素を追加してください。
メモリーインスタンスを作成するために、次の行をスクリプトに追加します。
initial と maximum の単位は WebAssembly ページです。これらは 64KB に固定されています。上の例では、メモリーインスタンスは初期サイズが 640KB、最大サイズが 6.4MB であることを意味しています。
WebAssembly メモリーが持つバイト列は ArrayBuffer として buffer ゲッター/セッターから公開されています。例えば、線形メモリーの先頭ワードに直接、 42 を書き込むには次のようにします。
WebAssembly のメモリーは常にリトルエンディアンであるため、リトルエンディアンでの読み書きを強制する true の使用に注意してください。次に、以下を使用して同じ値を返すことができます。
デモで試してみましょう。これまでに追加した内容を保存してブラウザーで読み込んだ後、JavaScript コンソールで上の 2 行を入力してみてください。
メモリーインスタンスは Memory.prototype.grow() を呼び出すことで拡張することができます。引数は WebAssembly ページ単位で指定します。
Memory インスタンスの作成時に最大値が指定していて、この最大値を超えて拡張しようとすると RangeError 例外が発生します。エンジンは提供された上限を利用してメモリーを事前に確保しておくことで、より効率的なリサイズが可能になります。
メモ: ArrayBuffer の byteLength は変更不可であるため、 Memory.prototype.grow() 操作が成功した後、buffer ゲッターは新しい (新しい byteLength で) ArrayBufferを返します。そして、前の ArrayBuffer は「切り離された状態」になるか、メモリーから切り離されます。
関数と同様に、線形メモリーはモジュール内で定義することもインポートすることもできます。同じようにモジュールは任意でメモリーをエクスポートすることも可能です。これは JavaScript が WebAssembly インスタンスに対して新しく作成した WebAssembly.Memory をインポートで渡したり、Memory のエクスポートから(Instance.prototype.exports を介して)受け取れることを意味しています。
より複雑なメモリーの例を見て、上記のことを明確にしましょう。先に定義したメモリーインスタンスをインポートし、それを整数の配列で埋め込んで、それらを合計する WebAssembly モジュールです。これは memory.wasm で見ることができます。
memory.wasm のローカルコピーを以前と同じディレクトリーに作成します。
メモ: モジュールのテキスト表現は memory.wat を参照してください。
memory.html サンプルファイルに戻って、以前と同じように Wasm モジュールを読み取り、コンパイル、インスタンス化します。以下のものをスクリプトの最後に追加してください。
このモジュールはモジュール内部のメモリーをエクスポートします。instance という名前でモジュールの Instance が取得され、エクスポートされた関数 accumulate() を使用してモジュールの線形メモリー (mem) に直接入力された配列を合計する事ができます。指定された場所に、次のコードを追加してみましょう。
Memory オブジェクト自体でなく、Memory オブジェクトの buffer (Memory.prototype.buffer) から Uint32Array ビューを作成していることに注意してください。
メモリーのインポートは関数のインポートと同じように機能します。JavaScript 関数の代わりに Memory オブジェクトを渡すだけです。メモリーのインポートは 2 つの理由で役に立ちます。
メモ: 完全なデモは memory.html (動作例) を参照してください。
WebAssembly Table は JavaScript と WebAssembly コードの両方でアクセスできるリサイズ可能な 参照 の型付き配列です。Memory はリサイズ可能な生のバイト列を提供しますが、参照はエンジンに保証された値(このバイト列は安全性、移植性、安定性の理由からコンテンツによって直接読み書きしてはいけない)であるため、参照を格納するために使用することは安全ではありません。
テーブルは要素の型を持ち、テーブルに格納できる参照の型が制限されます。WebAssembly の現バージョンでは WebAssembly コード内で必要な参照の型は関数型の1つだけです。そして、これが唯一の正しい要素の型となります。将来のバージョンでは、さらに多くの要素の型が追加される予定です。
関数参照は関数ポインターを持つ C/C++ のような言語をコンパイルするために必要です。C/C++ のネイティブ実装では、関数ポインターはプロセスの仮想アドレス空間内の関数のコードの生のアドレスで表現されるため、安全性の理由から線形メモリーに直接格納することはできません。代わりに、関数参照はテーブルに格納されます。整数値のインデックスは線形メモリーに格納することができます。
関数ポインターを呼び出すときは、WebAssembly を呼び出す側でインデックスを指定します。インデックスを付けたり、インデックス付けされた関数参照を呼び出す前に安全な境界のチェックをすることができます。したがって、テーブルは現在、安全かつ移植可能に低レベルのプログラミング言語の機能をコンパイルするために使用される、低レベルのプリミティブです。
テーブルは Table.prototype.set() を通してテーブル内の値を1つ更新することができます。さらに、Table.prototype.grow() でテーブルに格納できる値の数を増やすことができます。時間の経過とともに間接呼び出しされる関数を変更することを許容し、これは 動的リンク技術 のために必要なものです。変化した値に対して JavaScript では Table.prototype.get() を通してすぐにアクセスできます。wasm モジュールからも同様です。
テーブルのシンプルな例を見てみましょう。紹介する WebAssembly モジュールは2つの要素 (要素0は13、要素1は42を返します) を持つテーブルをエクスポートするものです。モジュールは table.wasm から見つけられます。
table.wasm をローカルの新しいディレクトリーにコピーします。
メモ: このモジュールのテキスト表現は table.wat を参照してください。
HTML template を table.html という名前で同じディレクトリーにコピーします。
前と同じように、Wasm モジュールを読み取り、コンパイル、インスタンス化します。次のコードを HTML の body の末尾の <script> 要素に追加してください。
今度はテーブル内のデータにアクセスしてみましょう。コードの指定された場所に次の行を追加してください。
このコードはテーブルに格納されている各関数参照に順番にアクセスし、内包した値をコンソールに書き出すためにインスタンス化します。 Table.prototype.get() で各関数参照を取得した後、関数を実行するためには括弧を追加することに注意してください。
メモ: 完全なデモは table.html (動作例) を参照してください。
WebAssembly はグローバル変数のインスタンスを作成する機能を持っており、 JavaScript の両方からアクセスでき、1 つ以上の WebAssembly.Module インスタンスにわたってインポート/エクスポートが可能です。これにより、複数のモジュールを動的にリンクすることができるので、非常に便利です。
JavaScript の内部から WebAssembly のグローバルインスタンスを作成するには、次のような WebAssembly.Global() コンストラクターを使用します。
これは 2 つの引数を取ることがわかります。
グローバル変数について記述した 2 つのプロパティを含むオブジェクトです。
変数の実際の値を含む値。これは、指定されたデータ型と一致している限り、どのような値でもよい。
では、これをどう使うのでしょうか。次の例では、値を 0 とする mutable 型の i32 としてグローバルを定義しています。
次に、グローバル変数の値を変更してみます。最初は Global.value を使用して 42 に設定し、それから global.wasm モジュールからエクスポートされた incGlobal() 関数を使用して 43 にします(この関数は、指定された値に何でも 1 を加算し、新しい値を返します)。
メモ: GitHub の動作例 を見ることができます。ソースコードも見てください。
これで、WebAssembly の主要な構成要素の使用方法を説明しました。ここで、多重性の概念について触れておきましょう。これにより、WebAssembly はアーキテクチャの効率性において多くの進歩を遂げました。
多重性については、「WebAssembly テキスト形式の理解」の記事で多重性の働きについてみることができます。その中のテーブルの変更と動的リンクを参照してください。
この記事では WebAssembly JavaScript API の基本的な使い方について説明しました。WebAssembly モジュールを JavaScript のコンテキストに組み込む方法、その関数を使えるようすること、JavaScript でのメモリーとテーブルの使い方について。さらに、多重性の概念についても触れました。
This page was last modified on 2025年7月22日 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.