From d8fdbaa9c73f6f370d515788e2ab255bc8abb5c3 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 18 Aug 2022 11:28:42 +0900 Subject: [PATCH 1/4] =?UTF-8?q?/webassembly=20=E4=BB=A5=E4=B8=8B=E3=81=AE?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=B8=80?= =?UTF-8?q?=E6=8B=AC=E5=A4=89=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/webassembly/c_to_wasm/{index.html => index.md} | 0 files/ja/webassembly/caching_modules/{index.html => index.md} | 0 files/ja/webassembly/concepts/{index.html => index.md} | 0 files/ja/webassembly/existing_c_to_wasm/{index.html => index.md} | 0 files/ja/webassembly/exported_functions/{index.html => index.md} | 0 files/ja/webassembly/{index.html => index.md} | 0 files/ja/webassembly/loading_and_running/{index.html => index.md} | 0 files/ja/webassembly/rust_to_wasm/{index.html => index.md} | 0 files/ja/webassembly/text_format_to_wasm/{index.html => index.md} | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename files/ja/webassembly/c_to_wasm/{index.html => index.md} (100%) rename files/ja/webassembly/caching_modules/{index.html => index.md} (100%) rename files/ja/webassembly/concepts/{index.html => index.md} (100%) rename files/ja/webassembly/existing_c_to_wasm/{index.html => index.md} (100%) rename files/ja/webassembly/exported_functions/{index.html => index.md} (100%) rename files/ja/webassembly/{index.html => index.md} (100%) rename files/ja/webassembly/loading_and_running/{index.html => index.md} (100%) rename files/ja/webassembly/rust_to_wasm/{index.html => index.md} (100%) rename files/ja/webassembly/text_format_to_wasm/{index.html => index.md} (100%) diff --git a/files/ja/webassembly/c_to_wasm/index.html b/files/ja/webassembly/c_to_wasm/index.md similarity index 100% rename from files/ja/webassembly/c_to_wasm/index.html rename to files/ja/webassembly/c_to_wasm/index.md diff --git a/files/ja/webassembly/caching_modules/index.html b/files/ja/webassembly/caching_modules/index.md similarity index 100% rename from files/ja/webassembly/caching_modules/index.html rename to files/ja/webassembly/caching_modules/index.md diff --git a/files/ja/webassembly/concepts/index.html b/files/ja/webassembly/concepts/index.md similarity index 100% rename from files/ja/webassembly/concepts/index.html rename to files/ja/webassembly/concepts/index.md diff --git a/files/ja/webassembly/existing_c_to_wasm/index.html b/files/ja/webassembly/existing_c_to_wasm/index.md similarity index 100% rename from files/ja/webassembly/existing_c_to_wasm/index.html rename to files/ja/webassembly/existing_c_to_wasm/index.md diff --git a/files/ja/webassembly/exported_functions/index.html b/files/ja/webassembly/exported_functions/index.md similarity index 100% rename from files/ja/webassembly/exported_functions/index.html rename to files/ja/webassembly/exported_functions/index.md diff --git a/files/ja/webassembly/index.html b/files/ja/webassembly/index.md similarity index 100% rename from files/ja/webassembly/index.html rename to files/ja/webassembly/index.md diff --git a/files/ja/webassembly/loading_and_running/index.html b/files/ja/webassembly/loading_and_running/index.md similarity index 100% rename from files/ja/webassembly/loading_and_running/index.html rename to files/ja/webassembly/loading_and_running/index.md diff --git a/files/ja/webassembly/rust_to_wasm/index.html b/files/ja/webassembly/rust_to_wasm/index.md similarity index 100% rename from files/ja/webassembly/rust_to_wasm/index.html rename to files/ja/webassembly/rust_to_wasm/index.md diff --git a/files/ja/webassembly/text_format_to_wasm/index.html b/files/ja/webassembly/text_format_to_wasm/index.md similarity index 100% rename from files/ja/webassembly/text_format_to_wasm/index.html rename to files/ja/webassembly/text_format_to_wasm/index.md From 0d768a8a1f0e048e2c6d2c842827cc9ed1bb4eb0 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 18 Aug 2022 11:32:15 +0900 Subject: [PATCH 2/4] =?UTF-8?q?/Webassembly=20=E4=BB=A5=E4=B8=8B=E3=82=92?= =?UTF-8?q?=20md=20=E3=81=B8=E4=B8=80=E6=8B=AC=E5=A4=89=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/webassembly/c_to_wasm/index.md | 241 +++++++-------- files/ja/webassembly/caching_modules/index.md | 150 ++++----- files/ja/webassembly/concepts/index.md | 166 +++++----- .../webassembly/existing_c_to_wasm/index.md | 131 ++++---- .../webassembly/exported_functions/index.md | 66 ++-- files/ja/webassembly/index.md | 185 +++++------- .../webassembly/loading_and_running/index.md | 102 +++---- files/ja/webassembly/rust_to_wasm/index.md | 284 ++++++++++-------- .../webassembly/text_format_to_wasm/index.md | 66 ++-- 9 files changed, 682 insertions(+), 709 deletions(-) diff --git a/files/ja/webassembly/c_to_wasm/index.md b/files/ja/webassembly/c_to_wasm/index.md index d1f297e6b23499..0bd517c7337c8f 100644 --- a/files/ja/webassembly/c_to_wasm/index.md +++ b/files/ja/webassembly/c_to_wasm/index.md @@ -3,175 +3,156 @@ title: C/C++からWebAssemblyにコンパイルする slug: WebAssembly/C_to_wasm translation_of: WebAssembly/C_to_wasm --- -
{{WebAssemblySidebar}}
+{{WebAssemblySidebar}} -

C / C ++のような言語でコードを書いたら、Emscripten のようなツールを使って WebAssembly にコンパイルすることができます。 どのように動作するかを見てみましょう。

+C / C ++のような言語でコードを書いたら、[Emscripten](/ja/docs/Mozilla/Projects/Emscripten) のようなツールを使って WebAssembly にコンパイルすることができます。 どのように動作するかを見てみましょう。 -

Emscripten の環境設定

+## Emscripten の環境設定 -

まず、必要な開発環境をセットアップしましょう。

+まず、必要な開発環境をセットアップしましょう。 -

準備

+### 準備 -

Emscripten SDKを取得します。以下の指示にしたがってください。https://emscripten.org/docs/getting_started/downloads.html

+Emscripten SDK を取得します。以下の指示にしたがってください。 -

サンプルコードをコンパイルする

+## サンプルコードをコンパイルする -

環境を設定した後は、C のサンプルコードを Emscripten にコンパイルする方法を見てみましょう。 Emscripten でコンパイルするときにはいくつかのオプションがありますが、この記事でカバーする主な2つのシナリオは次のとおりです:

+環境を設定した後は、C のサンプルコードを Emscripten にコンパイルする方法を見てみましょう。 Emscripten でコンパイルするときにはいくつかのオプションがありますが、この記事でカバーする主な 2 つのシナリオは次のとおりです: -
    -
  • wasm にコンパイルし、コードを実行するための HTML とウェブ環境上で wasm を実行するための全ての JavaScript グルーコードを生成する。
  • -
  • wasm にコンパイルと JavaScript の生成だけ行う。
  • -
+- wasm にコンパイルし、コードを実行するための HTML とウェブ環境上で wasm を実行するための全ての JavaScript グルーコードを生成する。 +- wasm にコンパイルと JavaScript の生成だけ行う。 -

2つについて見てみましょう。

+2 つについて見てみましょう。 -

HTML と JavaScript を生成する

+### HTML と JavaScript を生成する -

最も簡単なケースを見てみましょう。コードを WebAssembly としてブラウザで実行するための全てを Emscripten で生成するようにします。

+最も簡単なケースを見てみましょう。コードを WebAssembly としてブラウザで実行するための全てを Emscripten で生成するようにします。 -
    -
  1. まずはコンパイルするためのサンプルコードを用意します。以下のCのサンプルコードをコピーして hello.c としてローカルドライブの新しいディレクトリに保存してください: +1. まずはコンパイルするためのサンプルコードを用意します。以下の C のサンプルコードをコピーして `hello.c` としてローカルドライブの新しいディレクトリに保存してください: -
    #include <stdio.h>
    +    ```cpp
    +    #include 
     
    -int main(int argc, char ** argv) {
    -  printf("Hello World\n");
    -}
    -
  2. -
  3. Emscripten コンパイラ環境を導入したターミナルウィンドウを使用して、hello.c ファイルと同じディレクトリに移動して、次のコマンドを実行します: -
    emcc hello.c -s WASM=1 -o hello.html
    -
  4. -
+ int main(int argc, char ** argv) { + printf("Hello World\n"); + } + ``` -

このコマンドで渡されたオプションは次のとおりです:

+2. Emscripten コンパイラ環境を導入したターミナルウィンドウを使用して、`hello.c` ファイルと同じディレクトリに移動して、次のコマンドを実行します: -
    -
  • -s WASM=1 — 出力を wasm に指定します。指定しない場合、Emscripten はデフォルトでは asm.js として出力します。
  • -
  • -o hello.html — コードを実行するための HTML ページを指定します。wasm モジュールとそれをウェブ環境で使用できるようにコンパイル、インスタンス化するための JavaScript グルーコードも出力に含まれます。
  • -
+ ```bash + emcc hello.c -s WASM=1 -o hello.html + ``` -

この時点でソースディレクトリに以下のファイルが出力されているはずです:

+このコマンドで渡されたオプションは次のとおりです: -
    -
  • バイナリの wasm モジュールコード (hello.wasm)
  • -
  • ネイティブの C の関数と JavaScript/wasm の間で変換を行う JavaScript ファイル (hello.js)
  • -
  • wasm コードをロード、コンパイル、インスタンス化し、ブラウザに出力するための HTML ファイル (hello.html)
  • -
+- `-s WASM=1` — 出力を wasm に指定します。指定しない場合、Emscripten はデフォルトでは [asm.js](http://asmjs.org/) として出力します。 +- `-o hello.html` — コードを実行するための HTML ページを指定します。wasm モジュールとそれをウェブ環境で使用できるようにコンパイル、インスタンス化するための JavaScript グルーコードも出力に含まれます。 -

サンプルコードを実行する

+この時点でソースディレクトリに以下のファイルが出力されているはずです: -

WebAssembly をサポートしているブラウザで hello.html をロードするだけです。WebAssembly は Firefox 52+ と Chrome 57+/最新の Opera でデフォルトで有効になっています (Firefox 47+では about:configjavascript.options.wasm flag を有効にすることで、Chrome (51+) と Opera (38+) では chrome://flags に飛んで Experimental WebAssembly フラグを有効にすることで wasm コードを実行することができます) 。

+- バイナリの wasm モジュールコード (`hello.wasm`) +- ネイティブの C の関数と JavaScript/wasm の間で変換を行う JavaScript ファイル (`hello.js`) +- wasm コードをロード、コンパイル、インスタンス化し、ブラウザに出力するための HTML ファイル (`hello.html`) -

全てが計画通りに機能していれば、ウェブページ上の Emscripten コンソールに "Hello world" の出力が表示されるはずです。おめでとうございます、ようやくCを WebAssembly にコンパイルしてブラウザで実行することができました!

+### サンプルコードを実行する -

カスタム HTML テンプレートを使う

+WebAssembly をサポートしているブラウザで `hello.html` をロードするだけです。WebAssembly は Firefox 52+ と Chrome 57+/最新の Opera でデフォルトで有効になっています (Firefox 47+では _about:config_ で `javascript.options.wasm` flag を有効にすることで、Chrome (51+) と Opera (38+) では _chrome://flags_ に飛んで _Experimental WebAssembly_ フラグを有効にすることで wasm コードを実行することができます) 。 -

場合によっては、カスタム HTML テンプレートを使用することもできます。 どうやってできるかを見てみましょう。

+全てが計画通りに機能していれば、ウェブページ上の Emscripten コンソールに "Hello world" の出力が表示されるはずです。おめでとうございます、ようやく C を WebAssembly にコンパイルしてブラウザで実行することができました! -
    -
  1. -

    まず、次の C のコードを hello2.c として新しいディレクトリに保存します:

    +### カスタム HTML テンプレートを使う -
    #include <stdio.h>
    +場合によっては、カスタム HTML テンプレートを使用することもできます。 どうやってできるかを見てみましょう。
     
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    +1.  まず、次の C のコードを `hello2.c` として新しいディレクトリに保存します:
     
    -}
    -
  2. -
  3. -

    shell_minimal.html をあなたの emsdk レポジトリから探します。先程作成した新しいディレクトリに html_template というサブディレクトリを作って、そこにコピーします。

    -
  4. -
  5. -

    新しいディレクトリに移動して (Emscripten コンパイラ環境があるターミナルウィンドウで) 、次のコマンドを実行します:

    + ```cpp + #include -
    emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html
    + int main(int argc, char ** argv) { + printf("Hello World\n"); -

    今回渡したオプションは少しだけ異なります:

    + } + ``` -
      -
    • -o hello2.html と指定したことで、今回コンパイラは JavaScript グルーコードと .html を出力します。
    • -
    • さらに --shell-file html_template/shell_minimal.html と指定しました — これは例を実行する HTML を生成するための、HTML テンプレートパスです。
    • -
    -
  6. -
  7. -

    この例を実行してみましょう。上記のコマンドで hello2.html が生成されます。これは生成された wasm コードに対してロード、実行などを行うグルーコードを含むテンプレートと同じ内容を持ちます。ブラウザを開いて最後の例と同じ出力であることを確認してください。

    -
  8. -
+2. `shell_minimal.html` をあなたの emsdk レポジトリから探します。先程作成した新しいディレクトリに `html_template` というサブディレクトリを作って、そこにコピーします。 +3. 新しいディレクトリに移動して (Emscripten コンパイラ環境があるターミナルウィンドウで) 、次のコマンドを実行します: -
-

: 例えば、 emcc -o hello2.js hello2.c -O3 -s WASM=1 のように -o フラグにHTMLファイルの代わりに .js ファイルを渡すことで JavaScript で出力することを指定できます。そのあとに、スクラッチで独自のカスタム HTML を作ることができます。しかし、これはおすすめできません — Emscripten はメモリ割り当て、メモリリークやその他の問題を扱うための JavaScript グルーコードが多数必要になります。これは提供されたテンプレートにすでに含まれています。全てをあなた自身で書くよりも簡単に使用できます。していること全てに習熟してきたら、必要に応じて独自のカスタマイズバージョンを作りましょう。

-
+ ```bash + emcc -o hello2.html hello2.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html + ``` -

C で定義されたカスタム関数を呼び出す

+ 今回渡したオプションは少しだけ異なります: -

C で定義された関数があって、それを JavaScript から呼び出したい場合、Emscripten の ccall() 関数と EMSCRIPTEN_KEEPALIVE 宣言 (対象の関数をエクスポートする関数リストに加えるものです (Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process? を参照してください)) を使用します。これがどのように働くか見てみましょう。

+ - `-o hello2.html` と指定したことで、今回コンパイラは JavaScript グルーコードと `.html` を出力します。 + - さらに `--shell-file html_template/shell_minimal.html` と指定しました — これは例を実行する HTML を生成するための、HTML テンプレートパスです。 -
    -
  1. -

    はじめに、次のコードを hello3.c として新しいディレクトリに保存します:

    +4. この例を実行してみましょう。上記のコマンドで hello2.html が生成されます。これは生成された wasm コードに対してロード、実行などを行うグルーコードを含むテンプレートと同じ内容を持ちます。ブラウザを開いて最後の例と同じ出力であることを確認してください。 -
    #include <stdio.h>
    -#include <emscripten/emscripten.h>
    +> **Note:** **注**: 例えば、 `emcc -o hello2.js hello2.c -O3 -s WASM=1` のように `-o` フラグに HTML ファイルの代わりに .js ファイルを渡すことで JavaScript で出力することを指定できます。そのあとに、スクラッチで独自のカスタム HTML を作ることができます。しかし、これはおすすめできません — Emscripten はメモリ割り当て、メモリリークやその他の問題を扱うための JavaScript グルーコードが多数必要になります。これは提供されたテンプレートにすでに含まれています。全てをあなた自身で書くよりも簡単に使用できます。していること全てに習熟してきたら、必要に応じて独自のカスタマイズバージョンを作りましょう。
     
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    -}
    +### C で定義されたカスタム関数を呼び出す
     
    -#ifdef __cplusplus
    -extern "C" {
    -#endif
    +C で定義された関数があって、それを JavaScript から呼び出したい場合、Emscripten の `ccall()` 関数と `EMSCRIPTEN_KEEPALIVE` 宣言 (対象の関数をエクスポートする関数リストに加えるものです ([Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?](https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process) を参照してください)) を使用します。これがどのように働くか見てみましょう。
     
    -void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) {
    -  printf("MyFunction Called\n");
    -}
    +1.  はじめに、次のコードを `hello3.c` として新しいディレクトリに保存します:
     
    -#ifdef __cplusplus
    -}
    -#endif
    - -

    デフォルトでは、Emscripten が生成したコードは常に main() を呼び出し、他のデッドコードは削除されます。関数名の前に EMSCRIPTEN_KEEPALIVE を置くことによって、これが起こらなくなります。また、EMSCRIPTEN_KEEPALIVE を使用するために emscripten.h をインポートする必要があります。

    + ```cpp + #include + #include -
    -

    : #ifdef ブロックを加えたことによって、C++ のコードからこの例をインクルードしようとしても動作するでしょう。 C と C++ の間でのマングリング規則によって、他の場合では壊れることもありますが、ここでは C++ を使用している場合に、外部の C の関数として扱うように設定しています。

    -
    -
  2. -
  3. -

    便宜上、この新しいディレクトリに html_template/shell_minimal.html (もちろん、このファイルはあなたの実際の開発環境に置きます)を加えます。

    -
  4. -
  5. -

    さて、再びコンパイル手順を実行しましょう。あなたの最新のディレクトリの中 (そして、Emscripten コンパイラ環境の入っているターミナルウィンドウ) で、このように C のコードをコンパイルします (NO_EXIT_RUNTIMEオプションを付与してコンパイルする必要があることに注意してください。そうしない場合、 main() 関数が終了したときにランタイムもシャットダウンされてしまい、コンパイルされたコードが正しく呼ばれなくなる可能性があります - 例えば、atexitの呼び出しなどの適切なCのエミュレーションに必要です):

    + int main(int argc, char ** argv) { + printf("Hello World\n"); + } -
    emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']"
    -
  6. -
  7. -

    例をブラウザでロードしたら、前と同じものが見られるでしょう。

    -
  8. -
  9. -

    JavaScript から新しい myFunction() 関数を呼び出す必要があります。まずは、 以下のような{{htmlelement("button")}} を最初の <script type='text/javascript'> タグの上に加えましょう。

    + #ifdef __cplusplus + extern "C" { + #endif -
    <button class="mybutton">Run myFunction</button>
    -
  10. -
  11. -

    そして、{{htmlelement("script")}} 要素内の最後に次のコードを追加します ( </script> タグの直前):

    - -
    document.querySelector('.mybutton').addEventListener('click', function(){
    -  alert('check console');
    -  var result = Module.ccall('myFunction', // name of C function
    -                             null, // return type
    -                             null, // argument types
    -                             null); // arguments
    -});
    -
  12. -
- -

これはエクスポートされた関数をどのようにして ccall() を使用して呼び出すかを示しています。

- -

関連情報

- - + void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) { + printf("MyFunction Called\n"); + } + + #ifdef __cplusplus + } + #endif + ``` + + デフォルトでは、Emscripten が生成したコードは常に `main()` を呼び出し、他のデッドコードは削除されます。関数名の前に `EMSCRIPTEN_KEEPALIVE` を置くことによって、これが起こらなくなります。また、`EMSCRIPTEN_KEEPALIVE` を使用するために `emscripten.h` をインポートする必要があります。 + + > **Note:** **注**: `#ifdef` ブロックを加えたことによって、C++ のコードからこの例をインクルードしようとしても動作するでしょう。 C と C++ の間でのマングリング規則によって、他の場合では壊れることもありますが、ここでは C++ を使用している場合に、外部の C の関数として扱うように設定しています。 + +2. 便宜上、この新しいディレクトリに `html_template/shell_minimal.html` (もちろん、このファイルはあなたの実際の開発環境に置きます)を加えます。 +3. さて、再びコンパイル手順を実行しましょう。あなたの最新のディレクトリの中 (そして、Emscripten コンパイラ環境の入っているターミナルウィンドウ) で、このように C のコードをコンパイルします (NO_EXIT_RUNTIME オプションを付与してコンパイルする必要があることに注意してください。そうしない場合、 main() 関数が終了したときにランタイムもシャットダウンされてしまい、コンパイルされたコードが正しく呼ばれなくなる可能性があります - 例えば、atexit の呼び出しなどの適切な C のエミュレーションに必要です): + + ```bash + emcc -o hello3.html hello3.c -O3 -s WASM=1 --shell-file html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall']" + ``` + +4. 例をブラウザでロードしたら、前と同じものが見られるでしょう。 +5. JavaScript から新しい `myFunction()` 関数を呼び出す必要があります。まずは、 以下のような{{htmlelement("button")}} を最初の `` タグの直前): + + ```js + document.querySelector('.mybutton').addEventListener('click', function(){ + alert('check console'); + var result = Module.ccall('myFunction', // name of C function + null, // return type + null, // argument types + null); // arguments + }); + ``` + +これはエクスポートされた関数をどのようにして `ccall()` を使用して呼び出すかを示しています。 + +## 関連情報 + +- [emscripten.org](http://emscripten.org/) — Emscripten とそれの多種多様なオプションについての詳細を確認してください。 +- [Calling compiled C functions from JavaScript using ccall/cwrap](https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html#calling-compiled-c-functions-from-javascript-using-ccall-cwrap) +- [Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?](https://kripken.github.io/emscripten-site/docs/getting_started/FAQ.html#why-do-functions-in-my-c-c-source-code-vanish-when-i-compile-to-javascript-and-or-i-get-no-functions-to-process) diff --git a/files/ja/webassembly/caching_modules/index.md b/files/ja/webassembly/caching_modules/index.md index 5264321d831696..08d742b3725676 100644 --- a/files/ja/webassembly/caching_modules/index.md +++ b/files/ja/webassembly/caching_modules/index.md @@ -11,46 +11,45 @@ tags: - wasm translation_of: WebAssembly/Caching_modules --- -
{{WebAssemblySidebar}}
+{{WebAssemblySidebar}} -
-

警告: 実験的な {{jsxref("WebAssembly.Module")}} IndexedDB のシリアル化サポートがブラウザから削除されています。{{bug("1469395")}} とこの仕様の問題を参照してください。

-
+> **Warning:** **警告**: 実験的な {{jsxref("WebAssembly.Module")}} IndexedDB のシリアル化サポートがブラウザから削除されています。{{bug("1469395")}} と[この仕様の問題](https://github.com/WebAssembly/spec/issues/821)を参照してください。 -

キャッシングはアプリケーションのパフォーマンスを向上させるのに役立ちます — コンパイルされた WebAssembly モジュールをクライアントに格納することによって、毎回ダウンロードしてコンパイルする必要がなくなります。この記事では、キャッシングまわりのベストプラクティスについて解説します。

+キャッシングはアプリケーションのパフォーマンスを向上させるのに役立ちます — コンパイルされた WebAssembly モジュールをクライアントに格納することによって、毎回ダウンロードしてコンパイルする必要がなくなります。この記事では、キャッシングまわりのベストプラクティスについて解説します。 -

IndexedDB を用いたキャッシング

+## IndexedDB を用いたキャッシング -

IndexedDB はクライアント側で構造化されたデータを格納、検索できるトランザクショナルデータベースシステムです。 これはテキスト、blob、他のクローン可能なオブジェクトをアプリケーションのステートの保存、アセットの永続化をするのに理想的な方法です。

+[IndexedDB](/ja/docs/Web/API/IndexedDB_API) はクライアント側で構造化されたデータを格納、検索できるトランザクショナルデータベースシステムです。 これはテキスト、blob、他のクローン可能なオブジェクトをアプリケーションのステートの保存、アセットの永続化をするのに理想的な方法です。 -

これには wasm モジュール ({{jsxref("WebAssembly.Module")}} JavaScript オブジェクト) も含まれます。

+これには wasm モジュール ({{jsxref("WebAssembly.Module")}} JavaScript オブジェクト) も含まれます。 -

キャッシュライブラリをセットアップする

+## キャッシュライブラリをセットアップする -

IndexedDB はやや昔ながらの API です。まず、私たちは今日のよりモダンな API にあわせて、キャッシュするコードを素早く書け、よりよく機能させるためのライブラリ関数を提供します。

+IndexedDB はやや昔ながらの API です。まず、私たちは今日のよりモダンな API にあわせて、キャッシュするコードを素早く書け、よりよく機能させるためのライブラリ関数を提供します。 -

wasm-utils.js ライブラリスクリプト内で instantiateCachedURL() を見つけることができます— この関数は urldbVersion から wasm モジュールをフェッチし、importObject を指定してインスタンス化を行います。そして、成功時に wasm インスタンスを渡すプロミスを返します。さらに、コンパイルされた wasm モジュールをキャッシュするデータベースの作成、新しいモジュールのデータベースへの格納、事前にキャッシュされたモジュールのデータベースからの取得 (再度ダウンロードする必要がなくなります) を行います。

+wasm-utils.js ライブラリスクリプト内で `instantiateCachedURL()` を見つけることができます— この関数は `url` と `dbVersion` から wasm モジュールをフェッチし、`importObject` を指定してインスタンス化を行います。そして、成功時に wasm インスタンスを渡すプロミスを返します。さらに、コンパイルされた wasm モジュールをキャッシュするデータベースの作成、新しいモジュールのデータベースへの格納、事前にキャッシュされたモジュールのデータベースからの取得 (再度ダウンロードする必要がなくなります) を行います。 -
-

: サイト全体の wasm のキャッシュ (指定されたURLだけではありません) は関数に渡す dbVersion によってバージョニングされます。wasm モジュールコードが更新された場合や、URLが変更された場合は dbVersion を更新する必要があります。以降 instantiateCachedURL() を呼び出すと、キャッシュ全体がクリアされ、期限切れのモジュールの使用を避けることができます。

-
+> **Note:** **注**: サイト全体の wasm のキャッシュ (指定された URL だけではありません) は関数に渡す `dbVersion` によってバージョニングされます。wasm モジュールコードが更新された場合や、URL が変更された場合は `dbVersion` を更新する必要があります。以降 `instantiateCachedURL()` を呼び出すと、キャッシュ全体がクリアされ、期限切れのモジュールの使用を避けることができます。 -

この関数はいくつかの必要な定数を定義することから始まります:

+この関数はいくつかの必要な定数を定義することから始まります: -
function instantiateCachedURL(dbVersion, url, importObject) {
+```js
+function instantiateCachedURL(dbVersion, url, importObject) {
   const dbName = 'wasm-cache';
-  const storeName = 'wasm-cache';
+ const storeName = 'wasm-cache'; +``` -

データベースをセットアップする

+### データベースをセットアップする -

instantiateCachedURL() に含まれる最初のヘルパー関数 — openDatabase() — は wasm モジュールを格納するためのオブジェクトストアを作成し、 dbVersion が更新された場合はデータベースをクリアする処理をハンドリングも行います。これは解決時に新しいデータベースを渡すプロミスを返します。

+`instantiateCachedURL()` に含まれる最初のヘルパー関数 — `openDatabase()` — は wasm モジュールを格納するためのオブジェクトストアを作成し、 `dbVersion` が更新された場合はデータベースをクリアする処理をハンドリングも行います。これは解決時に新しいデータベースを渡すプロミスを返します。 -
  function openDatabase() {
-    return new Promise((resolve, reject) => {
+```js
+  function openDatabase() {
+    return new Promise((resolve, reject) => {
       var request = indexedDB.open(dbName, dbVersion);
       request.onerror = reject.bind(null, 'Error opening wasm cache database');
-      request.onsuccess = () => { resolve(request.result) };
-      request.onupgradeneeded = event => {
+      request.onsuccess = () => { resolve(request.result) };
+      request.onupgradeneeded = event => {
         var db = request.result;
         if (db.objectStoreNames.contains(storeName)) {
             console.log(`Clearing out version ${event.oldVersion} wasm cache`);
@@ -60,99 +59,110 @@ translation_of: WebAssembly/Caching_modules
         db.createObjectStore(storeName)
       };
     });
-  }
+ } +``` -

データベースからモジュールを検索する

+### データベースからモジュールを検索する -

次の関数 — lookupInDatabase() — は上で作成したオブジェクトストアから指定した url で検索するプロミスベースの操作を提供します。解決時に格納されたコンパイル済モジュール、棄却時にエラーを渡すプロミスを返します。

+次の関数 — `lookupInDatabase()` — は上で作成したオブジェクトストアから指定した `url` で検索するプロミスベースの操作を提供します。解決時に格納されたコンパイル済モジュール、棄却時にエラーを渡すプロミスを返します。 -
  function lookupInDatabase(db) {
-    return new Promise((resolve, reject) => {
+```js
+  function lookupInDatabase(db) {
+    return new Promise((resolve, reject) => {
       var store = db.transaction([storeName]).objectStore(storeName);
       var request = store.get(url);
       request.onerror = reject.bind(null, `Error getting wasm module ${url}`);
-      request.onsuccess = event => {
+      request.onsuccess = event => {
         if (request.result)
           resolve(request.result);
         else
           reject(`Module ${url} was not found in wasm cache`);
       }
     });
-  }
+ } +``` -

モジュールの保存とインスタンス化

+### モジュールの保存とインスタンス化 -

次に storeInDatabase() 関数を定義します。この関数は非同期に指定された wasm モジュールを指定したデータベースに保存します。

+次に `storeInDatabase()` 関数を定義します。この関数は非同期に指定された wasm モジュールを指定したデータベースに保存します。 -
  function storeInDatabase(db, module) {
+```js
+  function storeInDatabase(db, module) {
     var store = db.transaction([storeName], 'readwrite').objectStore(storeName);
     var request = store.put(module, url);
-    request.onerror = err => { console.log(`Failed to store in wasm cache: ${err}`) };
-    request.onsuccess = err => { console.log(`Successfully stored ${url} in wasm cache`) };
-  }
+ request.onerror = err => { console.log(`Failed to store in wasm cache: ${err}`) }; + request.onsuccess = err => { console.log(`Successfully stored ${url} in wasm cache`) }; + } +``` -

ヘルパー関数を使用する

+### ヘルパー関数を使用する -

プロミスベースのヘルパー関数が全て定義されました。これらを使用して IndexDB のキャッシュルックアップするコアロジックを表現できるようになりました。データベースをオープンし、url をキーとして db に格納されているコンパイル済モジュールの有無を確認してみましょう:

+プロミスベースのヘルパー関数が全て定義されました。これらを使用して IndexDB のキャッシュルックアップするコアロジックを表現できるようになりました。データベースをオープンし、`url` をキーとして `db` に格納されているコンパイル済モジュールの有無を確認してみましょう: -
  return openDatabase().then(db => {
-    return lookupInDatabase(db).then(module => {
+```js + return openDatabase().then(db => { + return lookupInDatabase(db).then(module => { +``` -

成功したら、インポートオブジェクトを指定してモジュールをインスタンス化します:

+成功したら、インポートオブジェクトを指定してモジュールをインスタンス化します: -
      console.log(`Found ${url} in wasm cache`);
+```js
+      console.log(`Found ${url} in wasm cache`);
       return WebAssembly.instantiate(module, importObject);
-    },
+ }, +``` -

失敗した場合、スクラッチでコンパイルします。次回以降に使用するためにコンパイルしたモジュールを url をキーとしてデータベースに格納します:

+失敗した場合、スクラッチでコンパイルします。次回以降に使用するためにコンパイルしたモジュールを url をキーとしてデータベースに格納します: -
    errMsg => {
+```js
+    errMsg => {
       console.log(errMsg);
-      return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
+      return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
         storeInDatabase(db, results.module);
         return results.instance;
       });
     })
-  },
+ }, +``` -
-

: {{jsxref("WebAssembly.instantiate()")}} は {{jsxref("WebAssembly.Module()", "Module")}} と {{jsxref("WebAssembly.Instance()", "Instance")}} の両方を返します。Module はコンパイルされたコードを表し、IDB に格納したり、postMessage() を通じて ワーカーとの間で共有することができます。Instance はステートフルで、呼び出し可能な JavaScript の関数を含んでいるため、格納/共有することは出来ません。

-
+> **Note:** **注**: {{jsxref("WebAssembly.instantiate()")}} は {{jsxref("WebAssembly.Module()", "Module")}} と {{jsxref("WebAssembly.Instance()", "Instance")}} の両方を返します。Module はコンパイルされたコードを表し、IDB に格納したり、[`postMessage()`](/ja/docs/Web/API/MessagePort/postMessage) を通じて ワーカーとの間で共有することができます。Instance はステートフルで、呼び出し可能な JavaScript の関数を含んでいるため、格納/共有することは出来ません。 -

データベースをオープンすることに失敗した場合(例えば、パーミッションやクォータ等の原因による)、モジュールをフェッチしてコンパイルするだけにし、結果を格納しないでください (格納するデータベースがないため) 。

+データベースをオープンすることに失敗した場合(例えば、パーミッションやクォータ等の原因による)、モジュールをフェッチしてコンパイルするだけにし、結果を格納しないでください (格納するデータベースがないため) 。 -
  errMsg => {
+```js
+  errMsg => {
     console.log(errMsg);
-    return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
+    return WebAssembly.instantiateStreaming(fetch(url)).then(results => {
       return results.instance
     });
   });
-}
+} +``` -

wasm モジュールをキャッシュする

+## wasm モジュールをキャッシュする -

上で定義されたライブラリ関数を使用して、wasm モジュールインスタンスの取得やエクスポートされた機能を使用することが (その間にバックグラウンドでキャッシュのハンドリングをしています) 、次のパラメータで呼び出すだけのシンプルなものになります:

+上で定義されたライブラリ関数を使用して、wasm モジュールインスタンスの取得やエクスポートされた機能を使用することが (その間にバックグラウンドでキャッシュのハンドリングをしています) 、次のパラメータで呼び出すだけのシンプルなものになります: -
    -
  • キャッシュバージョン — 詳細は上で説明されています — wasm モジュールが更新されたときや別 URL に移動したときに更新する必要があります。
  • -
  • インスタンス化したい wasm モジュールの URL。
  • -
  • インポートオブジェクト (必要ならば)
  • -
+- キャッシュバージョン — 詳細は上で説明されています — wasm モジュールが更新されたときや別 URL に移動したときに更新する必要があります。 +- インスタンス化したい wasm モジュールの URL。 +- インポートオブジェクト (必要ならば) -
const wasmCacheVersion = 1;
+```js
+const wasmCacheVersion = 1;
 
-instantiateCachedURL(wasmCacheVersion, 'test.wasm').then(instance =>
+instantiateCachedURL(wasmCacheVersion, 'test.wasm').then(instance =>
   console.log("Instance says the answer is: " + instance.exports.answer())
-).catch(err =>
+).catch(err =>
   console.error("Failure to instantiate: " + err)
-);
+); +``` -

ソースコードと例は GitHub の indexeddb-cache.html (動作例) を参照してください。

+ソースコードと例は GitHub の [indexeddb-cache.html](https://github.com/mdn/webassembly-examples/blob/master/other-examples/indexeddb-cache.html) ([動作例](https://mdn.github.io/webassembly-examples/other-examples/indexeddb-cache.html)) を参照してください。 -

ブラウザのサポート

+## ブラウザのサポート -

現時点では、WebAssembly モジュールの構造化された複製をサポートしているため、この手法は Firefox と Edge で動作します。

+現時点では、WebAssembly モジュールの構造化された複製をサポートしているため、この手法は Firefox と Edge で動作します。 -

Chrome は WebAssembly 構造化クローンサポートフラグの背後にサポートが実装されていますが、いくつかの懸念があるため、デフォルトではまだ有効にしていません (たとえば、この説明を参照)。

+Chrome は WebAssembly 構造化クローンサポートフラグの背後にサポートが実装されていますが、いくつかの懸念があるため、デフォルトではまだ有効にしていません (たとえば、[この説明を参照](https://github.com/WebAssembly/design/issues/972))。 -

Safari ではまだ実装されていません。

+Safari ではまだ実装されていません。 diff --git a/files/ja/webassembly/concepts/index.md b/files/ja/webassembly/concepts/index.md index 9e94a90ddbaf54..5b954f25586d2e 100644 --- a/files/ja/webassembly/concepts/index.md +++ b/files/ja/webassembly/concepts/index.md @@ -11,150 +11,130 @@ tags: - rust translation_of: WebAssembly/Concepts --- -
{{WebAssemblySidebar}}
+{{WebAssemblySidebar}} -

この記事では、 WebAssembly がどのように機能しているか、その目標、解決している問題、ウェブブラウザーのレンダリングエンジン内での動作などの概念について説明します。

+この記事では、 WebAssembly がどのように機能しているか、その目標、解決している問題、ウェブブラウザーのレンダリングエンジン内での動作などの概念について説明します。 -

WebAssembly とは何か

+## WebAssembly とは何か -

WebAssembly は最近のウェブブラウザーで動作し、新たな機能と大幅なパフォーマンス向上を提供する新しい種類のコードです。基本的に直接記述ではなく、C、C++、Rust 等の低水準の言語にとって効果的なコンパイル対象となるように設計されています。

+WebAssembly は最近のウェブブラウザーで動作し、新たな機能と大幅なパフォーマンス向上を提供する新しい種類のコードです。基本的に直接記述ではなく、C、C++、Rust 等の低水準の言語にとって効果的なコンパイル対象となるように設計されています。 -

この機能はウェブプラットフォームにとって大きな意味を持ちます。 — ウェブ上で動作するクライアントアプリで従来は実現できなかった、ネイティブ水準の速度で複数の言語で記述されたコードをウェブ上で動作させる方法を提供します。

+この機能はウェブプラットフォームにとって大きな意味を持ちます。 — ウェブ上で動作するクライアントアプリで従来は実現できなかった、ネイティブ水準の速度で複数の言語で記述されたコードをウェブ上で動作させる方法を提供します。 -

それ以上に、その利点を享受するために利用者は WebAssembly のコードをどのように作成するのか知る必要さえ有りません。 WebAssembly モジュールはウェブ (あるいは Node.js) アプリにインポートする事ができ、 WebAssembly の機能は JavaScript を経由して他の領域から利用できる状態になります。 JavaScript 製フレームワークでは大幅なパフォーマンス改善と開発中の新機能をウェブ開発者が容易に利用できるようにするために WebAssembly を用いることができます。

+それ以上に、その利点を享受するために利用者は WebAssembly のコードをどのように作成するのか知る必要さえ有りません。 WebAssembly モジュールはウェブ (あるいは Node.js) アプリにインポートする事ができ、 WebAssembly の機能は JavaScript を経由して他の領域から利用できる状態になります。 JavaScript 製フレームワークでは大幅なパフォーマンス改善と開発中の新機能をウェブ開発者が容易に利用できるようにするために WebAssembly を用いることができます。 -

WebAssembly の目標

+## WebAssembly の目標 -

WebAssembly は W3C WebAssembly Community Group 内で策定されるオープン標準として以下を目標に定めて作成されています:

+WebAssembly は [W3C WebAssembly Community Group](https://www.w3.org/community/webassembly/) 内で策定されるオープン標準として以下を目標に定めて作成されています: -
    -
  • 高速で、高効率であり、ポータブルである事 — WebAssembly のコードは 共通ハードウェア対応環境 を利用して異なるプラットフォーム間でネイティブ水準の速度で実行可能です。
  • -
  • 可読性を持ちデバッグ可能である事 — WebAssembly は低水準のアセンブリ言語ですが、人間が読めるテキストフォーマットを持ちます(その仕様策定は終わっていないものの)。このフォーマットは人の手で読み書きできて、デバッグもできます。
  • -
  • 安全である事 — WebAssembly は安全でサンドボックス化された実行環境上で動作するように設計されています。他のウェブ言語と同様に、ブラウザーに対して same-origin および権限ポリシーの確認を強制します。
  • -
  • ウェブを破壊しない事 — WebAssembly は他のウェブ技術と協調し、後方互換性を維持するように設計されます。
  • -
+- 高速で、高効率であり、ポータブルである事 — WebAssembly のコードは [共通ハードウェア対応環境](http://webassembly.org/docs/portability/#assumptions-for-efficient-execution) を利用して異なるプラットフォーム間でネイティブ水準の速度で実行可能です。 +- 可読性を持ちデバッグ可能である事 — WebAssembly は低水準のアセンブリ言語ですが、人間が読めるテキストフォーマットを持ちます(その仕様策定は終わっていないものの)。このフォーマットは人の手で読み書きできて、デバッグもできます。 +- 安全である事 — WebAssembly は安全でサンドボックス化された実行環境上で動作するように設計されています。他のウェブ言語と同様に、ブラウザーに対して same-origin および権限ポリシーの確認を強制します。 +- ウェブを破壊しない事 — WebAssembly は他のウェブ技術と協調し、後方互換性を維持するように設計されます。 -
-

メモ: WebAssembly はまたウェブの領域外の JavaScript 環境での利用も行います (Non-web embeddings を参照)。

-
+> **Note:** **メモ**: WebAssembly はまたウェブの領域外の JavaScript 環境での利用も行います ([Non-web embeddings](http://webassembly.org/docs/non-web/) を参照)。 -

WebAssembly はどのようにウェブプラットフォームに適合するのか

+## WebAssembly はどのようにウェブプラットフォームに適合するのか -

ウェブプラットフォームは 2 つの領域からなると考える事ができます:

+ウェブプラットフォームは 2 つの領域からなると考える事ができます: -
    -
  • ウェブアプリのコードを実行する仮想マシン (VM) 、例としてアプリを動作させる JavaScript コード。
  • -
  • ウェブブラウザー / デバイスの機能をコントロールして物事を実現するためにウェブアプリが呼ぶことのできる Web API のセット (DOMCSSOMWebGLIndexedDBWeb Audio API 等)。
  • -
+- ウェブアプリのコードを実行する仮想マシン (VM) 、例としてアプリを動作させる JavaScript コード。 +- ウェブブラウザー / デバイスの機能をコントロールして物事を実現するためにウェブアプリが呼ぶことのできる [Web API](/ja/docs/Web/API) のセット ([DOM](/ja/docs/Web/API/Document_Object_Model)、 [CSSOM](/ja/docs/Web/API/CSS_Object_Model)、 [WebGL](/ja/docs/Web/API/WebGL_API)、 [IndexedDB](/ja/docs/Web/API/IndexedDB_API)、 [Web Audio API](/ja/docs/Web/API/Web_Audio_API) 等)。 -

歴史的に、仮想マシンは JavaScript を読み込む事しかできませんでした。 JavaScript が今日のウェブで人々が遭遇する多くの問題を解決する上で十分にパワフルであるため私達にとって仮想マシンはとても有効でした。しかしながら私達は JavaScript をもっと厳しい状況、3D ゲーム、VR に AR、コンピュータービジョン、画像/動画編集等ネイティブの性能が要求されるような多くの領域 (これら以外の利用アイディアに関しては WebAssembly use cases を参照) において用いる際にパフォーマンス上の問題に遭遇するようになっています。

+歴史的に、仮想マシンは JavaScript を読み込む事しかできませんでした。 JavaScript が今日のウェブで人々が遭遇する多くの問題を解決する上で十分にパワフルであるため私達にとって仮想マシンはとても有効でした。しかしながら私達は JavaScript をもっと厳しい状況、3D ゲーム、VR に AR、コンピュータービジョン、画像/動画編集等ネイティブの性能が要求されるような多くの領域 (これら以外の利用アイディアに関しては [WebAssembly use cases](http://webassembly.org/docs/use-cases/) を参照) において用いる際にパフォーマンス上の問題に遭遇するようになっています。 -

加えて巨大な JavaScript アプリケーションのダウンロード、構造の解析とコンパイルのコストは異常に高いものになりえます。モバイルや他のリソースが限られたプラットフォームではこのようなパフォーマンスのボトルネックの影響をずっと強く受ける事になります。

+加えて巨大な JavaScript アプリケーションのダウンロード、構造の解析とコンパイルのコストは異常に高いものになりえます。モバイルや他のリソースが限られたプラットフォームではこのようなパフォーマンスのボトルネックの影響をずっと強く受ける事になります。 -

WebAssembly は JavaScript と異なる言語ですが、その置き換えを意図していません。その代わり、JavaScript の足りない所を補填して併用し、ウェブ開発者に双方の以下のような利益を提供する事を狙いとしています:

+WebAssembly は JavaScript と異なる言語ですが、その置き換えを意図していません。その代わり、JavaScript の足りない所を補填して併用し、ウェブ開発者に双方の以下のような利益を提供する事を狙いとしています: -
    -
  • JavaScript は高水準の言語であり、ウェブアプリケーションを作る上で十分な柔軟性と表現力を持っています。そして多くの利点 — 動的型付け言語である、コンパイルが必須でない、パワフルなフレームワーク、ライブラリやツールを提供する豊富な土壌等を持っています。
  • -
  • WebAssembly はネイティブに近いパフォーマンスで動作して、C++ や Rust のような低水準のメモリー管理を行う言語がウェブ上で動作するようコンパイルされる対象となる、コンパクトなバイナリー形式を持つ低水準なアセンブリに似た言語です (WebAssembly は将来的にガベージコレクションによるメモリー管理を行う言語をサポートする 高レベルの目標 を持っている事に注意してください)。
  • -
+- JavaScript は高水準の言語であり、ウェブアプリケーションを作る上で十分な柔軟性と表現力を持っています。そして多くの利点 — 動的型付け言語である、コンパイルが必須でない、パワフルなフレームワーク、ライブラリやツールを提供する豊富な土壌等を持っています。 +- WebAssembly はネイティブに近いパフォーマンスで動作して、C++ や Rust のような低水準のメモリー管理を行う言語がウェブ上で動作するようコンパイルされる対象となる、コンパクトなバイナリー形式を持つ低水準なアセンブリに似た言語です (WebAssembly は将来的にガベージコレクションによるメモリー管理を行う言語をサポートする [高レベルの目標](http://webassembly.org/docs/high-level-goals/) を持っている事に注意してください)。 -

ブラウザーにおいての WebAssembly の登場によって、私たちが先述したような仮想マシンはこれから 2 つの種類の言語をロードして実行することになります — JavaScript と WebAssembly です。

+ブラウザーにおいての WebAssembly の登場によって、私たちが先述したような仮想マシンはこれから 2 つの種類の言語をロードして実行することになります — JavaScript と WebAssembly です。 -

必要に応じてこの異なったコードは互いを呼び出し合う事ができます — WebAssembly JavaScript API はエクスポートした WebAssembly のコードを普遍的に呼び出せる JavaScript 関数でラップし、WebAssembly のコードは通常の JavaScript 関数をインポートして同期的に呼び出せます。実際、WebAssembly のコードの基本単位はモジュールと呼ばれ、 WebAssembly のモジュールは ES2015 のモジュールと多くの対になる概念を持っています。

+必要に応じてこの異なったコードは互いを呼び出し合う事ができます — [WebAssembly JavaScript API](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) はエクスポートした WebAssembly のコードを普遍的に呼び出せる JavaScript 関数でラップし、WebAssembly のコードは通常の JavaScript 関数をインポートして同期的に呼び出せます。実際、WebAssembly のコードの基本単位はモジュールと呼ばれ、 WebAssembly のモジュールは ES2015 のモジュールと多くの対になる概念を持っています。 -

WebAssembly のキーコンセプト

+### WebAssembly のキーコンセプト -

ブラウザー上で WebAssembly がどのように動作するかを理解するため必要となるキーコンセプトがいくつか存在します。これらのコンセプトはそれぞれが WebAssembly JavaScript API に一対一で対応しています。

+ブラウザー上で WebAssembly がどのように動作するかを理解するため必要となるキーコンセプトがいくつか存在します。これらのコンセプトはそれぞれが [WebAssembly JavaScript API](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) に一対一で対応しています。 -
    -
  • Module (モジュール): ブラウザーによって実行可能な機械語にコンパイルされた WebAssembly のバイナリーに対応します。モジュールはステートレスであるため、Blob のように、明示的に IndexedDB にキャッシュ できたり window やウェブワーカーと ( postMessage() を経由して ) 共有する事ができます。モジュールは ES2015 のモジュールのように import と export の宣言を行います。
  • -
  • Memory (メモリー): WebAssembly の低水準なメモリーアクセス命令によって読み込みおよび書き込みが行われるバイト列を一次元の配列として保持している、リサイズ可能な ArrayBuffer です。
  • -
  • Table (テーブル): メモリー内に (安全性およびポータブル性を維持するため) バイト列として保持することができなかった (関数等に対する) 参照を保持しているリサイズ可能な型付き配列です。
  • -
  • Instance (インスタンス): メモリー、テーブル、インポートされた値を含む実行時に利用されるすべての状態と対となるモジュールです。インスタンスは特定の import によって特定のグローバル環境にロードされた ES2015 におけるモジュールのような物です。
  • -
+- **Module (モジュール)**: ブラウザーによって実行可能な機械語にコンパイルされた WebAssembly のバイナリーに対応します。モジュールはステートレスであるため、[Blob](/ja/docs/Web/API/Blob) のように、明示的に [IndexedDB にキャッシュ](/ja/docs/WebAssembly/Caching_modules) できたり window やウェブワーカーと ( [`postMessage()`](/ja/docs/Web/API/MessagePort/postMessage) を経由して ) 共有する事ができます。モジュールは ES2015 のモジュールのように import と export の宣言を行います。 +- **Memory (メモリー)**: WebAssembly の低水準なメモリーアクセス命令によって読み込みおよび書き込みが行われるバイト列を一次元の配列として保持している、リサイズ可能な ArrayBuffer です。 +- **Table (テーブル)**: メモリー内に (安全性およびポータブル性を維持するため) バイト列として保持することができなかった (関数等に対する) 参照を保持しているリサイズ可能な型付き配列です。 +- **Instance (インスタンス)**: メモリー、テーブル、インポートされた値を含む実行時に利用されるすべての状態と対となるモジュールです。インスタンスは特定の import によって特定のグローバル環境にロードされた ES2015 におけるモジュールのような物です。 -

JavaScript API はモジュール、メモリー、テーブルおよびインスタンスを作る機能を開発者に提供します。 WebAssembly のインスタンスが与えられれば、 JavaScript はその中で export されたオブジェクトを、一般的な JavaScript で渡せる状態にされた関数同様に、同期的に呼び出すことができます。また任意の JavaScript の関数はその関数を WebAssembly のインスタンスに import する事で WebAssembly のコードから同期的に呼び出されるようにする事もできます。

+JavaScript API はモジュール、メモリー、テーブルおよびインスタンスを作る機能を開発者に提供します。 WebAssembly のインスタンスが与えられれば、 JavaScript はその中で export されたオブジェクトを、一般的な JavaScript で渡せる状態にされた関数同様に、同期的に呼び出すことができます。また任意の JavaScript の関数はその関数を WebAssembly のインスタンスに import する事で WebAssembly のコードから同期的に呼び出されるようにする事もできます。 -

JavaScript は WebAssembly のコードがどのようにダウンロードされ、コンパイルされて実行されるかを完全に制御できるため、JavaScript 開発者は WebAssembly を単に効果的に高いパフォーマンスを発揮する JavaScript の機能のようにとらえることもできます。

+JavaScript は WebAssembly のコードがどのようにダウンロードされ、コンパイルされて実行されるかを完全に制御できるため、JavaScript 開発者は WebAssembly を単に効果的に高いパフォーマンスを発揮する JavaScript の機能のようにとらえることもできます。 -

将来的には、 WebAssembly モジュールは (<script type='module'> を利用して) ES2015 モジュールのようにロード可能 となり、これは JavaScript が WebAssembly モジュールを ES2015 モジュールと同じくらい簡単に取得、コンパイル、インポートできるようになる事を意味します。

+将来的には、 WebAssembly モジュールは (` + +``` -

そして、正しいバージョン番号が出力されます:

+そして、正しいバージョン番号が[出力](https://googlechrome.github.io/samples/webassembly/version.html)されます: -

  正しいバージョン番号を示すデベロッパーツールのコンソールのスクリーンショット

+![ 正しいバージョン番号を示すデベロッパーツールのコンソールのスクリーンショット](https://mdn.mozillademos.org/files/15913/version.png) -
-

注: libwebp は現在のバージョン a.b.c を 16 進数の 0xabc で返します。例えば、v0.6.1は0x000601 = 1537としてエンコードされています。

-
+> **Note:** **注:** libwebp は現在のバージョン a.b.c を 16 進数の 0xabc で返します。例えば、v0.6.1 は 0x000601 = 1537 としてエンコードされています。 -

JavaScriptからWasmに画像を取得する

+### JavaScript から Wasm に画像を取得する -

エンコーダのバージョン番号を取得するのは素晴らしいことですが、画像をエンコードした方が印象的です。どうすればいいのでしょうか?

+エンコーダのバージョン番号を取得するのは素晴らしいことですが、画像をエンコードした方が印象的です。どうすればいいのでしょうか? -

最初に答えなければならない質問は、どうやって画像を wasm に入れるのかということです。libwebpのEncoding APIを見ると、RGB、RGBA、BGR、BGRAのバイト列を期待していることがわかります。幸いにも Canvas API には {{domxref("CanvasRenderingContext2D.getImageData")}} があり、RGBA の画像データを含む {{jsxref("Uint8ClampedArray")}}が得られます:

+最初に答えなければならない質問は、どうやって画像を wasm に入れるのかということです。libwebp の[Encoding API](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)を見ると、RGB、RGBA、BGR、BGRA のバイト列を期待していることがわかります。幸いにも Canvas API には {{domxref("CanvasRenderingContext2D.getImageData")}} があり、RGBA の画像データを含む {{jsxref("Uint8ClampedArray")}}が得られます: -
 async function loadImage(src) {
+```js
+ async function loadImage(src) {
   // Load image
-  const imgBlob = await fetch(src).then(resp => resp.blob());
+  const imgBlob = await fetch(src).then(resp => resp.blob());
   const img = await createImageBitmap(imgBlob);
   // Make canvas same size as image
   const canvas = document.createElement('canvas');
@@ -80,11 +85,13 @@ int version() {
   const ctx = canvas.getContext('2d');
   ctx.drawImage(img, 0, 0);
   return ctx.getImageData(0, 0, img.width, img.height);
-}
+} +``` -

これで、JavaScript から wasm にデータをコピーすることだけが「唯一の」問題となります。そのためには、追加で2つの関数を公開する必要があります — 1つは、wasm内で画像のためにメモリを確保する関数、もう1つは、それを再び解放する関数です:

+これで、JavaScript から wasm にデータをコピーすることだけが「唯一の」問題となります。そのためには、追加で 2 つの関数を公開する必要があります — 1 つは、wasm 内で画像のためにメモリを確保する関数、もう 1 つは、それを再び解放する関数です: -
#include <stdlib.h> // required for malloc definition
+```cpp
+#include  // required for malloc definition
 
 EMSCRIPTEN_KEEPALIVE
 uint8_t* create_buffer(int width, int height) {
@@ -94,11 +101,13 @@ uint8_t* create_buffer(int width, int height) {
 EMSCRIPTEN_KEEPALIVE
 void destroy_buffer(uint8_t* p) {
   free(p);
-}
+} +``` -

create_buffer() 関数は RGBA 画像用 — したがって、ピクセル当たり4バイト — のバッファを確保します。malloc() が返すポインタは、そのバッファの最初のメモリセルのアドレスです。ポインタが JavaScript に返されると、それは単なる数値として扱われます。この関数を cwrap を使って JavaScript に公開した後、その数値を使ってバッファの開始点を見つけ、画像データをコピーすることができます。

+`create_buffer()` 関数は RGBA 画像用 — したがって、ピクセル当たり 4 バイト — のバッファを確保します。malloc() が返すポインタは、そのバッファの最初のメモリセルのアドレスです。ポインタが JavaScript に返されると、それは単なる数値として扱われます。この関数を cwrap を使って JavaScript に公開した後、その数値を使ってバッファの開始点を見つけ、画像データをコピーすることができます。 -
const api = {
+```js
+const api = {
   version: Module.cwrap('version', 'number', []),
   create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
   destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
@@ -108,21 +117,23 @@ const image = await loadImage('./image.jpg');
 const p = api.create_buffer(image.width, image.height);
 Module.HEAP8.set(image.data, p);
 // ... call encoder ...
-api.destroy_buffer(p);
+api.destroy_buffer(p); +``` -

画像をエンコードする

+### 画像をエンコードする -

wasmで画像を使えるようになりました。いよいよWebPエンコーダを呼び出して動かす時が来ました。WebPのドキュメントを見ると、WebPEncodeRGBAがふさわしいようです。この関数は、入力画像へのポインタと画像の寸法、そして 0 から 100 の間のクオリティーオプションを受け取ります。また、出力バッファを確保するので、WebP 画像の処理が終わったら WebPFree()を使って解放する必要があります。

+wasm で画像を使えるようになりました。いよいよ WebP エンコーダを呼び出して動かす時が来ました。[WebP のドキュメント](https://developers.google.com/speed/webp/docs/api#simple_encoding_api)を見ると、`WebPEncodeRGBA`がふさわしいようです。この関数は、入力画像へのポインタと画像の寸法、そして 0 から 100 の間のクオリティーオプションを受け取ります。また、出力バッファを確保するので、WebP 画像の処理が終わったら `WebPFree()`を使って解放する必要があります。 -

エンコード処理の結果は、出力バッファとその長さになります。C 言語の関数は(メモリを動的に確保しない限り)戻り値の型として配列を使うことができないため 、この例では静的なグローバル配列を使用しています。これはクリーンな C 言語とは言えないかもしれません。実際、これは wasm ポインタが 32 ビット幅であることに依存しています。しかし、これは話を単純にするための公正な手段です。

+エンコード処理の結果は、出力バッファとその長さになります。C 言語の関数は(メモリを動的に確保しない限り)戻り値の型として配列を使うことができないため 、この例では静的なグローバル配列を使用しています。これはクリーンな C 言語とは言えないかもしれません。実際、これは wasm ポインタが 32 ビット幅であることに依存しています。しかし、これは話を単純にするための公正な手段です。 -
int result[2];
+```js
+int result[2];
 EMSCRIPTEN_KEEPALIVE
 void encode(uint8_t* img_in, int width, int height, float quality) {
   uint8_t* img_out;
   size_t size;
 
-  size = WebPEncodeRGBA(img_in, width, height, width * 4, quality, &img_out);
+  size = WebPEncodeRGBA(img_in, width, height, width * 4, quality, &img_out);
 
   result[0] = (int)img_out;
   result[1] = size;
@@ -141,39 +152,41 @@ int get_result_pointer() {
 EMSCRIPTEN_KEEPALIVE
 int get_result_size() {
   return result[1];
-}
+} +``` -

これで、エンコーディング関数を呼び出し、ポインタと画像サイズを取得し、それをあなたの JavaScript バッファに格納し、プロセス中で確保されたすべての wasm バッファを解放することができるようになりました。

+これで、エンコーディング関数を呼び出し、ポインタと画像サイズを取得し、それをあなたの JavaScript バッファに格納し、プロセス中で確保されたすべての wasm バッファを解放することができるようになりました。 -
api.encode(p, image.width, image.height, 100);
+```js
+api.encode(p, image.width, image.height, 100);
 const resultPointer = api.get_result_pointer();
 const resultSize = api.get_result_size();
 const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize);
 const result = new Uint8Array(resultView);
-api.free_result(resultPointer);
+api.free_result(resultPointer); +``` -
-

Note: new Uint8Array(someBuffer)は同じメモリチャンク上に新しいビューを作成し、new Uint8Array(someTypedArray)はデータをコピーします。

-
+> **Note:** `new Uint8Array(someBuffer)`は同じメモリチャンク上に新しいビューを作成し、`new Uint8Array(someTypedArray)`はデータをコピーします。 -

画像のサイズによっては、wasmが入力画像と出力画像を格納するためのメモリを十分に大きくすることができないというエラーが発生する可能性があります:

+画像のサイズによっては、wasm が入力画像と出力画像を格納するためのメモリを十分に大きくすることができないというエラーが発生する可能性があります: -


-  Screenshot of the DevTools console showing an error.

+![ + Screenshot of the DevTools console showing an error.](https://mdn.mozillademos.org/files/15922/error.png) -

幸いにも、この問題の解決策はエラーメッセージの中にあります。コンパイルコマンドに-s ALLOW_MEMORY_GROWTH=1を追加するだけです。

+幸いにも、この問題の解決策はエラーメッセージの中にあります。コンパイルコマンドに`-s ALLOW_MEMORY_GROWTH=1`を追加するだけです。 -

これで完了です。WebPエンコーダをコンパイルし、JPEG画像をWebPにトランスコードしました。うまくいったことを証明するために、結果のバッファをblobにして<img>要素で使用してください:

+これで完了です。WebP エンコーダをコンパイルし、JPEG 画像を WebP にトランスコードしました。うまくいったことを証明するために、結果のバッファを blob にして``要素で使用してください: -
const blob = new Blob([result], {type: 'image/webp'});
+```js
+const blob = new Blob([result], {type: 'image/webp'});
 const blobURL = URL.createObjectURL(blob);
 const img = document.createElement('img');
 img.src = blobURL;
 document.body.appendChild(img)
-
+``` -

見るがいい、新しいWebP画像の栄光を。

+見るがいい、新しい WebP 画像の栄光を。 -

デモ | 原著

+[デモ](https://googlechrome.github.io/samples/webassembly/image.html) | [原著](https://developers.google.com/web/updates/2018/03/emscripting-a-c-library) -

 デベロッパーツールのネットワークパネルと生成された画像。

+![ デベロッパーツールのネットワークパネルと生成された画像。](https://mdn.mozillademos.org/files/15914/result.jpg) diff --git a/files/ja/webassembly/exported_functions/index.md b/files/ja/webassembly/exported_functions/index.md index c1b696898dc0b4..2aad08f2d5ae3c 100644 --- a/files/ja/webassembly/exported_functions/index.md +++ b/files/ja/webassembly/exported_functions/index.md @@ -11,28 +11,27 @@ tags: - wasm translation_of: WebAssembly/Exported_functions --- -
{{WebAssemblySidebar}}
+{{WebAssemblySidebar}} -

エクスポートされた WebAssembly 関数は WebAssembly 関数が JavaScript でどのように表現されるのか、この記事では、もう少し詳しく説明します。

+エクスポートされた WebAssembly 関数は WebAssembly 関数が JavaScript でどのように表現されるのか、この記事では、もう少し詳しく説明します。 -

エクスポートされた...とは?

+## エクスポートされた...とは? -

エクスポートされた WebAssembly 関数は WebAssembly 関数を表現する JavaScript ラッパーです。それらを呼び出したときにバックグラウンドでいくつかの動作を行います。引数を wasm で使える型に(例えば、JavaScript の数値を Int32 に)変換し、wasm モジュール内の関数に渡し、実行し、結果を変換して JavaScript 側に戻します。

+エクスポートされた WebAssembly 関数は WebAssembly 関数を表現する JavaScript ラッパーです。それらを呼び出したときにバックグラウンドでいくつかの動作を行います。引数を wasm で使える型に(例えば、JavaScript の数値を Int32 に)変換し、wasm モジュール内の関数に渡し、実行し、結果を変換して JavaScript 側に戻します。 -

エクスポートされた WebAssembly 関数は次の 2 つの方法で取得できます:

+エクスポートされた WebAssembly 関数は次の 2 つの方法で取得できます: -
    -
  • 既存のテーブルの Table.prototype.get() を呼び出す。
  • -
  • wasm モジュールインスタンスの Instance.exports を通してエクスポートされた関数にアクセスする。
  • -
+- 既存のテーブルの [`Table.prototype.get()`](/ja/docs/WebAssembly/API/Table/get) を呼び出す。 +- wasm モジュールインスタンスの [`Instance.exports`](/ja/docs/WebAssembly/API/Instance/exports) を通してエクスポートされた関数にアクセスする。 -

いずれにしても、同じ種類の内在する関数のラッパーを取得できます。JavaScript からみると、すべての wasm 関数は JavaScript 関数のようにみえます。しかし、これは wasm 関数オブジェクトインスタンスによってカプセル化されており、アクセスする方法は限られています。

+いずれにしても、同じ種類の内在する関数のラッパーを取得できます。JavaScript からみると、すべての wasm 関数は JavaScript 関数のようにみえます。しかし、これは wasm 関数オブジェクトインスタンスによってカプセル化されており、アクセスする方法は限られています。 -

+## 例 -

物事を明らかにするために例を見ていきましょう(例は GitHub の table-set.html動作例、wasm の テキスト表現 を参照してください):

+物事を明らかにするために例を見ていきましょう(例は GitHub の [table-set.html](https://github.com/mdn/webassembly-examples/blob/master/other-examples/table-set.html) と [動作例](https://mdn.github.io/webassembly-examples/other-examples/table-set.html)、wasm の [テキスト表現](https://github.com/mdn/webassembly-examples/blob/master/ja-api-examples/table.wat) を参照してください): -
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
+```js
+var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
 
 WebAssembly.instantiateStreaming(fetch('table.wasm'))
 .then(function(obj) {
@@ -43,35 +42,38 @@ WebAssembly.instantiateStreaming(fetch('table.wasm'))
   otherTable.set(1,tbl.get(1));
   console.log(otherTable.get(0)());
   console.log(otherTable.get(1)());
-});
+}); +``` -

ここでは、{{jsxref("WebAssembly.Table")}} コンストラクタを使用して JavaScript からテーブル(otherTable)を作成し、{{jsxref("WebAssembly.instantiateStreaming()")}} ユーティリティ関数を使用して table.wasm をページに読み込みます。

+ここでは、{{jsxref("WebAssembly.Table")}} コンストラクタを使用して JavaScript からテーブル(`otherTable`)を作成し、{{jsxref("WebAssembly.instantiateStreaming()")}} ユーティリティ関数を使用して table.wasm をページに読み込みます。 -

そのあと、モジュールからエクスポートされた関数を取得し、関数の参照を tbl.get() を通して取り出し、それぞれを実行した結果をコンソールに出力します。次に、 set() を使用して、tbl テーブルと同じ関数への参照を otherTable テーブルに含まれるようにします。

+そのあと、モジュールからエクスポートされた関数を取得し、関数の参照を [`tbl.get()`](/ja/docs/WebAssembly/API/Table/get) を通して取り出し、それぞれを実行した結果をコンソールに出力します。次に、 `set()` を使用して、`tbl` テーブルと同じ関数への参照を `otherTable` テーブルに含まれるようにします。 -

確認するために、otherTable から参照を取得し直し、その結果もコンソールに出力します(同じ結果が得られます)。

+確認するために、`otherTable` から参照を取得し直し、その結果もコンソールに出力します(同じ結果が得られます)。 -

それらは本当の関数です

+## それらは本当の関数です -

前の例で、Table.prototype.get() のそれぞれの返り値はエクスポートされた WebAssembly 関数でした。まさに私達が話していたことです。

+前の例で、[`Table.prototype.get()`](/ja/docs/WebAssembly/API/Table/get) のそれぞれの返り値はエクスポートされた WebAssembly 関数でした。まさに私達が話していたことです。 -

これらは WebAssembly 関数のラッパーであるのに加えて本当の JavaScript 関数 であることに注意してください。上の例を WebAssembly をサポートするブラウザーでロードして、コンソール上で実行すると:

+これらは WebAssembly 関数のラッパーであるのに加えて本当の JavaScript 関数 であることに注意してください。上の例を [WebAssembly をサポートするブラウザー](/ja/docs/WebAssembly#Browser_compatibility)でロードして、コンソール上で実行すると: -
var testFunc = otherTable.get(0);
-typeof testFunc;
+```js +var testFunc = otherTable.get(0); +typeof testFunc; +``` -

結果として関数が返されます。この関数は他の JavaScript の他の 関数 と同じように扱うことができます(call()bind()、その他)。testFunc.toString() は興味深い結果を返します:

+結果として関数が返されます。この関数は他の JavaScript の他の [関数](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function) と同じように扱うことができます(` call()、``bind()、その他 `)。`testFunc.toString()` は興味深い結果を返します: -
function 0() {
+```js
+function 0() {
     [native code]
-}
+} +``` -

これはラッパー型の性質のアイデアの多くを提供します。

+これはラッパー型の性質のアイデアの多くを提供します。 -

エクスポートされた WebAssembly 関数について他の注意事項は:

+エクスポートされた WebAssembly 関数について他の注意事項は: -
    -
  • length プロパティは wasm 内の関数シグネチャで宣言されている引数の数です。
  • -
  • name プロパティは toString() の結果で見えている wasm モジュール内での関数のインデックスです。
  • -
  • i64 型の値を受け取る、または返すエクスポートされた wasm 関数を呼び出そうとすると、現在 JavaScript 上で i64 を表現する的確な方法がないためエラーをスローします。これは将来的に変わる可能性があります。新しい int64 型が将来の標準で検討されており、wasm によって使用される可能性があります。
  • -
+- [length](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/length) プロパティは wasm 内の関数シグネチャで宣言されている引数の数です。 +- [name](/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/name) プロパティは `toString()` の結果で見えている wasm モジュール内での関数のインデックスです。 +- i64 型の値を受け取る、または返すエクスポートされた wasm 関数を呼び出そうとすると、現在 JavaScript 上で i64 を表現する的確な方法がないためエラーをスローします。これは将来的に変わる可能性があります。新しい int64 型が将来の標準で検討されており、wasm によって使用される可能性があります。 diff --git a/files/ja/webassembly/index.md b/files/ja/webassembly/index.md index 497f89e062c027..b41ab5696cea11 100644 --- a/files/ja/webassembly/index.md +++ b/files/ja/webassembly/index.md @@ -7,109 +7,82 @@ tags: - wasm translation_of: WebAssembly --- -
{{WebAssemblySidebar}}
- -

WebAssembly はモダンなウェブブラウザーで実行できる新しいタイプのコードです。ネイティブに近いパフォーマンスで動作するコンパクトなバイナリー形式の低レベルなアセンブリ風言語です。さらに、 C/C++ や Rust のような言語のコンパイル対象となって、それらの言語をウェブ上で実行することができます。 WebAssembly は JavaScript と並行して動作するように設計されているため、両方を連携させることができます。

- -

概要

- -

WebAssembly はウェブプラットフォームに大きな影響を与えます — 以前ではできなかったようなウェブ上で動作するクライアントアプリケーションのために、複数の言語で記述されたコードをウェブ上でネイティブに近いスピードで実行する方法を提供します。

- -

WebAssembly は JavaScript を補完、並行して動作するように設計されています — WebAssembly JavaScript API を使用して、 WebAssembly モジュールを JavaScript アプリケーションにロードし、2 つの間で機能を共有できます。これにより、WebAssembly コードの記述方法を知らなくても、 WebAssembly のパフォーマンスとパワー、JavaScript の表現力と柔軟性を同じアプリケーションで活用できます。

- -

さらに、W3C WebAssembly Working GroupCommunity Group を介して、ウェブ標準として開発されており、主要なブラウザーベンダーも積極的に参加しています。

- -
-
-

ガイド

- -
-
WebAssembly のコンセプト
-
まずは WebAssembly の高レベルなコンセプト— WebAssembly とはなにか、有用性、ウェブプラットフォーム (またはそれ以上) にどのように適合するか、どのように使用するか — の理解から始めてください。
-
C/C++ から WebAssembly にコンパイルする
-
C/C++ で書いたコードを Emscripten のようなツールを使って .wasm にコンパイルできます。どのように動作するか確認してみましょう。
-
既存の C モジュール から WebAssembly へのコンパイル
-
WebAssembly のコアユースケースは、既存のCライブラリのエコシステムを利用し、開発者が Web 上でそれらを使用できるようにすることです。
-
Rust から WebAssembly へのコンパイル
-
Rust コードを書いていれば、WebAssembly にコンパイルすることができます!このチュートリアルでは、Rust プロジェクトをコンパイルして既存の Web アプリケーションで使用するために知っておく必要があるすべてのことを説明します。
-
WebAssembly コードのロードと実行
-
.wasm を手に入れたら、この記事では、Fetch または XHR API と WebAssembly JavaScript API を組み合わせて、フェッチコンパイル、インスタンス化する方法について説明します。
-
WebAssembly JavaScript API の使用
-
.wasm モジュールをロードしたら、それを使いたいでしょう。この記事では、WebAssembly JavaScript API を用いて WebAssembly を使用する方法を説明します。
-
エクスポートされた WebAssembly 関数
-
エクスポートされた WebAssembly 関数は、WebAssembly 関数の JavaScript リフレクションであり、JavaScript から WebAssembly コードを呼び出すことができます。 この記事では、それらが何なのか説明します。
-
WebAssembly テキストフォーマットを理解する
-
この記事では wasm テキスト形式について説明します。これは .wasm モジュールの低レベルなテキスト表現で、デバッグ時にブラウザーの開発者ツールに表示されます。
-
WebAssembly テキストフォーマットから wasm に変換する
-
この記事では、テキスト形式で書かれた WebAssembly モジュールを .wasm バイナリに変換する方法について説明します。
-
-
- -
-

API リファレンス

- -
-
{{jsxref("Global_objects/WebAssembly", "WebAssembly")}}
-
このオブジェクトは、 WebAssembly に関連する全ての機能の名前空間として振る舞います。
-
{{jsxref("Global_objects/WebAssembly/Global", "WebAssembly.Global()")}}
-
WebAssembly.Global オブジェクトは JavaScript と1つ以上の {{jsxref("WebAssembly.Module")}} インスタンス(のインポート/エクスポート可能な値)を横断してアクセスできるグローバル変数のインスタンスを表現します。これによって、複数モジュールでの動的リンクを実現できます。
-
{{jsxref("Global_objects/WebAssembly/Module", "WebAssembly.Module()")}}
-
WebAssembly.Module オブジェクトにはブラウザーでコンパイルされたステートレスな WebAssembly コードが含まれており、効率的に Worker で共有したり、IndexedDB にキャッシュしたり、複数回インスタンス化したりすることができます。
-
{{jsxref("Global_objects/WebAssembly/Instance", "WebAssembly.Instance()")}}
-
WebAssembly.Instance オブジェクトはステートフルで、実行可能な Module のインスタンスです。Instance オブジェクトには JavaScript から WebAssembly コードを呼び出すことを許可されたエクスポートされた WebAssembly 関数が含まれます。
-
{{jsxref("Global_objects/WebAssembly/instantiateStreaming", "WebAssembly.instantiateStreaming()")}}
-
WebAssembly.instantiate() 関数は WebAssembly コードをコンパイル、インスタンス化するための主要な API で、Module と、その最初の Instance を返します。
-
{{jsxref("Global_objects/WebAssembly/Memory", "WebAssembly.Memory()")}}
-
WebAssembly.Memory オブジェクトはリサイズ可能な {{jsxref("Global_objects/ArrayBuffer", "ArrayBuffer")}} で、 Instance からアクセスされる生のバイト列を保持します。
-
{{jsxref("Global_objects/WebAssembly/Table", "WebAssembly.Table()")}}
-
WebAssembly.Table オブジェクトは Instance からアクセスされる関数参照などの不透明値のリサイズ可能な型付き配列です。
-
{{jsxref("WebAssembly.CompileError()")}}
-
WebAssembly CompileError オブジェクトを生成します。
-
{{jsxref("WebAssembly.LinkError()")}}
-
WebAssembly LinkError オブジェクトを生成します。
-
{{jsxref("WebAssembly.RuntimeError()")}}
-
WebAssembly RuntimeError オブジェクトを生成します。
-
-
-
- -

- - - -

仕様書

- - - - - - - - - - - - - - - - -
仕様書状態備考
{{SpecName('WebAssembly JS')}}{{Spec2('WebAssembly JS')}}JavaScript API の初回ドラフト定義。
- -

ブラウザーの互換性

- -

{{Compat("javascript.builtins.WebAssembly")}}

- -

関連情報

- - +{{WebAssemblySidebar}} + +WebAssembly はモダンなウェブブラウザーで実行できる新しいタイプのコードです。ネイティブに近いパフォーマンスで動作するコンパクトなバイナリー形式の低レベルなアセンブリ風言語です。さらに、 C/C++ や Rust のような言語のコンパイル対象となって、それらの言語をウェブ上で実行することができます。 WebAssembly は JavaScript と並行して動作するように設計されているため、両方を連携させることができます。 + +## 概要 + +WebAssembly はウェブプラットフォームに大きな影響を与えます — 以前ではできなかったようなウェブ上で動作するクライアントアプリケーションのために、複数の言語で記述されたコードをウェブ上でネイティブに近いスピードで実行する方法を提供します。 + +WebAssembly は JavaScript を補完、並行して動作するように設計されています — WebAssembly JavaScript API を使用して、 WebAssembly モジュールを JavaScript アプリケーションにロードし、2 つの間で機能を共有できます。これにより、WebAssembly コードの記述方法を知らなくても、 WebAssembly のパフォーマンスとパワー、JavaScript の表現力と柔軟性を同じアプリケーションで活用できます。 + +さらに、[W3C WebAssembly Working Group](https://www.w3.org/wasm/) と [Community Group](https://www.w3.org/community/webassembly/) を介して、ウェブ標準として開発されており、主要なブラウザーベンダーも積極的に参加しています。 + +## ガイド + +- [WebAssembly のコンセプト](/ja/docs/WebAssembly/Concepts) + - : まずは WebAssembly の高レベルなコンセプト— WebAssembly とはなにか、有用性、ウェブプラットフォーム (またはそれ以上) にどのように適合するか、どのように使用するか — の理解から始めてください。 +- [C/C++ から WebAssembly にコンパイルする](/ja/docs/WebAssembly/C_to_wasm) + - : C/C++ で書いたコードを[ Emscripten](/ja/docs/Mozilla/Projects/Emscripten/) のようなツールを使って .wasm にコンパイルできます。どのように動作するか確認してみましょう。 +- [既存の C モジュール から WebAssembly へのコンパイル](/ja/docs/WebAssembly/existing_C_to_wasm) + - : WebAssembly のコアユースケースは、既存の C ライブラリのエコシステムを利用し、開発者が Web 上でそれらを使用できるようにすることです。 +- [Rust から WebAssembly へのコンパイル](/ja/docs/WebAssembly/rust_to_wasm) + - : Rust コードを書いていれば、WebAssembly にコンパイルすることができます!このチュートリアルでは、Rust プロジェクトをコンパイルして既存の Web アプリケーションで使用するために知っておく必要があるすべてのことを説明します。 +- [WebAssembly コードのロードと実行](/ja/docs/WebAssembly/Loading_and_running) + - : .wasm を手に入れたら、この記事では、[Fetch](/ja/docs/Web/API/Fetch_API) または [XHR](/ja/docs/Web/API/XMLHttpRequest) API と [WebAssembly JavaScript](/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) API を組み合わせて、フェッチコンパイル、インスタンス化する方法について説明します。 +- [WebAssembly JavaScript API の使用](/ja/docs/WebAssembly/Using_the_JavaScript_API) + - : .wasm モジュールをロードしたら、それを使いたいでしょう。この記事では、WebAssembly JavaScript API を用いて WebAssembly を使用する方法を説明します。 +- [エクスポートされた WebAssembly 関数](/ja/docs/WebAssembly/Exported_functions) + - : エクスポートされた WebAssembly 関数は、WebAssembly 関数の JavaScript リフレクションであり、JavaScript から WebAssembly コードを呼び出すことができます。 この記事では、それらが何なのか説明します。 +- [WebAssembly テキストフォーマットを理解する](/ja/docs/WebAssembly/Understanding_the_text_format) + - : この記事では wasm テキスト形式について説明します。これは .wasm モジュールの低レベルなテキスト表現で、デバッグ時にブラウザーの開発者ツールに表示されます。 +- [WebAssembly テキストフォーマットから wasm に変換する](/ja/docs/WebAssembly/Text_format_to_wasm) + - : この記事では、テキスト形式で書かれた WebAssembly モジュールを .wasm バイナリに変換する方法について説明します。 + +## API リファレンス + +- {{jsxref("Global_objects/WebAssembly", "WebAssembly")}} + - : このオブジェクトは、 WebAssembly に関連する全ての機能の名前空間として振る舞います。 +- {{jsxref("Global_objects/WebAssembly/Global", "WebAssembly.Global()")}} + - : `WebAssembly.Global` オブジェクトは JavaScript と 1 つ以上の {{jsxref("WebAssembly.Module")}} インスタンス(のインポート/エクスポート可能な値)を横断してアクセスできるグローバル変数のインスタンスを表現します。これによって、複数モジュールでの動的リンクを実現できます。 +- {{jsxref("Global_objects/WebAssembly/Module", "WebAssembly.Module()")}} + - : `WebAssembly.Module` オブジェクトにはブラウザーでコンパイルされたステートレスな WebAssembly コードが含まれており、効率的に [Worker で共有](/ja/docs/Web/API/Worker/postMessage)したり、[IndexedDB にキャッシュ](/ja/docs/WebAssembly/Caching_modules)したり、複数回インスタンス化したりすることができます。 +- {{jsxref("Global_objects/WebAssembly/Instance", "WebAssembly.Instance()")}} + - : `WebAssembly.Instance` オブジェクトはステートフルで、実行可能な `Module` のインスタンスです。`Instance` オブジェクトには JavaScript から WebAssembly コードを呼び出すことを許可された[エクスポートされた WebAssembly 関数](/ja/docs/WebAssembly/Exported_functions)が含まれます。 +- {{jsxref("Global_objects/WebAssembly/instantiateStreaming", "WebAssembly.instantiateStreaming()")}} + - : `WebAssembly.instantiate()` 関数は WebAssembly コードをコンパイル、インスタンス化するための主要な API で、`Module` と、その最初の `Instance` を返します。 +- {{jsxref("Global_objects/WebAssembly/Memory", "WebAssembly.Memory()")}} + - : `WebAssembly.Memory` オブジェクトはリサイズ可能な {{jsxref("Global_objects/ArrayBuffer", "ArrayBuffer")}} で、 `Instance` からアクセスされる生のバイト列を保持します。 +- {{jsxref("Global_objects/WebAssembly/Table", "WebAssembly.Table()")}} + - : `WebAssembly.Table` オブジェクトは `Instance` からアクセスされる関数参照などの不透明値のリサイズ可能な型付き配列です。 +- {{jsxref("WebAssembly.CompileError()")}} + - : WebAssembly `CompileError` オブジェクトを生成します。 +- {{jsxref("WebAssembly.LinkError()")}} + - : WebAssembly `LinkError` オブジェクトを生成します。 +- {{jsxref("WebAssembly.RuntimeError()")}} + - : WebAssembly `RuntimeError` オブジェクトを生成します。 + +## 例 + +- [WASMSobel](https://github.com/JasonWeathersby/WASMSobel) +- 他の多くの例については [webassembly-examples](https://github.com/mdn/webassembly-examples/) レポジトリーを参照してください。 + +## 仕様書 + +| 仕様書 | 状態 | 備考 | +| ---------------------------------------- | ------------------------------------ | ----------------------------------- | +| {{SpecName('WebAssembly JS')}} | {{Spec2('WebAssembly JS')}} | JavaScript API の初回ドラフト定義。 | + +## ブラウザーの互換性 + +{{Compat("javascript.builtins.WebAssembly")}} + +## 関連情報 + +- [WebAssembly on Mozilla Research](https://research.mozilla.org/webassembly/) +- [webassembly.org](http://webassembly.org/) +- [WebAssembly articles on Mozilla Hacks blog](https://hacks.mozilla.org/category/webassembly/) +- [W3C WebAssembly Community Group](https://www.w3.org/community/webassembly/) +- [Large-Allocation HTTP header](/ja/docs/Web/HTTP/Headers/Large-Allocation) +- [Emscripting a C Library to Wasm](https://developers.google.com/web/updates/2018/03/emscripting-a-c-library) diff --git a/files/ja/webassembly/loading_and_running/index.md b/files/ja/webassembly/loading_and_running/index.md index b105e5cdbf84c2..500df1cc2bed1b 100644 --- a/files/ja/webassembly/loading_and_running/index.md +++ b/files/ja/webassembly/loading_and_running/index.md @@ -9,64 +9,67 @@ tags: - バイトコード translation_of: WebAssembly/Loading_and_running --- -
{{WebAssemblySidebar}}
+{{WebAssemblySidebar}} -

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

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

どんな方法があるの?

+## どんな方法があるの? -

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

+WebAssembly は ` + + +``` + +最後に、HTML ファイルで参照される `index.js` を作成し、以下の内容を追加してください。 + +```js +const js = import("./node_modules/@yournpmusername/hello-wasm/hello_wasm.js"); +js.then(js => { js.greet("WebAssembly"); -}); +}); +``` -

また npm のユーザー名を記入する必要があることに注意してください。

+また npm のユーザー名を記入する必要があることに注意してください。 -

これは新しいモジュールを node_modules フォルダーからインポートします。これは最善の方法ではないと思いますが、デモなので、これでいいでしょう。一度そのモジュールが読み込まれると、そこから greet 関数を呼び出し、"WebAssembly" を文字列として渡します。ここに特別なことはなにもありませんが、Rust コードを呼び出していることに注意してください。JavaScript コードから観察する限り、これはただの普通のモジュールです。

+これは新しいモジュールを `node_modules` フォルダーからインポートします。これは最善の方法ではないと思いますが、デモなので、これでいいでしょう。一度そのモジュールが読み込まれると、そこから `greet` 関数を呼び出し、`"WebAssembly"` を文字列として渡します。ここに特別なことはなにもありませんが、Rust コードを呼び出していることに注意してください。JavaScript コードから観察する限り、これはただの普通のモジュールです。 -

ファイルを作りました。これを試してみましょう。

+ファイルを作りました。これを試してみましょう。 -
$ npm install
-$ npm run serve
+```bash +$ npm install +$ npm run serve +``` -

これでウェブサーバーが起動します。http://localhost:8080 を読み込んでください。Hello, WebAssembly! と書かれたアラートボックスが画面に出てくるはずです。JavaScript からの Rust の呼び出しと Rust からの JavaScript の呼び出しに成功しました。

+これでウェブサーバーが起動します。http\://localhost:8080 を読み込んでください。`Hello, WebAssembly!` と書かれたアラートボックスが画面に出てくるはずです。JavaScript からの Rust の呼び出しと Rust からの JavaScript の呼び出しに成功しました。 -

結び

+## 結び -

ここでチュートリアルは終わりです。あなたの役に立ったと思われることを望みます。

+ここでチュートリアルは終わりです。あなたの役に立ったと思われることを望みます。 -

この領域にはたくさんの進行中の刺激的な仕事があります。もしそれをもっとよくするのを手伝いたいなら、Rust Webassembly Working Group を確認してください。

+この領域にはたくさんの進行中の刺激的な仕事があります。もしそれをもっとよくするのを手伝いたいなら、[Rust Webassembly Working Group](http://fitzgeraldnick.com/2018/02/27/wasm-domain-working-group.html) を確認してください。 diff --git a/files/ja/webassembly/text_format_to_wasm/index.md b/files/ja/webassembly/text_format_to_wasm/index.md index dd011ff444281b..196d39c3d73154 100644 --- a/files/ja/webassembly/text_format_to_wasm/index.md +++ b/files/ja/webassembly/text_format_to_wasm/index.md @@ -12,17 +12,15 @@ tags: - wat2wasm translation_of: WebAssembly/Text_format_to_wasm --- -

{{WebAssemblySidebar}}

+{{WebAssemblySidebar}} -

WebAssembly にはS式ベースのテキスト表現があります。これはテキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現です。この記事では、これがどのように動作するか、テキスト形式のファイルを .wasm アセンブリ形式に変換するのに利用可能なツールの使用方法について少し説明します。

+WebAssembly には S 式ベースのテキスト表現があります。これはテキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現です。この記事では、これがどのように動作するか、テキスト形式のファイルを `.wasm` アセンブリ形式に変換するのに利用可能なツールの使用方法について少し説明します。 -
-

: テキスト形式のファイルは通常 .wat という拡張子で保存されます。場合によっては .wast も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。

-
+> **Note:** **注**: テキスト形式のファイルは通常 `.wat` という拡張子で保存されます。場合によっては `.wast` も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。 -

はじめてのテキストフォーマット

+## はじめてのテキストフォーマット -

簡単な例を見てみましょう。次のプログラムは imports というモジュールから imported_func という名前の関数をインポートし、exported_func という名前の関数をエクスポートしています:

+簡単な例を見てみましょう。次のプログラムは `imports` というモジュールから `imported_func` という名前の関数をインポートし、`exported_func` という名前の関数をエクスポートしています:
(module
   (func $i (import "imports" "imported_func") (param i32))
@@ -32,43 +30,41 @@ translation_of: WebAssembly/Text_format_to_wasm
   )
 )
-

WebAssembly 関数 exported_func は私達の環境 (WebAssembly モジュールを使用しているウェブアプリケーションなど) で使用するためにエクスポートされます。この関数が呼び出されたとき、インポートされた JavaScript 関数 imported_func パラメータとして値 (42) を渡して実行されます。

+WebAssembly 関数 `exported_func` は私達の環境 (WebAssembly モジュールを使用しているウェブアプリケーションなど) で使用するためにエクスポートされます。この関数が呼び出されたとき、インポートされた JavaScript 関数 `imported_func` パラメータとして値 (42) を渡して実行されます。 -

テキストの .wat ファイルからバイナリの .wasm ファイルに変換する

+## テキストの .wat ファイルからバイナリの .wasm ファイルに変換する -

上の .wat テキスト表現の例を .wasm アセンブリ形式に変換してみましょう。

+上の `.wat` テキスト表現の例を `.wasm` アセンブリ形式に変換してみましょう。 -
    -
  1. はじめに、上のコードをテキストファイルにコピーして simple.wat という名前のファイルを作成します。
  2. -
  3. このテキスト表現をブラウザが実際に読み込んで利用可能なアセンブリ言語にアセンブルする必要があります。 このために wabt ツールを使用することができます。これは WebAssembly のテキスト表現から wasm 変換する、または逆に変換するコンパイラ(加えてもう少し別のツール)が含まれます。https://github.com/webassembly/wabt に行って、そのページの説明に従ってツールの設定をします。
  4. -
  5. ツールをビルドしたら、システム PATH/wabt/out ディレクトリを追加します。
  6. -
  7. 次に、wast2wasm プログラムを実行します。入力ファイルパス、続いて -o パラメータ、出力ファイルパスを指定します: -
    wat2wasm simple.wat -o simple.wasm
    -
  8. -
+1. はじめに、上のコードをテキストファイルにコピーして `simple.wat` という名前のファイルを作成します。 +2. このテキスト表現をブラウザが実際に読み込んで利用可能なアセンブリ言語にアセンブルする必要があります。 このために wabt ツールを使用することができます。これは WebAssembly のテキスト表現から wasm 変換する、または逆に変換するコンパイラ(加えてもう少し別のツール)が含まれます。 に行って、そのページの説明に従ってツールの設定をします。 +3. ツールをビルドしたら、システム `PATH` に `/wabt/out` ディレクトリを追加します。 +4. 次に、wast2wasm プログラムを実行します。入力ファイルパス、続いて `-o` パラメータ、出力ファイルパスを指定します: -

これで simple.wasm という名前のファイルに wasm が出力されます。これには .wasm アセンブリのコードが含まれます。

+ ```bash + wat2wasm simple.wat -o simple.wasm + ``` -
-

: wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: wasm2wat simple.wasm -o text.wat.

-
+これで `simple.wasm` という名前のファイルに wasm が出力されます。これには `.wasm` アセンブリのコードが含まれます。 -

アセンブリの出力を見る

+> **Note:** **注**: wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: `wasm2wat simple.wasm -o text.wat`. -

出力されたファイルはアセンブリベースなので通常のテキストエディタで表示することができません。ただし、wat2wasm ツールの -v オプションを使用して見ることができます。以下を試してみてください:

+## アセンブリの出力を見る -
wat2wasm simple.wat -v
+出力されたファイルはアセンブリベースなので通常のテキストエディタで表示することができません。ただし、wat2wasm ツールの `-v` オプションを使用して見ることができます。以下を試してみてください: -

ターミナルには次のように出力されるでしょう:

+```bash +wat2wasm simple.wat -v +``` -

several strings of binary with textual descriptions beside them. For example: 0000008: 01 ; section code

+ターミナルには次のように出力されるでしょう: -

関連情報

+![several strings of binary with textual descriptions beside them. For example: 0000008: 01 ; section code ](/en-US/docs/WebAssembly/Text_format_to_wasm/assembly-output.png) -
    -
  • WebAssembly テキストフォーマットを理解する — テキスト形式のシンタックスの詳細説明。
  • -
  • C/C++ から WebAssembly にコンパイルする — Binaryen/Emscripten のようなツールはソースコードを wasm にコンパイルし、JavaScript のコンテキストでモジュールを実行するために必要な API コードを作成します。それらの使用方法の詳細はこちらから探してください。
  • -
  • WebAssembly JavaScript API の使用 — WebAssembly API コードがどのように機能するかについて詳しく知りたい場合はこちらをお読みください。
  • -
  • Text format — WebAssembly GitHub レポジトリのテキスト形式の詳細説明。
  • -
  • wast-loader — あなたのためにこれをすべて処理する WebPack のローダーです。
  • -
+## 関連情報 + +- [WebAssembly テキストフォーマットを理解する](/ja/docs/WebAssembly/Understanding_the_text_format) — テキスト形式のシンタックスの詳細説明。 +- [C/C++ から WebAssembly にコンパイルする](/ja/docs/WebAssembly/C_to_wasm) — Binaryen/Emscripten のようなツールはソースコードを wasm にコンパイルし、JavaScript のコンテキストでモジュールを実行するために必要な API コードを作成します。それらの使用方法の詳細はこちらから探してください。 +- [WebAssembly JavaScript API の使用](/ja/docs/WebAssembly/Using_the_JavaScript_API) — WebAssembly API コードがどのように機能するかについて詳しく知りたい場合はこちらをお読みください。 +- [Text format](https://webassembly.github.io/spec/core/text/index.html) — WebAssembly GitHub レポジトリのテキスト形式の詳細説明。 +- [wast-loader](https://github.com/xtuc/webassemblyjs/tree/master/packages/wast-loader) — あなたのためにこれをすべて処理する WebPack のローダーです。 From bc0de16f6acf5d49f75308ea06f20790a7964f10 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 18 Aug 2022 17:56:21 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E8=87=AA=E5=8B=95=E5=A4=89=E6=8F=9B?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E9=83=A8?= =?UTF-8?q?=E5=88=86=E3=82=92=E5=A4=89=E6=8F=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/webassembly/text_format_to_wasm/index.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/files/ja/webassembly/text_format_to_wasm/index.md b/files/ja/webassembly/text_format_to_wasm/index.md index 196d39c3d73154..bb635c57b97499 100644 --- a/files/ja/webassembly/text_format_to_wasm/index.md +++ b/files/ja/webassembly/text_format_to_wasm/index.md @@ -16,19 +16,21 @@ translation_of: WebAssembly/Text_format_to_wasm WebAssembly には S 式ベースのテキスト表現があります。これはテキストエディタ、ブラウザの開発者ツールなどで見せるために設計された中間表現です。この記事では、これがどのように動作するか、テキスト形式のファイルを `.wasm` アセンブリ形式に変換するのに利用可能なツールの使用方法について少し説明します。 -> **Note:** **注**: テキスト形式のファイルは通常 `.wat` という拡張子で保存されます。場合によっては `.wast` も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。 +> **Note:** テキスト形式のファイルは通常 `.wat` という拡張子で保存されます。場合によっては `.wast` も使われます。これはアサーションなどの変換時に .wasm に含まれない特別なテストコマンドを含むファイルを指します。 ## はじめてのテキストフォーマット 簡単な例を見てみましょう。次のプログラムは `imports` というモジュールから `imported_func` という名前の関数をインポートし、`exported_func` という名前の関数をエクスポートしています: -
(module
+```wasm
+(module
   (func $i (import "imports" "imported_func") (param i32))
   (func (export "exported_func")
     i32.const 42
     call $i
   )
-)
+) +``` WebAssembly 関数 `exported_func` は私達の環境 (WebAssembly モジュールを使用しているウェブアプリケーションなど) で使用するためにエクスポートされます。この関数が呼び出されたとき、インポートされた JavaScript 関数 `imported_func` パラメータとして値 (42) を渡して実行されます。 @@ -47,7 +49,7 @@ WebAssembly 関数 `exported_func` は私達の環境 (WebAssembly モジュー これで `simple.wasm` という名前のファイルに wasm が出力されます。これには `.wasm` アセンブリのコードが含まれます。 -> **Note:** **注**: wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: `wasm2wat simple.wasm -o text.wat`. +> **Note:** wasm2wat を使用して wasm から テキスト表現に戻すことができます。例: `wasm2wat simple.wasm -o text.wat`. ## アセンブリの出力を見る From 45914a3ba9a42034e3f4691d5587d29df58c34c6 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 18 Aug 2022 18:13:31 +0900 Subject: [PATCH 4/4] =?UTF-8?q?2022/08/13=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=90=8C=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/webassembly/rust_to_wasm/index.md | 195 ++++++++++++--------- 1 file changed, 113 insertions(+), 82 deletions(-) diff --git a/files/ja/webassembly/rust_to_wasm/index.md b/files/ja/webassembly/rust_to_wasm/index.md index 38730c63fcd516..dcacb92aaa496f 100644 --- a/files/ja/webassembly/rust_to_wasm/index.md +++ b/files/ja/webassembly/rust_to_wasm/index.md @@ -2,19 +2,21 @@ title: Rust から WebAssembly にコンパイルする slug: WebAssembly/Rust_to_wasm tags: + - Compiling - WebAssembly - rust - wasm - - コンパイル translation_of: WebAssembly/Rust_to_wasm +l10n: + sourceCommit: 51f2cde58fff4a44242577b2540bdfdfc525dda4 --- {{WebAssemblySidebar}} Rust のコードがあれば、それを [WebAssembly](/ja/docs/WebAssembly) (wasm) にコンパイルすることができます。このチュートリアルでは Rust プロジェクトをコンパイルして既存のウェブアプリケーションで使用するために必要なことについて説明します。 -## Rust と WebAssembly のユースケース +## Rust と WebAssembly の用途 -Rust と WebAssembly には、主に 2 つのユースケースがあります。 +Rust と WebAssembly には、主に 2 つの用途があります。 - アプリケーション全体を構築する — ウェブアプリ全体を Rust ベースで構築します。 - アプリケーションの一部を構築する — 既存の JavaScript フロントエンドの内部で Rust を使用します。 @@ -41,34 +43,9 @@ Rust と WebAssembly には、主に 2 つのユースケースがあります $ cargo install wasm-pack ``` -### Node.js のインストールと npm アカウントの取得 +## WebAssembly パッケージのビルド -このチュートリアルでは npm パッケージをビルドするので、Node.js と npm のインストールが必要になります。さらに、パッケージを npm にパブリッシュするので、npm アカウントも必要になります。それらは無料です。*技術的には*パッケージをパブリッシュする必要はありませんが、そのほうが簡単に使用できるので、このチュートリアルではそうすると仮定します。 - -Node.js と npm を取得するために、[Get npm!](https://www.npmjs.com/get-npm) ページに行き、手順に従ってください。バージョンの選択に関しては、好きなバージョンを選択してください。このチュートリアルはバージョンに特有ではありません。 - -npm アカウントを取得するために、[npm signup page](https://www.npmjs.com/signup) に行き、フォームに記入してください。 - -次に、コマンドラインで `npm adduser` を実行してください。 - -```bash -$ npm adduser -Username: yournpmusername -Password: -Email: (this IS public) you@example.com -``` - -ユーザー名とパスワードとメールアドレスを記入してください。うまくいけば、以下の表示が見られます。 - -```bash -Logged in as yournpmusername on https://registry.npmjs.org/. -``` - -もし何かうまくいかなければ、トラブルシューティングのヘルプを得るために npm に連絡してください。 - -## WebAssembly の npm パッケージのビルド - -セットアップは以上です。Rust で新しいパッケージを作りましょう。個人的なプロジェクトを置いておく場所へ移動して以下を実行してください。 +セットアップは以上です。 Rust で新しいパッケージを作りましょう。個人的なプロジェクトを置いておく場所へ移動して以下を実行してください。 ```bash $ cargo new --lib hello-wasm @@ -77,21 +54,25 @@ $ cargo new --lib hello-wasm これにより新たなライブラリが出発に必要なものすべてと一緒に `hello-wasm` という名前のサブディレクトリーに作成されます。 -
+-- Cargo.toml
+```plain
++-- Cargo.toml
 +-- src
-    +-- lib.rs
+ +-- lib.rs +``` まず `Cargo.toml` があります。これはビルドを設定するためのファイルです。もし `Gemfile` を Bundler から使ったり、`package.json` を npm から使ったりしたことがあるなら、なじみがあるでしょう。cargo は両者と似たような動作をします。 -次に、cargo はいくつかの Rust コードを `src/lib.rs` に生成してくれています。 +次に、 Cargo はいくつかの Rust コードを `src/lib.rs` に生成してくれています。 -
#[cfg(test)]
+```rust
+#[cfg(test)]
 mod tests {
     #[test]
     fn it_works() {
         assert_eq!(2 + 2, 4);
     }
-}
+} +``` このチュートリアルでは、このテストコードはまったく使わないので、消してください。 @@ -99,19 +80,19 @@ mod tests { 代わりに以下のコードを `src/lib.rs` に書き込みましょう。 -
extern crate wasm_bindgen;
-
+```rust
 use wasm_bindgen::prelude::*;
 
 #[wasm_bindgen]
 extern {
-    pub fn alert(s: &str);
+    pub fn alert(s: &str);
 }
 
 #[wasm_bindgen]
-pub fn greet(name: &str) {
-    alert(&format!("Hello, {}!", name));
-}
+pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); +} +``` これが Rust プロジェクトの中身です。三つの主要な部分があります。順番に説明しましょう。ここでは高水準な説明を行い、細部は省略します。Rust についてもっと学びたいのであれば、無料のオンラインブック [The Rust Programming Language](https://doc.rust-lang.org/book/) (訳注: [和訳](https://doc.rust-jp.rs/book/second-edition/)もあります) を確認してください。 @@ -119,11 +100,11 @@ pub fn greet(name: &str) { 最初の部分は以下のようになっています。 -
extern crate wasm_bindgen;
-
-use wasm_bindgen::prelude::*;
+```rust +use wasm_bindgen::prelude::*; +``` -1 行目は「やあ Rust、`wasm_bindgen` というライブラリを使ってるよ」ということです。ライブラリは Rust では「クレート」と呼ばれ、外部 (external) のクレートを使っているので `extern` キーワードを使用しています。 +ライブラリは Rust では「クレート」と呼ばれます。 理解できましたか? _Cargo_ が*クレート*を取り入れるのです。 @@ -139,10 +120,12 @@ use wasm_bindgen::prelude::*; 次の部分は以下のようになっています。 -
#[wasm_bindgen]
+```rust
+#[wasm_bindgen]
 extern {
-    pub fn alert(s: &str);
-}
+ pub fn alert(s: &str); +} +``` `#[ ]` の内側は「アトリビュート」と呼ばれ、次に来る文を何らかの形で修飾します。この場合、その文は外部で定義された関数を呼び出したいことを Rust に伝える `extern` です。アトリビュートは「wasm-bindgen はこれらの関数を見つける方法を知っている」ということを意味しています。 @@ -156,10 +139,12 @@ JavaScript 関数を呼び出したい時はいつでも、このファイルに 最後の部分は以下のコードです。 -
#[wasm_bindgen]
-pub fn greet(name: &str) {
-    alert(&format!("Hello, {}!", name));
-}
+```rust +#[wasm_bindgen] +pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); +} +``` 再び `#[wasm_bindgen]` アトリビュートが目に入ります。この場合、`extern` ブロックではなく `fn` を改変しています。これは JavaScript がこの Rust 関数を呼び出せるようにしてほしいということを意味します。これは `extern` とは逆です。自分が必要とする関数ではなく、外の世界に渡す関数なのです。 @@ -175,19 +160,22 @@ pub fn greet(name: &str) { コードを正しくコンパイルするには、はじめに `Cargo.toml` で設定する必要があります。`Cargo.toml` を開き、以下のように中身を変更してください。 -
[package]
+```toml
+[package]
 name = "hello-wasm"
 version = "0.1.0"
-authors = ["Your Name <you@example.com>"]
+authors = ["Your Name "]
 description = "A sample project with wasm-pack"
 license = "MIT/Apache-2.0"
 repository = "https://github.com/yourgithubusername/hello-wasm"
+edition = "2018"
 
 [lib]
 crate-type = ["cdylib"]
 
 [dependencies]
-wasm-bindgen = "0.2"
+wasm-bindgen = "0.2" +``` 自分自身のリポジトリを記入し、`git` が `authors` フィールドに使用するものと同じ情報を使用してください。 @@ -200,7 +188,7 @@ wasm-bindgen = "0.2" すべてのセットアップが完了したので、ビルドしましょう。ターミナルに以下のものを入力してください。 ```bash -$ wasm-pack build --scope mynpmusername +$ wasm-pack build --target web ``` このコマンドは多くのことをします (そして時間がかかます。特に初めて `wasm-pack` を実行したときはそうです)。それらについて詳しく学ぶには、[Mozilla Hacks のこのブログ投稿](https://hacks.mozilla.org/2018/04/hello-wasm-pack/)を確認してください。手短に説明すると、`wasm-pack build` は次のことをします。 @@ -217,16 +205,63 @@ $ wasm-pack build --scope mynpmusername 生成された WebAssembly のコードサイズについて確認すると、それはおそらく数百キロバイトでしょう。Rust にはサイズの最適化をまったく指示しておらず、最適化すればサイズを大幅に削減できます。これはこのチュートリアルの脱線ですが、もしもっと学習したいなら、Rust WebAssembly Working Group の[.wasm のサイズの縮小](https://rustwasm.github.io/book/game-of-life/code-size.html#shrinking-wasm-size)を確認してください。 -### パッケージの npm への発行 +## パッケージのウェブでの利用 + +さて、コンパイルされた wasm モジュールが入手できたので、ブラウザーで動かしてみましょう。 + +まず、プロジェクトのルートに `index.html` という名前のファイルを作成し、以下のような内容にしてみましょう。 + +```html + + + + + hello-wasm example + + + + + +``` + +このファイルのスクリプトは、js グルーコードをインポートし、wasm モジュールを初期化し、rust で書いた `greet` 関数を呼び出します。 -この新たなパッケージを npm レジストリに発行しましょう。 +プロジェクトのルートディレクトリに、ローカルのウェブサーバーを用意します(例: `python3 -m http.server` )。やり方がよくわからない場合は、[シンプルなローカル HTTP サーバーの実行](/ja/docs/Learn/Common_questions/set_up_a_local_testing_server#running_a_simple_local_http_server)を参考にしてください。 + +> **Note:** 必ず `application/wasm` という MIME 型に対応している最新のウェブサーバーを使用してください。古いウェブサーバーでは、まだ対応していないかもしれません。 + +ウェブサーバーから `index.html` を読み込む (Python3 の例を使用する場合: `http://localhost:8000`)。 画面上にアラートボックスが現れ、 `Hello, WebAssembly!` と表示されます。 JavaScript から Rust へ、そして Rust から JavaScript への呼び出しに成功しました。 + +## npm でパッケージが利用できるようにする + +WebAssembly モジュールを npm で使用する場合、いくつかの変更が必要です。 + +まず、Rust を target bundler オプションで再コンパイルすることから始めましょう。 + +```bash +$ wasm-pack build --target bundler +``` + +### Node.js と npm のインストール + +npmパッケージを構築しているので、Node.jsと npm をインストールしておく必要があります。 + +Node.js と npm を入手するには、 [Get npm!](https://docs.npmjs.com/getting-started/) ページへ移動して指示に従ってください。バージョンは好きなものを選んでください。このチュートリアルはバージョンを詳細に指定するものではありません。 + +次に、インストールした他の JavaScript パッケージがこのパッケージを利用できるようにするために、 \`npm link\` を使用しましょう。 ```bash $ cd pkg -$ npm publish --access=public +$ npm link ``` -Rust で書かれ、WebAssembly にコンパイルされた npm パッケージができました。JavaScript から利用する準備ができており、ユーザーが Rust をインストールすることを必要としません。コードに含まれているのは WebAssembly コードであり、Rust のソースではないのです。 +Rust で書かれ、 WebAssembly にコンパイルされた npm パッケージができました。JavaScript から利用する準備ができており、ユーザーが Rust をインストールすることを必要としません。コードに含まれているのは WebAssembly コードであり、Rust のソースではないのです。 ## パッケージのウェブでの利用 @@ -235,9 +270,10 @@ Rust で書かれ、WebAssembly にコンパイルされた npm パッケージ `pkg` ディレクトリーの外に戻り、新たなディレクトリー `site` を作成し、そこでこれを試してみましょう。 ```bash -$ cd ../.. +$ cd .. $ mkdir site $ cd site +$ npm link hello-wasm ``` 新しいファイル `package.json` を作成し、次のコードをそこに書き込んでください。 @@ -248,7 +284,7 @@ $ cd site "serve": "webpack-dev-server" }, "dependencies": { - "@mynpmusername/hello-wasm": "^0.1.0" + "hello-wasm": "^0.1.0" }, "devDependencies": { "webpack": "^4.25.1", @@ -258,8 +294,6 @@ $ cd site } ``` -dependencies の項の `@` の後に自分自身のユーザー名を記入する必要があることに注意してください。 - 次に、Webpack を設定する必要があります。`webpack.config.js` を作成し、そこに次のことを記入してください。 ```js @@ -274,11 +308,21 @@ module.exports = { }; ``` -さて HTML ファイルが必要です。`index.html` を作成し、次の内容を追加してください。 +次に、HTML ファイルで参照される `index.js` を作成し、以下の内容を追加してください。 + +```js +import("./node_modules/hello-wasm/hello_wasm.js").then((js) => { + js.greet("WebAssembly with npm"); +}); +``` + +まこれは新しいモジュールを `node_modules` フォルダーからインポートします。これは最善の方法ではないと思いますが、デモなので、これでいいでしょう。一度そのモジュールが読み込まれると、そこから `greet` 関数を呼び出し、`"WebAssembly"` を文字列として渡します。ここに特別なことはなにもありませんが、Rust コードを呼び出していることに注意してください。JavaScript コードから観察する限り、これはただの普通のモジュールです。 + +最後に HTML ファイルが必要です。 `index.html` を作成し、次の内容を追加してください。 ```html - + hello-wasm example @@ -289,19 +333,6 @@ module.exports = { ``` -最後に、HTML ファイルで参照される `index.js` を作成し、以下の内容を追加してください。 - -```js -const js = import("./node_modules/@yournpmusername/hello-wasm/hello_wasm.js"); -js.then(js => { - js.greet("WebAssembly"); -}); -``` - -また npm のユーザー名を記入する必要があることに注意してください。 - -これは新しいモジュールを `node_modules` フォルダーからインポートします。これは最善の方法ではないと思いますが、デモなので、これでいいでしょう。一度そのモジュールが読み込まれると、そこから `greet` 関数を呼び出し、`"WebAssembly"` を文字列として渡します。ここに特別なことはなにもありませんが、Rust コードを呼び出していることに注意してください。JavaScript コードから観察する限り、これはただの普通のモジュールです。 - ファイルを作りました。これを試してみましょう。 ```bash @@ -309,10 +340,10 @@ $ npm install $ npm run serve ``` -これでウェブサーバーが起動します。http\://localhost:8080 を読み込んでください。`Hello, WebAssembly!` と書かれたアラートボックスが画面に出てくるはずです。JavaScript からの Rust の呼び出しと Rust からの JavaScript の呼び出しに成功しました。 +これでウェブサーバーが起動します。 `http://localhost:8080` を読み込んでください。 `Hello, WebAssembly!` と書かれたアラートボックスが画面に出てくるはずです。JavaScript からの Rust の呼び出しと Rust からの JavaScript の呼び出しに成功しました。 -## 結び +## おわりに ここでチュートリアルは終わりです。あなたの役に立ったと思われることを望みます。 -この領域にはたくさんの進行中の刺激的な仕事があります。もしそれをもっとよくするのを手伝いたいなら、[Rust Webassembly Working Group](http://fitzgeraldnick.com/2018/02/27/wasm-domain-working-group.html) を確認してください。 +この領域にはたくさんの進行中の刺激的な仕事があります。もしそれをもっとよくするのを手伝いたいなら、 [the Rust WebAssembly Working Group](https://fitzgeraldnick.com/2018/02/27/wasm-domain-working-group.html) を確認してください。