From 244f22e150841094b591103b5552d442ddfefd80 Mon Sep 17 00:00:00 2001 From: julieng Date: Thu, 11 Nov 2021 07:39:13 +0100 Subject: move *.html to *.md --- files/fr/webassembly/c_to_wasm/index.html | 187 ------------- files/fr/webassembly/c_to_wasm/index.md | 187 +++++++++++++ files/fr/webassembly/concepts/index.html | 135 ---------- files/fr/webassembly/concepts/index.md | 135 ++++++++++ files/fr/webassembly/exported_functions/index.html | 69 ----- files/fr/webassembly/exported_functions/index.md | 69 +++++ files/fr/webassembly/index.html | 104 -------- files/fr/webassembly/index.md | 104 ++++++++ .../fr/webassembly/loading_and_running/index.html | 108 -------- files/fr/webassembly/loading_and_running/index.md | 108 ++++++++ .../using_the_javascript_api/index.html | 292 --------------------- .../webassembly/using_the_javascript_api/index.md | 292 +++++++++++++++++++++ 12 files changed, 895 insertions(+), 895 deletions(-) delete mode 100644 files/fr/webassembly/c_to_wasm/index.html create mode 100644 files/fr/webassembly/c_to_wasm/index.md delete mode 100644 files/fr/webassembly/concepts/index.html create mode 100644 files/fr/webassembly/concepts/index.md delete mode 100644 files/fr/webassembly/exported_functions/index.html create mode 100644 files/fr/webassembly/exported_functions/index.md delete mode 100644 files/fr/webassembly/index.html create mode 100644 files/fr/webassembly/index.md delete mode 100644 files/fr/webassembly/loading_and_running/index.html create mode 100644 files/fr/webassembly/loading_and_running/index.md delete mode 100644 files/fr/webassembly/using_the_javascript_api/index.html create mode 100644 files/fr/webassembly/using_the_javascript_api/index.md diff --git a/files/fr/webassembly/c_to_wasm/index.html b/files/fr/webassembly/c_to_wasm/index.html deleted file mode 100644 index b55618c1de..0000000000 --- a/files/fr/webassembly/c_to_wasm/index.html +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Compiler un nouveau module C/C++ en WebAssembly -slug: WebAssembly/C_to_wasm -tags: - - C - - C++ - - Compilation - - Emscripten - - WebAssembly - - wasm -translation_of: WebAssembly/C_to_wasm ---- -
{{WebAssemblySidebar}}
- -

Quand vous avez écrit un module de code dans un langage comme le C/C++, vous pouvez ensuite le compiler en WebAssembly en utilisant un outil comme Emscripten. Regardons comment cela fonctionne.

- -

Mise en place de l'environnement Emscripten

- -

D'abord, mettons en place l'environnement requis pour le développement.

- -

Prérequis

- -

Recuperer le SDK de Emscripten en utilisant les instructions suivantes: https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

- -

Compiler un exemple

- -

Une fois l'environnement mis en place, regardons comment l'utiliser pour compiler un exemple en C via Emscripten. Il existe un certain nombre d'options disponibles quand on compile avec Emscripten, mais nous allons couvrir seulement les deux principaux scénarios:

- - - -

Nous verrons les deux par la suite.

- -

Créer le document HTML et la "glue" JavaScript

- -

C'est le cas le plus simple que nous allons voir, pour lequel vous utiliserez Emscripten pour générer tout ce dont vous avez besoin pour exécuter votre code en WebAssembly dans le navigateur. 

- -
    -
  1. D'abord nous avons besoin d'un exemple à compiler. Prenez une copie du simple programme C suivant et sauvez-le dans un fichier nommé hello.c dans un nouveau répertoire de votre disque dur: - -
    #include <stdio.h>
    -
    -int main(int argc, char ** argv) {
    -  printf("Hello World\n");
    -}
    -
  2. -
  3. Maintenant, en utilisant la fenêtre terminal qui vous a servi pour entrer dans l'environnement du compilateur Emscripten, naviguez jusqu'au répertoire dans lequel se trouve votre fichier hello.c et exécutez la commande suivante : -
    emcc hello.c -s WASM=1 -o hello.html
    -
  4. -
- -

Les options passées avec la commande sont les suivantes :

- - - -

À ce stade votre dossier source devrait contenir :

- - - -

Exécuter votre exemple

- -

Maintenant, tout ce qui vous reste à faire est de charger le fichier hello.html dans un navigateur qui supporte WebAssembly. Il est activé par défaut dans Firefox 52+, Chrome 57+ et dans la derniere version d'Opera (vous pouvez aussi executer du code wasm dans Firefox 47+ en activant le flag javascript.options.wasm dans about:config, ou dans Chrome (51+) et Opera (38+) en allant dans chrome://flags and en activant le flag Experimental WebAssembly.)

- -

Si tout a fonctionné comme prévu, vous devriez voir la sortie "Hello World" dans la console Emscripten apparaissant dans la page web et dans la console Javascript de votre navigateur. Bravo, vous venez de compiler un programme C en WebAssembly puis d'executer ce programme dans votre navigateur!   

- -

Utiliser un template HTML personnalisé

- -

Vous souhaiterez parfois utiliser un template HTML personnalisé. Voyons comment faire :

- -
    -
  1. -

    Tout d'abord, sauvegarder le code C suivant dans un fichier nommé hello2.c, au sein d'un nouveau dossier (vide) :

    - -
    #include <stdio.h>
    -
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    -
    -}
    -
  2. -
  3. -

    Cherchez le fichier shell_minimal.html dans le dépôt emsdk. Copiez-le dans un sous-dossier nommé html_template dans votre précédent nouveau dossier.

    -
  4. -
  5. -

    Naviguez maintenant jusqu'au nouveau dossier (toujours dans votre terminal disposant de l'environnement Emscripten), et exécutez la commande suivante :

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

    Les options que nous avons donné sont un peu différentes cette fois :

    - -
      -
    • Nous avons spécifié -o hello2.html, ce qui signifie que le compilateur va générer du code JavaScript "glue" ainsi qu'un .html.
    • -
    • Nous avons également spécifié --shell-file html_template/shell_minimal.html — cela fournit le chemin vers le template HTML que vous souhaitez utiliser pour créer le HTML qui vous permettra d'exécuter l'exemple.
    • -
    -
  6. -
  7. -

    Maintenant, lançons l'exemple. La commande ci-dessus aura généré hello2.html, qui aura à peu près le même contenu que le template avec un peu de code "glue" pour charger le code wasm généré, l'exéuter, etc. Ouvrez-le dans votre navigateur et vous verrez quasiment la même chose qu'avec notre dernier exemple.

    -
  8. -
- -
-

Note : Vous pouvez spécifier, comme sortie, juste le fichier* JavaScript "glue" au lieu de la sortie HTML en specifiant un fichier .js au lieu d'un fichier HTML dans le flag-o . Par exemple: emcc -o hello2.js hello2.c -O3 -s WASM=1. Vous pouevz ensuite votre propre fichier HTML à partir de rien bien que ce soit une approche plus compliquée. Il est généralement plus simple d'utiliser le template HTML fournit.

- -

* Emscripten necessite une grande variété de code Javascript "glue" pour gérer les allocations memoire, les fuites memoires et bien d'autres problèmes.

-
- -

Appeler une fonction personnalisée définie en C

- -

Si vous avez une fonction définie dans votre code C et que vous souhaitez l'appeler de Javascript, vous pouvez le faire en utilisant la fonction Emscripten ccall() et la déclaration EMSCRIPTEN_KEEPALIVE (qui ajoute vos fonctions dans la liste des fonctions exportées) . Voir Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?. Regardons comment cela fonctionne.

- -
    -
  1. -

    Pour démarrer, sauvegardez le code suivante dans un fichier nommé hello3.c dans un nouveau répertoire:

    - -
    #include <stdio.h>
    -#include <emscripten/emscripten.h>
    -
    -int main(int argc, char ** argv) {
    -    printf("Hello World\n");
    -}
    -
    -#ifdef __cplusplus
    -extern "C" {
    -#endif
    -
    -void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) {
    -  printf("MyFunction Called\n");
    -}
    -
    -#ifdef __cplusplus
    -}
    -#endif
    - -

    By default, Emscripten-generated code always just calls the main() function, and other functions are eliminated as dead code. Putting EMSCRIPTEN_KEEPALIVE before a function name stops this from happening. You also need to import the emscripten.h library to use EMSCRIPTEN_KEEPALIVE.

    - -
    -

    Note : We are including the #ifdef blocks so that if you are trying to include this in C++ code, the example will still work. Due to C versus C++ name mangling rules, this would otherwise break, but here we are setting it so that it treats it as an external C function if you are using C++.

    -
    -
  2. -
  3. -

    Now add html_template/shell_minimal.html into this new directory too, just for convenience (you'd obviously put this in a central place in your real dev environment).

    -
  4. -
  5. -

    Now let's run the compilation step again. From inside your latest directory (and while inside your Emscripten compiler environment terminal window), compile your C code with the following command. (Note that we need to compile with NO_EXIT_RUNTIME, which is necessary as otherwise when main() exits the runtime would be shut down - necessary for proper C emulation, e.g., atexits are called - and it wouldn't be valid to call compiled code.)

    - -
    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. -

    If you load the example in your browser again, you'll see the same thing as before!

    -
  8. -
  9. -

    Now we need to run our new myFunction() function from JavaScript. First of all, let's add a {{htmlelement("button")}} as shown below, just above the first opening <script type='text/javascript'> tag.

    - -
    <button class="mybutton">Run myFunction</button>
    -
  10. -
  11. -

    Now add the following code inside the last {{htmlelement("script")}} element (just above the closing </script> tag):

    - -
    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. -
- -

This illustrates how ccall() is used to call the exported function.

- -

Voir aussi

- - diff --git a/files/fr/webassembly/c_to_wasm/index.md b/files/fr/webassembly/c_to_wasm/index.md new file mode 100644 index 0000000000..b55618c1de --- /dev/null +++ b/files/fr/webassembly/c_to_wasm/index.md @@ -0,0 +1,187 @@ +--- +title: Compiler un nouveau module C/C++ en WebAssembly +slug: WebAssembly/C_to_wasm +tags: + - C + - C++ + - Compilation + - Emscripten + - WebAssembly + - wasm +translation_of: WebAssembly/C_to_wasm +--- +
{{WebAssemblySidebar}}
+ +

Quand vous avez écrit un module de code dans un langage comme le C/C++, vous pouvez ensuite le compiler en WebAssembly en utilisant un outil comme Emscripten. Regardons comment cela fonctionne.

+ +

Mise en place de l'environnement Emscripten

+ +

D'abord, mettons en place l'environnement requis pour le développement.

+ +

Prérequis

+ +

Recuperer le SDK de Emscripten en utilisant les instructions suivantes: https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

+ +

Compiler un exemple

+ +

Une fois l'environnement mis en place, regardons comment l'utiliser pour compiler un exemple en C via Emscripten. Il existe un certain nombre d'options disponibles quand on compile avec Emscripten, mais nous allons couvrir seulement les deux principaux scénarios:

+ + + +

Nous verrons les deux par la suite.

+ +

Créer le document HTML et la "glue" JavaScript

+ +

C'est le cas le plus simple que nous allons voir, pour lequel vous utiliserez Emscripten pour générer tout ce dont vous avez besoin pour exécuter votre code en WebAssembly dans le navigateur. 

+ +
    +
  1. D'abord nous avons besoin d'un exemple à compiler. Prenez une copie du simple programme C suivant et sauvez-le dans un fichier nommé hello.c dans un nouveau répertoire de votre disque dur: + +
    #include <stdio.h>
    +
    +int main(int argc, char ** argv) {
    +  printf("Hello World\n");
    +}
    +
  2. +
  3. Maintenant, en utilisant la fenêtre terminal qui vous a servi pour entrer dans l'environnement du compilateur Emscripten, naviguez jusqu'au répertoire dans lequel se trouve votre fichier hello.c et exécutez la commande suivante : +
    emcc hello.c -s WASM=1 -o hello.html
    +
  4. +
+ +

Les options passées avec la commande sont les suivantes :

+ + + +

À ce stade votre dossier source devrait contenir :

+ + + +

Exécuter votre exemple

+ +

Maintenant, tout ce qui vous reste à faire est de charger le fichier hello.html dans un navigateur qui supporte WebAssembly. Il est activé par défaut dans Firefox 52+, Chrome 57+ et dans la derniere version d'Opera (vous pouvez aussi executer du code wasm dans Firefox 47+ en activant le flag javascript.options.wasm dans about:config, ou dans Chrome (51+) et Opera (38+) en allant dans chrome://flags and en activant le flag Experimental WebAssembly.)

+ +

Si tout a fonctionné comme prévu, vous devriez voir la sortie "Hello World" dans la console Emscripten apparaissant dans la page web et dans la console Javascript de votre navigateur. Bravo, vous venez de compiler un programme C en WebAssembly puis d'executer ce programme dans votre navigateur!   

+ +

Utiliser un template HTML personnalisé

+ +

Vous souhaiterez parfois utiliser un template HTML personnalisé. Voyons comment faire :

+ +
    +
  1. +

    Tout d'abord, sauvegarder le code C suivant dans un fichier nommé hello2.c, au sein d'un nouveau dossier (vide) :

    + +
    #include <stdio.h>
    +
    +int main(int argc, char ** argv) {
    +    printf("Hello World\n");
    +
    +}
    +
  2. +
  3. +

    Cherchez le fichier shell_minimal.html dans le dépôt emsdk. Copiez-le dans un sous-dossier nommé html_template dans votre précédent nouveau dossier.

    +
  4. +
  5. +

    Naviguez maintenant jusqu'au nouveau dossier (toujours dans votre terminal disposant de l'environnement Emscripten), et exécutez la commande suivante :

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

    Les options que nous avons donné sont un peu différentes cette fois :

    + +
      +
    • Nous avons spécifié -o hello2.html, ce qui signifie que le compilateur va générer du code JavaScript "glue" ainsi qu'un .html.
    • +
    • Nous avons également spécifié --shell-file html_template/shell_minimal.html — cela fournit le chemin vers le template HTML que vous souhaitez utiliser pour créer le HTML qui vous permettra d'exécuter l'exemple.
    • +
    +
  6. +
  7. +

    Maintenant, lançons l'exemple. La commande ci-dessus aura généré hello2.html, qui aura à peu près le même contenu que le template avec un peu de code "glue" pour charger le code wasm généré, l'exéuter, etc. Ouvrez-le dans votre navigateur et vous verrez quasiment la même chose qu'avec notre dernier exemple.

    +
  8. +
+ +
+

Note : Vous pouvez spécifier, comme sortie, juste le fichier* JavaScript "glue" au lieu de la sortie HTML en specifiant un fichier .js au lieu d'un fichier HTML dans le flag-o . Par exemple: emcc -o hello2.js hello2.c -O3 -s WASM=1. Vous pouevz ensuite votre propre fichier HTML à partir de rien bien que ce soit une approche plus compliquée. Il est généralement plus simple d'utiliser le template HTML fournit.

+ +

* Emscripten necessite une grande variété de code Javascript "glue" pour gérer les allocations memoire, les fuites memoires et bien d'autres problèmes.

+
+ +

Appeler une fonction personnalisée définie en C

+ +

Si vous avez une fonction définie dans votre code C et que vous souhaitez l'appeler de Javascript, vous pouvez le faire en utilisant la fonction Emscripten ccall() et la déclaration EMSCRIPTEN_KEEPALIVE (qui ajoute vos fonctions dans la liste des fonctions exportées) . Voir Why do functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get No functions to process?. Regardons comment cela fonctionne.

+ +
    +
  1. +

    Pour démarrer, sauvegardez le code suivante dans un fichier nommé hello3.c dans un nouveau répertoire:

    + +
    #include <stdio.h>
    +#include <emscripten/emscripten.h>
    +
    +int main(int argc, char ** argv) {
    +    printf("Hello World\n");
    +}
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +void EMSCRIPTEN_KEEPALIVE myFunction(int argc, char ** argv) {
    +  printf("MyFunction Called\n");
    +}
    +
    +#ifdef __cplusplus
    +}
    +#endif
    + +

    By default, Emscripten-generated code always just calls the main() function, and other functions are eliminated as dead code. Putting EMSCRIPTEN_KEEPALIVE before a function name stops this from happening. You also need to import the emscripten.h library to use EMSCRIPTEN_KEEPALIVE.

    + +
    +

    Note : We are including the #ifdef blocks so that if you are trying to include this in C++ code, the example will still work. Due to C versus C++ name mangling rules, this would otherwise break, but here we are setting it so that it treats it as an external C function if you are using C++.

    +
    +
  2. +
  3. +

    Now add html_template/shell_minimal.html into this new directory too, just for convenience (you'd obviously put this in a central place in your real dev environment).

    +
  4. +
  5. +

    Now let's run the compilation step again. From inside your latest directory (and while inside your Emscripten compiler environment terminal window), compile your C code with the following command. (Note that we need to compile with NO_EXIT_RUNTIME, which is necessary as otherwise when main() exits the runtime would be shut down - necessary for proper C emulation, e.g., atexits are called - and it wouldn't be valid to call compiled code.)

    + +
    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. +

    If you load the example in your browser again, you'll see the same thing as before!

    +
  8. +
  9. +

    Now we need to run our new myFunction() function from JavaScript. First of all, let's add a {{htmlelement("button")}} as shown below, just above the first opening <script type='text/javascript'> tag.

    + +
    <button class="mybutton">Run myFunction</button>
    +
  10. +
  11. +

    Now add the following code inside the last {{htmlelement("script")}} element (just above the closing </script> tag):

    + +
    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. +
+ +

This illustrates how ccall() is used to call the exported function.

+ +

Voir aussi

+ + diff --git a/files/fr/webassembly/concepts/index.html b/files/fr/webassembly/concepts/index.html deleted file mode 100644 index 2d770e0eea..0000000000 --- a/files/fr/webassembly/concepts/index.html +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Concepts de WebAssembly -slug: WebAssembly/Concepts -translation_of: WebAssembly/Concepts ---- -
{{WebAssemblySidebar}}
- -

Cet article explique les concepts de fonctionnement de WebAssembly, y compris ses objectifs, les problèmes qu'il résout et la manière dont il s'exécute dans le moteur de rendu du navigateur.

- -

Qu'est-ce que WebAssembly ?

- -

WebAssembly est un nouveau type de code pouvant être exécuté dans les navigateurs modernes et fournissant de nouvelles fonctionnalités ainsi que des gains majeurs en performance. Il n'est pas particulièrement destiné à être écrit à la main, mais il est plutôt conçu pour être une cible de compilation efficace pour les langages source de bas niveau tels C, C ++, Rust, etc.

- -

Cela a d'énormes implications pour la plate-forme web — il fournit un moyen d'exécuter un code écrit dans divers langages sur le web à une vitesse proche du natif, avec des applications clientes exécutées sur le web qui auparavant n'auraient pas pu être réalisées.

- -

De plus, vous ne devez même pas savoir comment créer du code WebAssembly pour en profiter. Les modules WebAssembly peuvent être importés dans une application web (ou Node.js) en exposant les fonctions WebAssembly à utiliser via JavaScript. Les frameworks JavaScript pourraient utiliser WebAssembly pour conférer des avantages massifs de performance et de nouvelles fonctionnalités tout en rendant la fonctionnalité facilement accessible aux développeurs web.

- -

Objectifs de WebAssembly

- -

WebAssembly est en cours de création en tant que standard ouvert au sein du W3C WebAssembly Community Group avec les objectif suivants :

- - - -
-

Note : WebAssembly aura également des usages en dehors du web et des environnements JavaScript (voir Non-web embeddings).

-
- -

Comment WebAssembly s'intègre dans la plateforme web ?

- -

La plateforme web peut s'imaginer comme composée de deux parties :

- - - -

Historiquement, la VM était seulement capable de charger le JavaScript. Cela fonctionnait bien pour nous comme le JavaScript est assez puissant pour résoudre la majeure partie des problèmes que les gens rencontrent sur Internet. Nous nous sommes, cependant, confrontés à des problèmes de performances lors de l'utilisation de JavaScript pour des cas d'utilisations plus avancés comme les jeux 3D, la réalité virtuelle et augmentée, la vision artificielle, l'édition d'image/vidéo, et un nombre de domaines qui demandent des performances natives ( voir Cas d'utilisations WebAssembly pour plus d'informations).

- -

De plus, le coût du téléchargement, du parsing et de la compilation de très grosses applications JavaScript peut être prohibitif. L'utilisation de mobiles ou d'autres plateformes à puissance réduite accentue d'autant plus l'effet de goulet d'étranglement des performances.

- -

WebAssembly est un langage différent de JavaScript, mais n'a pas pour but de le remplacer. Il faut plutôt l'envisager comme complément, travaillant "main dans la main" avec JavaScript, permettant ainsi aux développeurs WEB de prendre avantage des points forts de chacun des deux langages :

- - - -

Avec l'apparition du WebAssembly dans les navigateurs, la machine virtuelle dont nous parlions précédemment charge et exécute deux type de code - JavaScript ET WebAssembly.

- -

Les deux différents type de code peuvent s'appeler si nécessaire — l'API WebAssembly JavaScript enveloppe le code exporté avec des fonctions JavaScript qui peuvent être appelées normalement et le code WebAssembly peut importer et appeler normalement de manière synchrone les fonctions JavaScript. En fait, l'unité de base de code WebAssembly est appelée module et est similaire par de nombreux aspects aux modules ES2015.

- -

Les concepts clefs du WebAssembly 

- -

Il y a différents concepts clefs nécessaires pour comprendre comment fonctionne WebAssembly dans le navigateur. Tous ces concepts se retrouvent totalement dans l'API WebAssembly JavaScript.

- - - -

L'API JavaScript fournit aux développeurs la capacité de créer des modules, de la mémoire, des tables et instances. Pour une instance WebAssembly donnée, le code JavaScript peut appeler - de manière synchrone - ses exports qui sont accessibles comme des fonctions JavaScript normales. De façon arbitraire, toute fonction JavaScript peut aussi être appelée - de manière synchrone - par du code WebAssembly en passant ces fonctions JavaScript comme des imports à une instance WebAssembly.

- -

Vu que JavaScript a un contrôle total sur la façon de charger, compiler et exécuter du code WebAssembly, les développeurs peuvent voir le WebAssembly comme une fonctionnalité JavaScript pour générer efficacement des fonctions très rapides.

- -

Dans le futur, les modules WebAssembly seront chargeables comme des module ES2015 (en utilisant <script type='module'>), ce qui veut dire que JavaScript sera capable de récupérer, compiler et importer un module WebAssembly aussi facilement qu'un module ES2015.

- -

Comment utiliser WebAssembly dans son applicatif ?

- -

Précédemment nous parlions des primitives bas niveau que WebAssembly ajoute à la plateforme Web : un format binaire pour le code et une API pour charger et exécuter ce code binaire. Maintenant, parlons de comment utiliser ces primitives en pratique.

- -

L'écosystème WebAssembly est à un stade embryonnaire ;

- -

D'autres outils verront sans aucun doute le jour à l'avenir. Pour le moment, il y a trois points d'entrée principaux :

- - - -

Parlons de ces options :

- -

Portage depuis le C/C++

- -

L'outil Emscripten est capable de prendre du code source C/C++ et de le compiler dans un module .wasm, de générer le code "glue" JavaScript nécessaire pour charger et exécuter le module et de créer un document HTML capable d'afficher les résultats d'exécution du code.

- -

- -

En résumé, le principe de fonctionnement est le suivant :

- -
    -
  1. D'abord, Emscripten alimente clang+LLVM - une chaîne de compilation open source mature empruntée par exemple à XCode sur OSX - avec le code C/C++.
  2. -
  3. Emscripten transforme ensuite le résultat compilé par clang+LLVM en binaire .wasm.
  4. -
  5. Par lui-même WebAssembly ne peut pour l'instant pas accéder directement au DOM ; Il peut seulement appeler JavaScript avec des données de type primitif entier ou flottant. Ainsi, pour accéder à toute API Web, WebAssembly a besoin d'appeler du JavaScript qui ensuite effectuera l'appel à l'API Web. C'est pourquoi Emscripten crée le document HTML et le code "passe-plat" JavaScript nécessaire pour atteindre cet objectif.
  6. -
- -
-

Note : Il existe des propositions future pour  permettre au WebAssembly d'appeler directement l'API Web.

-
- -

Le code "passe-plat" en JavaScript n'est pas aussi simple que vous pourriez l'imaginer. Pour le moment, Emscripten implémente des librairies C/C++ populaire comme SDL, OpenGL, OpenAL, et une partie de POSIX. Ces bibliothèques sont implémentées sous forme d'API Web et donc chacune d'entre elles requiert un peu de code JavaScript "passe-plat" pour relier WebAssembly à l'API Web sous-jacente.

- -

Ainsi le code "passe-plat" implémente les fonctionnalités de chaque librairie utilisée par le C/C++. Le code "passe-plat" contient aussi la logique pour appeler l'API JavaScript WebAssembly pour chercher, charger et exécuter le fichier .wasm.

- -

Le document HTML généré charge le fichier JavaScript contenant le code "passe-plat" et écrit stdout dans un {{htmlelement("textarea")}}. Si l'application utilise OpenGL, le HTML contient aussi un élément {{htmlelement("canvas")}} qui est utilisé comme cible de rendu. Il est vraiment simple de modifier la sortie Emscripten pour en faire l'application web que vous souhaitez.

- -

Vous pouvez trouver toute la documentation sur Emscripten à l'adresse emscripten.org, et un guide pour exploiter la chaîne de compilation et ainsi compiler votre propre application C/C++ en wasm à l'adresse Compiler du C/C++ en WebAssembly.

- -

Écrire du WebAssembly directement

- -

Voulez vous construire votre propre compilateur ou vos propres outils ou faire une librairie JavaScript qui génère du WebAssembly à la volée ?

- -

De la même manière que les langages assembleur physiques, le format binaire du  WebAssembly a une représentation textuelle. Ces deux formats ont un fonctionnement équivalents. Vous pouvez écrire ou générer ce format à la main et ensuite le convertir au format binaire avec un des nombreux outils de conversion texte vers binaire WebAssembly.

- -

Pour un guide simple sur comment réaliser ceci, regarder notre article Convertir le WebAssembly au format text en wasm.

- -

En résumé

- -

Cet article vous a donné une explication sur ce qu'est WebAssembly, pourquoi il est si utile, comment il s'intègre dans le Web et comment vous pouvez l'utiliser.

- -

Voir aussi

- - diff --git a/files/fr/webassembly/concepts/index.md b/files/fr/webassembly/concepts/index.md new file mode 100644 index 0000000000..2d770e0eea --- /dev/null +++ b/files/fr/webassembly/concepts/index.md @@ -0,0 +1,135 @@ +--- +title: Concepts de WebAssembly +slug: WebAssembly/Concepts +translation_of: WebAssembly/Concepts +--- +
{{WebAssemblySidebar}}
+ +

Cet article explique les concepts de fonctionnement de WebAssembly, y compris ses objectifs, les problèmes qu'il résout et la manière dont il s'exécute dans le moteur de rendu du navigateur.

+ +

Qu'est-ce que WebAssembly ?

+ +

WebAssembly est un nouveau type de code pouvant être exécuté dans les navigateurs modernes et fournissant de nouvelles fonctionnalités ainsi que des gains majeurs en performance. Il n'est pas particulièrement destiné à être écrit à la main, mais il est plutôt conçu pour être une cible de compilation efficace pour les langages source de bas niveau tels C, C ++, Rust, etc.

+ +

Cela a d'énormes implications pour la plate-forme web — il fournit un moyen d'exécuter un code écrit dans divers langages sur le web à une vitesse proche du natif, avec des applications clientes exécutées sur le web qui auparavant n'auraient pas pu être réalisées.

+ +

De plus, vous ne devez même pas savoir comment créer du code WebAssembly pour en profiter. Les modules WebAssembly peuvent être importés dans une application web (ou Node.js) en exposant les fonctions WebAssembly à utiliser via JavaScript. Les frameworks JavaScript pourraient utiliser WebAssembly pour conférer des avantages massifs de performance et de nouvelles fonctionnalités tout en rendant la fonctionnalité facilement accessible aux développeurs web.

+ +

Objectifs de WebAssembly

+ +

WebAssembly est en cours de création en tant que standard ouvert au sein du W3C WebAssembly Community Group avec les objectif suivants :

+ + + +
+

Note : WebAssembly aura également des usages en dehors du web et des environnements JavaScript (voir Non-web embeddings).

+
+ +

Comment WebAssembly s'intègre dans la plateforme web ?

+ +

La plateforme web peut s'imaginer comme composée de deux parties :

+ + + +

Historiquement, la VM était seulement capable de charger le JavaScript. Cela fonctionnait bien pour nous comme le JavaScript est assez puissant pour résoudre la majeure partie des problèmes que les gens rencontrent sur Internet. Nous nous sommes, cependant, confrontés à des problèmes de performances lors de l'utilisation de JavaScript pour des cas d'utilisations plus avancés comme les jeux 3D, la réalité virtuelle et augmentée, la vision artificielle, l'édition d'image/vidéo, et un nombre de domaines qui demandent des performances natives ( voir Cas d'utilisations WebAssembly pour plus d'informations).

+ +

De plus, le coût du téléchargement, du parsing et de la compilation de très grosses applications JavaScript peut être prohibitif. L'utilisation de mobiles ou d'autres plateformes à puissance réduite accentue d'autant plus l'effet de goulet d'étranglement des performances.

+ +

WebAssembly est un langage différent de JavaScript, mais n'a pas pour but de le remplacer. Il faut plutôt l'envisager comme complément, travaillant "main dans la main" avec JavaScript, permettant ainsi aux développeurs WEB de prendre avantage des points forts de chacun des deux langages :

+ + + +

Avec l'apparition du WebAssembly dans les navigateurs, la machine virtuelle dont nous parlions précédemment charge et exécute deux type de code - JavaScript ET WebAssembly.

+ +

Les deux différents type de code peuvent s'appeler si nécessaire — l'API WebAssembly JavaScript enveloppe le code exporté avec des fonctions JavaScript qui peuvent être appelées normalement et le code WebAssembly peut importer et appeler normalement de manière synchrone les fonctions JavaScript. En fait, l'unité de base de code WebAssembly est appelée module et est similaire par de nombreux aspects aux modules ES2015.

+ +

Les concepts clefs du WebAssembly 

+ +

Il y a différents concepts clefs nécessaires pour comprendre comment fonctionne WebAssembly dans le navigateur. Tous ces concepts se retrouvent totalement dans l'API WebAssembly JavaScript.

+ + + +

L'API JavaScript fournit aux développeurs la capacité de créer des modules, de la mémoire, des tables et instances. Pour une instance WebAssembly donnée, le code JavaScript peut appeler - de manière synchrone - ses exports qui sont accessibles comme des fonctions JavaScript normales. De façon arbitraire, toute fonction JavaScript peut aussi être appelée - de manière synchrone - par du code WebAssembly en passant ces fonctions JavaScript comme des imports à une instance WebAssembly.

+ +

Vu que JavaScript a un contrôle total sur la façon de charger, compiler et exécuter du code WebAssembly, les développeurs peuvent voir le WebAssembly comme une fonctionnalité JavaScript pour générer efficacement des fonctions très rapides.

+ +

Dans le futur, les modules WebAssembly seront chargeables comme des module ES2015 (en utilisant <script type='module'>), ce qui veut dire que JavaScript sera capable de récupérer, compiler et importer un module WebAssembly aussi facilement qu'un module ES2015.

+ +

Comment utiliser WebAssembly dans son applicatif ?

+ +

Précédemment nous parlions des primitives bas niveau que WebAssembly ajoute à la plateforme Web : un format binaire pour le code et une API pour charger et exécuter ce code binaire. Maintenant, parlons de comment utiliser ces primitives en pratique.

+ +

L'écosystème WebAssembly est à un stade embryonnaire ;

+ +

D'autres outils verront sans aucun doute le jour à l'avenir. Pour le moment, il y a trois points d'entrée principaux :

+ + + +

Parlons de ces options :

+ +

Portage depuis le C/C++

+ +

L'outil Emscripten est capable de prendre du code source C/C++ et de le compiler dans un module .wasm, de générer le code "glue" JavaScript nécessaire pour charger et exécuter le module et de créer un document HTML capable d'afficher les résultats d'exécution du code.

+ +

+ +

En résumé, le principe de fonctionnement est le suivant :

+ +
    +
  1. D'abord, Emscripten alimente clang+LLVM - une chaîne de compilation open source mature empruntée par exemple à XCode sur OSX - avec le code C/C++.
  2. +
  3. Emscripten transforme ensuite le résultat compilé par clang+LLVM en binaire .wasm.
  4. +
  5. Par lui-même WebAssembly ne peut pour l'instant pas accéder directement au DOM ; Il peut seulement appeler JavaScript avec des données de type primitif entier ou flottant. Ainsi, pour accéder à toute API Web, WebAssembly a besoin d'appeler du JavaScript qui ensuite effectuera l'appel à l'API Web. C'est pourquoi Emscripten crée le document HTML et le code "passe-plat" JavaScript nécessaire pour atteindre cet objectif.
  6. +
+ +
+

Note : Il existe des propositions future pour  permettre au WebAssembly d'appeler directement l'API Web.

+
+ +

Le code "passe-plat" en JavaScript n'est pas aussi simple que vous pourriez l'imaginer. Pour le moment, Emscripten implémente des librairies C/C++ populaire comme SDL, OpenGL, OpenAL, et une partie de POSIX. Ces bibliothèques sont implémentées sous forme d'API Web et donc chacune d'entre elles requiert un peu de code JavaScript "passe-plat" pour relier WebAssembly à l'API Web sous-jacente.

+ +

Ainsi le code "passe-plat" implémente les fonctionnalités de chaque librairie utilisée par le C/C++. Le code "passe-plat" contient aussi la logique pour appeler l'API JavaScript WebAssembly pour chercher, charger et exécuter le fichier .wasm.

+ +

Le document HTML généré charge le fichier JavaScript contenant le code "passe-plat" et écrit stdout dans un {{htmlelement("textarea")}}. Si l'application utilise OpenGL, le HTML contient aussi un élément {{htmlelement("canvas")}} qui est utilisé comme cible de rendu. Il est vraiment simple de modifier la sortie Emscripten pour en faire l'application web que vous souhaitez.

+ +

Vous pouvez trouver toute la documentation sur Emscripten à l'adresse emscripten.org, et un guide pour exploiter la chaîne de compilation et ainsi compiler votre propre application C/C++ en wasm à l'adresse Compiler du C/C++ en WebAssembly.

+ +

Écrire du WebAssembly directement

+ +

Voulez vous construire votre propre compilateur ou vos propres outils ou faire une librairie JavaScript qui génère du WebAssembly à la volée ?

+ +

De la même manière que les langages assembleur physiques, le format binaire du  WebAssembly a une représentation textuelle. Ces deux formats ont un fonctionnement équivalents. Vous pouvez écrire ou générer ce format à la main et ensuite le convertir au format binaire avec un des nombreux outils de conversion texte vers binaire WebAssembly.

+ +

Pour un guide simple sur comment réaliser ceci, regarder notre article Convertir le WebAssembly au format text en wasm.

+ +

En résumé

+ +

Cet article vous a donné une explication sur ce qu'est WebAssembly, pourquoi il est si utile, comment il s'intègre dans le Web et comment vous pouvez l'utiliser.

+ +

Voir aussi

+ + diff --git a/files/fr/webassembly/exported_functions/index.html b/files/fr/webassembly/exported_functions/index.html deleted file mode 100644 index 94bf4140b5..0000000000 --- a/files/fr/webassembly/exported_functions/index.html +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Exported WebAssembly functions -slug: WebAssembly/Exported_functions -translation_of: WebAssembly/Exported_functions ---- -
{{WebAssemblySidebar}}
- -

Les fonctions WebAssembly exportées sont la représentation des fonctions WebAssembly dans JavaScript. Cet article décrit un plus en détail à quoi elle correspondent...

- -

Exportée... quoi?

- -

Les fonctions WebAssembly exportées sont simplement des emballages (wrappers) Javascript autour de fonction WebAssembly afin de les représenter dans un contexte Javascript. Lorsqu'elles sont appelées, une procédure en arrière plan est engagée afin d'obtenir une conversion des types compatible avec WebAssembly (Par exemple convertir numbers en Int32), les arguments sont transmis à la fonction au sein du module wasm, la fonction est invoquée, et enfin le résultat est à nouveau convertit et retourner à Javascript.

- -

Vous pouvez exporter les fonctions WebAssembly de deux manières:

- - - -

Dans les deux cas, vous obtenez le même genre de wrapper pour la fonction sous jacente. Du point de vue de JavaScript, une fonction wasm est une fonction JavaScript— A la différence prés qu'elles sont encapsulées par l'instance d'une fonction exportée wasm et qu'il y a un nombre limité de façon d'y accéder.

- -

Un exemple

- -

Regardons un exemple pour mettre les choses au clair (tu peux le trouver sur GitHub sur table-set.html; à voir également en live , et check la representation textuelle wasm):

- -
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
-
-WebAssembly.instantiateStreaming(fetch('table.wasm'))
-.then(obj => {
-  var tbl = obj.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)());
-});
- -

Dans cet exemple, nous créons une table (otherTable) à partir de JavaScript en utilisant le constructeur {{jsxref("WebAssembly.Table")}}, puis nous chargeons table.wasm dans notre page en utilisant la méthode {{jsxref("WebAssembly.instantiateStreaming()")}}.

- -

Nous pouvons ensuite accéder aux fonctions exportées à partir du module, récupérer les références de chaque fonction via  tbl.get() et logguer le résultat de chacune d'elles dans la console. Enfin, nous utilisons set() avec la table otherTable afin de lui fournir les references aux mêmes functions que la table tbl.

- -

Pour vérifier que cela à fonctionné correctement, nous récupérons les références de la table otherTable et imprimons également les résultats dans la console, et les résultats sont identiques aux précédents.

- -

Des fonctions à part entière

- -

Dans l'exemple précédent, la valeur de retour de chaque appel à Table.prototype.get() est une fonction WebAssembly exportée — exactement ce dont nous avons parlé jusqu'à maintenant.

- -

Il vaut la peine d'être noté que ceux sont des fonctions JavaScript à part entière, en plus d'être un emballage à des fonctions WebAssembly. Si vous chargez l'exemple ci-dessus dans un navigateur compatible avec WebAssembly, et excécutez les lignes suivantes dans votre console:

- -
var testFunc = otherTable.get(0);
-typeof testFunc;
- -

Vous obtiendrez le résultat function en valeur de retour. Cette fonction peut effectuer tout ce qu'une fonction Javascript classique peut effectuer — call(), bind(), etc. testFunc.toString() retourne un résultat intéressant:

- -
function 0() {
-    [native code]
-}
- -

Cela vous donne une idée plus précise de la nature de l'emballage (wrapper-type).

- -

Some other particulars to be aware of with exported WebAssembly functions:

- - diff --git a/files/fr/webassembly/exported_functions/index.md b/files/fr/webassembly/exported_functions/index.md new file mode 100644 index 0000000000..94bf4140b5 --- /dev/null +++ b/files/fr/webassembly/exported_functions/index.md @@ -0,0 +1,69 @@ +--- +title: Exported WebAssembly functions +slug: WebAssembly/Exported_functions +translation_of: WebAssembly/Exported_functions +--- +
{{WebAssemblySidebar}}
+ +

Les fonctions WebAssembly exportées sont la représentation des fonctions WebAssembly dans JavaScript. Cet article décrit un plus en détail à quoi elle correspondent...

+ +

Exportée... quoi?

+ +

Les fonctions WebAssembly exportées sont simplement des emballages (wrappers) Javascript autour de fonction WebAssembly afin de les représenter dans un contexte Javascript. Lorsqu'elles sont appelées, une procédure en arrière plan est engagée afin d'obtenir une conversion des types compatible avec WebAssembly (Par exemple convertir numbers en Int32), les arguments sont transmis à la fonction au sein du module wasm, la fonction est invoquée, et enfin le résultat est à nouveau convertit et retourner à Javascript.

+ +

Vous pouvez exporter les fonctions WebAssembly de deux manières:

+ + + +

Dans les deux cas, vous obtenez le même genre de wrapper pour la fonction sous jacente. Du point de vue de JavaScript, une fonction wasm est une fonction JavaScript— A la différence prés qu'elles sont encapsulées par l'instance d'une fonction exportée wasm et qu'il y a un nombre limité de façon d'y accéder.

+ +

Un exemple

+ +

Regardons un exemple pour mettre les choses au clair (tu peux le trouver sur GitHub sur table-set.html; à voir également en live , et check la representation textuelle wasm):

+ +
var otherTable = new WebAssembly.Table({ element: "anyfunc", initial: 2 });
+
+WebAssembly.instantiateStreaming(fetch('table.wasm'))
+.then(obj => {
+  var tbl = obj.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)());
+});
+ +

Dans cet exemple, nous créons une table (otherTable) à partir de JavaScript en utilisant le constructeur {{jsxref("WebAssembly.Table")}}, puis nous chargeons table.wasm dans notre page en utilisant la méthode {{jsxref("WebAssembly.instantiateStreaming()")}}.

+ +

Nous pouvons ensuite accéder aux fonctions exportées à partir du module, récupérer les références de chaque fonction via  tbl.get() et logguer le résultat de chacune d'elles dans la console. Enfin, nous utilisons set() avec la table otherTable afin de lui fournir les references aux mêmes functions que la table tbl.

+ +

Pour vérifier que cela à fonctionné correctement, nous récupérons les références de la table otherTable et imprimons également les résultats dans la console, et les résultats sont identiques aux précédents.

+ +

Des fonctions à part entière

+ +

Dans l'exemple précédent, la valeur de retour de chaque appel à Table.prototype.get() est une fonction WebAssembly exportée — exactement ce dont nous avons parlé jusqu'à maintenant.

+ +

Il vaut la peine d'être noté que ceux sont des fonctions JavaScript à part entière, en plus d'être un emballage à des fonctions WebAssembly. Si vous chargez l'exemple ci-dessus dans un navigateur compatible avec WebAssembly, et excécutez les lignes suivantes dans votre console:

+ +
var testFunc = otherTable.get(0);
+typeof testFunc;
+ +

Vous obtiendrez le résultat function en valeur de retour. Cette fonction peut effectuer tout ce qu'une fonction Javascript classique peut effectuer — call(), bind(), etc. testFunc.toString() retourne un résultat intéressant:

+ +
function 0() {
+    [native code]
+}
+ +

Cela vous donne une idée plus précise de la nature de l'emballage (wrapper-type).

+ +

Some other particulars to be aware of with exported WebAssembly functions:

+ + diff --git a/files/fr/webassembly/index.html b/files/fr/webassembly/index.html deleted file mode 100644 index 02b351d7b9..0000000000 --- a/files/fr/webassembly/index.html +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: WebAssembly -slug: WebAssembly -tags: - - Landing - - WebAssembly - - wasm -translation_of: WebAssembly ---- -
{{WebAssemblySidebar}}{{SeeCompatTable}}
- -

WebAssembly est un nouveau type de code qui peut être exécuté dans un navigateur web moderne. C'est un langage bas niveau, semblable à l'assembleur permettant d'atteindre des performances proches des applications natives (par exemple écrites en C/C++) tout en fonctionnant sur le Web. WebAssembly est conçu pour fonctionner en lien avec JavaScript.

- -

En résumé

- -

WebAssembly représente une avancée fondamentale de la plateforme web. Il permet d'exécuter du code (éventuellement écrit depuis différents langages) sur le Web avec des performances similaires aux applications natives.

- -

WebAssembly est conçu pour être utilisé de pair avec JavaScript. Grâce à l'API JavaScript WebAssembly, on peut charger des modules WebAssembly au sein d'une application JavaScript et partager des fonctionnalités entre les deux. Cela permet de tirer parti des performances de WebAssembly et de la flexibilité de JavaScript, même si on ne sait pas écrire du code WebAssembly.

- -

WebAssembly est conçu comme un standard web par le groupe communautaire du W3C pour WebAssembly auquel participe les différents éditeurs de navigateur.

- -

Guides

- -
-
Les concepts de WebAssembly
-
Découvrez les concepts clés de WebAssembly : ce que c'est, son utilité, l'intégration dans le Web et comment l'utiliser.
-
Compiler du code C/C++ en WebAssembly
-
Du code écrit en C/C++ peut être compilé en WebAssembly grâce à des outils tels que Emscripten. Nous voyons ici comment cela fonctionne.
-
Charger et exécuter du code WebAssembly
-
Dans cet article, on aborde comment récupérer, compiler et instancier en associant l'API WebAssembly JavaScript avec les API Fetch ou XHR.
-
Mettre en cache des modules WebAssembly compilés
-
La mise en cache de grands modules WebAssembly côté client permet d'améliorer les performances au démarrage. Dans cet article, on voit comment utiliser IndexedDB pour cela.
-
Utiliser l'API JavaScript de WebAssembly
-
Une fois le module WebAssembly chargé, on souhaitera l'utiliser… Dans cet article, on verra comment utiliser WebAssembly grâce à l'API JavaScript associée.
-
Les fonctions WebAssembly exportées
-
Les fonctions WebAssembly exportées sont les représentations JavaScript des fonctions WebAssembly qui permettent d'utiliser du code WebAssembly depuis un script JavaScript. Cet article décrit leur fonctionnement.
-
Comprendre le format texte WebAssembly
-
Cet article explique la composition du format texte de WebAssembly. Il s'agit d'une représentation bas-niveau du module .wasm tel que montré dans les outils de développement du navigateur.
-
Convertir un fichier texte WebAssembly en wasm
-
Cet article détaille comment convertir un module WebAssembly rédigé dans un format texte en un fichier binaire .wasm.
-
- -

Référence de l'API JavaScript

- -
-
{{jsxref("Objets_globaux/WebAssembly", "WebAssembly")}}
-
Cet objet représente l'espace de nom encapsulant les fonctionnalités relatives à WebAssembly.
-
{{jsxref("Objets_globaux/WebAssembly/Module", "WebAssembly.Module")}}
-
Un objet WebAssembly.Module contient du code WebAssembly, sans état, qui a déjà été compilé par le navigateur et qui peut être partagé dans les web workers, mis en cache dans IndexedDB et instancié à plusieurs reprises.
-
{{jsxref("Objets_globaux/WebAssembly/Instance", "WebAssembly.Instance")}}
-
Un objet WebAssembly.Instance est une instance exécutable (disposant d'un état) d'un Module. Les objets Instance contiennent toutes les fonctions WebAssembly exportées qui permettent d'utiliser du code WebAssembly via du code JavaScript.
-
{{jsxref("Objets_globaux/WebAssembly/instantiate", "WebAssembly.instantiate()")}}
-
La fonction WebAssembly.instantiate() représente l'API principale pour compiler et instancier le code WebAssembly. Cette méthode renvoie un Module ainsi que sa première Instance.
-
{{jsxref("Objets_globaux/WebAssembly/Memory", "WebAssembly.Memory()")}}
-
Un objet WebAssembly.Memory est un tableau {{jsxref("Objets_globaux/ArrayBuffer", "ArrayBuffer")}} redimensionnable qui contient les octets de mémoire brute auxquels on peut accéder via une Instance.
-
{{jsxref("Objets_globaux/WebAssembly/Table", "WebAssembly.Table()")}}
-
Un objet WebAssembly.Table est un tableau typé contenant des valeurs opaques et qui peut être redimensionné. On peut accéder aux valeurs via un objet Instance.
-
{{jsxref("WebAssembly.CompileError()")}}
-
Crée un nouvel objet WebAssembly CompileError.
-
{{jsxref("WebAssembly.LinkError()")}}
-
Crée un nouvel objet WebAssembly LinkError.
-
{{jsxref("WebAssembly.RuntimeError()")}}
-
Crée un nouvel objet WebAssembly RuntimeError.
-
- - -

Exemples

- - - -

Spécifications

- - - - - - - - - - - - - - - - -
SpécificationÉtatCommentaires
{{SpecName('WebAssembly JS')}}{{Spec2('WebAssembly JS')}}Brouillon de définition initiale pour l'API JavaScript.
- -

Compatibilité des navigateurs

- -

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

- -

Voir aussi

- - diff --git a/files/fr/webassembly/index.md b/files/fr/webassembly/index.md new file mode 100644 index 0000000000..02b351d7b9 --- /dev/null +++ b/files/fr/webassembly/index.md @@ -0,0 +1,104 @@ +--- +title: WebAssembly +slug: WebAssembly +tags: + - Landing + - WebAssembly + - wasm +translation_of: WebAssembly +--- +
{{WebAssemblySidebar}}{{SeeCompatTable}}
+ +

WebAssembly est un nouveau type de code qui peut être exécuté dans un navigateur web moderne. C'est un langage bas niveau, semblable à l'assembleur permettant d'atteindre des performances proches des applications natives (par exemple écrites en C/C++) tout en fonctionnant sur le Web. WebAssembly est conçu pour fonctionner en lien avec JavaScript.

+ +

En résumé

+ +

WebAssembly représente une avancée fondamentale de la plateforme web. Il permet d'exécuter du code (éventuellement écrit depuis différents langages) sur le Web avec des performances similaires aux applications natives.

+ +

WebAssembly est conçu pour être utilisé de pair avec JavaScript. Grâce à l'API JavaScript WebAssembly, on peut charger des modules WebAssembly au sein d'une application JavaScript et partager des fonctionnalités entre les deux. Cela permet de tirer parti des performances de WebAssembly et de la flexibilité de JavaScript, même si on ne sait pas écrire du code WebAssembly.

+ +

WebAssembly est conçu comme un standard web par le groupe communautaire du W3C pour WebAssembly auquel participe les différents éditeurs de navigateur.

+ +

Guides

+ +
+
Les concepts de WebAssembly
+
Découvrez les concepts clés de WebAssembly : ce que c'est, son utilité, l'intégration dans le Web et comment l'utiliser.
+
Compiler du code C/C++ en WebAssembly
+
Du code écrit en C/C++ peut être compilé en WebAssembly grâce à des outils tels que Emscripten. Nous voyons ici comment cela fonctionne.
+
Charger et exécuter du code WebAssembly
+
Dans cet article, on aborde comment récupérer, compiler et instancier en associant l'API WebAssembly JavaScript avec les API Fetch ou XHR.
+
Mettre en cache des modules WebAssembly compilés
+
La mise en cache de grands modules WebAssembly côté client permet d'améliorer les performances au démarrage. Dans cet article, on voit comment utiliser IndexedDB pour cela.
+
Utiliser l'API JavaScript de WebAssembly
+
Une fois le module WebAssembly chargé, on souhaitera l'utiliser… Dans cet article, on verra comment utiliser WebAssembly grâce à l'API JavaScript associée.
+
Les fonctions WebAssembly exportées
+
Les fonctions WebAssembly exportées sont les représentations JavaScript des fonctions WebAssembly qui permettent d'utiliser du code WebAssembly depuis un script JavaScript. Cet article décrit leur fonctionnement.
+
Comprendre le format texte WebAssembly
+
Cet article explique la composition du format texte de WebAssembly. Il s'agit d'une représentation bas-niveau du module .wasm tel que montré dans les outils de développement du navigateur.
+
Convertir un fichier texte WebAssembly en wasm
+
Cet article détaille comment convertir un module WebAssembly rédigé dans un format texte en un fichier binaire .wasm.
+
+ +

Référence de l'API JavaScript

+ +
+
{{jsxref("Objets_globaux/WebAssembly", "WebAssembly")}}
+
Cet objet représente l'espace de nom encapsulant les fonctionnalités relatives à WebAssembly.
+
{{jsxref("Objets_globaux/WebAssembly/Module", "WebAssembly.Module")}}
+
Un objet WebAssembly.Module contient du code WebAssembly, sans état, qui a déjà été compilé par le navigateur et qui peut être partagé dans les web workers, mis en cache dans IndexedDB et instancié à plusieurs reprises.
+
{{jsxref("Objets_globaux/WebAssembly/Instance", "WebAssembly.Instance")}}
+
Un objet WebAssembly.Instance est une instance exécutable (disposant d'un état) d'un Module. Les objets Instance contiennent toutes les fonctions WebAssembly exportées qui permettent d'utiliser du code WebAssembly via du code JavaScript.
+
{{jsxref("Objets_globaux/WebAssembly/instantiate", "WebAssembly.instantiate()")}}
+
La fonction WebAssembly.instantiate() représente l'API principale pour compiler et instancier le code WebAssembly. Cette méthode renvoie un Module ainsi que sa première Instance.
+
{{jsxref("Objets_globaux/WebAssembly/Memory", "WebAssembly.Memory()")}}
+
Un objet WebAssembly.Memory est un tableau {{jsxref("Objets_globaux/ArrayBuffer", "ArrayBuffer")}} redimensionnable qui contient les octets de mémoire brute auxquels on peut accéder via une Instance.
+
{{jsxref("Objets_globaux/WebAssembly/Table", "WebAssembly.Table()")}}
+
Un objet WebAssembly.Table est un tableau typé contenant des valeurs opaques et qui peut être redimensionné. On peut accéder aux valeurs via un objet Instance.
+
{{jsxref("WebAssembly.CompileError()")}}
+
Crée un nouvel objet WebAssembly CompileError.
+
{{jsxref("WebAssembly.LinkError()")}}
+
Crée un nouvel objet WebAssembly LinkError.
+
{{jsxref("WebAssembly.RuntimeError()")}}
+
Crée un nouvel objet WebAssembly RuntimeError.
+
+ + +

Exemples

+ + + +

Spécifications

+ + + + + + + + + + + + + + + + +
SpécificationÉtatCommentaires
{{SpecName('WebAssembly JS')}}{{Spec2('WebAssembly JS')}}Brouillon de définition initiale pour l'API JavaScript.
+ +

Compatibilité des navigateurs

+ +

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

+ +

Voir aussi

+ + diff --git a/files/fr/webassembly/loading_and_running/index.html b/files/fr/webassembly/loading_and_running/index.html deleted file mode 100644 index 2fd18151de..0000000000 --- a/files/fr/webassembly/loading_and_running/index.html +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Loading and running WebAssembly code -slug: WebAssembly/Loading_and_running -translation_of: WebAssembly/Loading_and_running ---- -
{{WebAssemblySidebar}}
- -
Pour utiliser webassembly au sein de javascript, votre module doit être placé en mémoire. La mise en mémoire du module précède les étapes de compiliation et d'instantiation. Cet article fournit une référence pour les différents méchanismes qui permettent de récupérer le bytecode webassembly, ainsi que des informations sur la manière de le compiler, l'instancier, et l'exécuter.  
- -

Quelles sont les différentes options?

- -

Webassembly n'est pas encore intégré à <script type='module'>  ou ES2015 import, autrement dit le navigateur ne peut pas récuperer les modules à l'aide de déclaration d'imports. 

- -

Les anciennes méthodes {{jsxref("WebAssembly.compile")}}/{{jsxref("WebAssembly.instantiate")}} requièrent la création d'un {{domxref("ArrayBuffer")}} contenant le binaire de votre module webassembly sous forme d'octet brut, pour ensuite effectuer sa compilation et son instantiation. Cette approche est simialire à new Function(string), à la différence que dans notre cas, nous substituons une chaine de charactères par une chaine de bytes (le code source webassembly). 

- -

Les nouvelles méthodes {{jsxref("WebAssembly.compileStreaming")}}/{{jsxref("WebAssembly.instantiateStreaming")}} sont beaucoup plus efficace — elles s'applique directement sur le flux d'octets récupérer par le réseau, et ne nécessite pas l'utilisaton d'un {{domxref("ArrayBuffer")}}.

- -

Quelle est donc la démarche à suivre pour obtenir cet array buffer et le compiler ? La réponse dans les sections suivantes.

- -

En utilisant Fetch

- -

Fetch  est une API qui facilite la récupération de ressources sur le réseau.

- -

La façon la plus rapide et la plus efficace de récupérer un module wasm (webassembly) est d'utiliser la méthode {{jsxref("WebAssembly.instantiateStreaming()")}}, qui accepte comme premier argument un appel de fonction fetch(), et s'occupe de récupérer, compiler, et instancier le module en une seule et même étape, en accedant directement au flux de code binaire provenant du serveur:

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

L'ancienne méthode {{jsxref("WebAssembly.instantiate()")}} n'accède pas directement au flux de données. Elle nécessite une étape supplémentaire afin de convertir le byte code récupéré en {{domxref("ArrayBuffer")}}. Elle s'implemente de cette façon:

- -
fetch('module.wasm').then(response =>
-  response.arrayBuffer()
-).then(bytes =>
-  WebAssembly.instantiate(bytes, importObject)
-).then(results => {
-  // Do something with the results!
-});
- - - -

Aside on instantiate() overloads

- -

The {{jsxref("WebAssembly.instantiate()")}} function has two overload forms — the one shown above takes the byte code to compile as an argument and returns a promise that resolves to an object containing both the compiled module object, and an instantiated instance of it. The object looks like this:

- -
{
-  module : Module // The newly compiled WebAssembly.Module object,
-  instance : Instance // A new WebAssembly.Instance of the module object
-}
- -
-

Note : En règle générale, on ne s'intéresse qu'à l'instance, mais il peut être utile de préserver le module afin de le mettre ultérieurement en cache, de le partager avec un autre worker ou window via postMessage(), ou tout simplement pour créer d'autres instances.

-
- -
-

Note : Un chargement supplémentaire du module nécessite un object  de type {{jsxref("WebAssembly.Module")}} comme argument, et retourne une promesse contenant directement un objet de type instance comme résultat. Voir Second overload example.

-
- -

Mise en marche du code webassembly

- -

Une fois l'instance webassembly disponible au sein de Javascript, vous pouvez commencer à utiliser les fonctionnalités exportées, accessibles via la propriété {{jsxref("WebAssembly.Instance/exports", "WebAssembly.Instance.exports")}}. Votre code peut s'organsier de la manière suivante:

- -
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)());
-})
- -
-

Note : Pour plus d'informations sur la façon dont fonctionne l'exportation au sein d'un module webassembly, lisez Using the WebAssembly JavaScript API, et Understanding WebAssembly text format.

-
- -

En utilisant XMLHttpRequest

- -

XMLHttpRequest est plus ancien que Fetch, mais peut toujours être utiliser afin récupérer un array buffer. En supposant que notre module se nome simple.wasm:

- -
    -
  1. Créer une nouvel instance {{domxref("XMLHttpRequest()")}}, afin d'utiliser la méthode {{domxref("XMLHttpRequest.open","open()")}} nécessaire pour ouvrir une requête. Paramètrer la requête avec une méthode GET, et y déclarer le chemin du fichier que nous souhaiter récupérer.
  2. -
  3. L'étape essentielle est içi de définir la réponse comme une réponse de type 'arraybuffer' en utilisant  la propriété {{domxref("XMLHttpRequest.responseType","responseType")}}.
  4. -
  5. Ensuite, la requête est envoyée à l'aide de la méthode {{domxref("XMLHttpRequest.send()")}}.
  6. -
  7. Enfin l'event handler {{domxref("XMLHttpRequest.onload", "onload")}} se charge d'invoquer une fonction lorsque la réponse a terminé de se télécharger — au sein de cette fonction, la propriété {{domxref("XMLHttpRequest.response", "response")}} nous donne accès à un array buffer. Celui ci est fournit à notre méthode {{jsxref("WebAssembly.instantiate()")}} d'un manière similaire à ce qui est fait avec la méthode Fetch().
  8. -
- -

Le code final est le suivant:

- -
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();
-  });
-};
- -
-

Note : Vous pouvez retrouver un autre exemple sur xhr-wasm.html.

-
diff --git a/files/fr/webassembly/loading_and_running/index.md b/files/fr/webassembly/loading_and_running/index.md new file mode 100644 index 0000000000..2fd18151de --- /dev/null +++ b/files/fr/webassembly/loading_and_running/index.md @@ -0,0 +1,108 @@ +--- +title: Loading and running WebAssembly code +slug: WebAssembly/Loading_and_running +translation_of: WebAssembly/Loading_and_running +--- +
{{WebAssemblySidebar}}
+ +
Pour utiliser webassembly au sein de javascript, votre module doit être placé en mémoire. La mise en mémoire du module précède les étapes de compiliation et d'instantiation. Cet article fournit une référence pour les différents méchanismes qui permettent de récupérer le bytecode webassembly, ainsi que des informations sur la manière de le compiler, l'instancier, et l'exécuter.  
+ +

Quelles sont les différentes options?

+ +

Webassembly n'est pas encore intégré à <script type='module'>  ou ES2015 import, autrement dit le navigateur ne peut pas récuperer les modules à l'aide de déclaration d'imports. 

+ +

Les anciennes méthodes {{jsxref("WebAssembly.compile")}}/{{jsxref("WebAssembly.instantiate")}} requièrent la création d'un {{domxref("ArrayBuffer")}} contenant le binaire de votre module webassembly sous forme d'octet brut, pour ensuite effectuer sa compilation et son instantiation. Cette approche est simialire à new Function(string), à la différence que dans notre cas, nous substituons une chaine de charactères par une chaine de bytes (le code source webassembly). 

+ +

Les nouvelles méthodes {{jsxref("WebAssembly.compileStreaming")}}/{{jsxref("WebAssembly.instantiateStreaming")}} sont beaucoup plus efficace — elles s'applique directement sur le flux d'octets récupérer par le réseau, et ne nécessite pas l'utilisaton d'un {{domxref("ArrayBuffer")}}.

+ +

Quelle est donc la démarche à suivre pour obtenir cet array buffer et le compiler ? La réponse dans les sections suivantes.

+ +

En utilisant Fetch

+ +

Fetch  est une API qui facilite la récupération de ressources sur le réseau.

+ +

La façon la plus rapide et la plus efficace de récupérer un module wasm (webassembly) est d'utiliser la méthode {{jsxref("WebAssembly.instantiateStreaming()")}}, qui accepte comme premier argument un appel de fonction fetch(), et s'occupe de récupérer, compiler, et instancier le module en une seule et même étape, en accedant directement au flux de code binaire provenant du serveur:

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

L'ancienne méthode {{jsxref("WebAssembly.instantiate()")}} n'accède pas directement au flux de données. Elle nécessite une étape supplémentaire afin de convertir le byte code récupéré en {{domxref("ArrayBuffer")}}. Elle s'implemente de cette façon:

+ +
fetch('module.wasm').then(response =>
+  response.arrayBuffer()
+).then(bytes =>
+  WebAssembly.instantiate(bytes, importObject)
+).then(results => {
+  // Do something with the results!
+});
+ + + +

Aside on instantiate() overloads

+ +

The {{jsxref("WebAssembly.instantiate()")}} function has two overload forms — the one shown above takes the byte code to compile as an argument and returns a promise that resolves to an object containing both the compiled module object, and an instantiated instance of it. The object looks like this:

+ +
{
+  module : Module // The newly compiled WebAssembly.Module object,
+  instance : Instance // A new WebAssembly.Instance of the module object
+}
+ +
+

Note : En règle générale, on ne s'intéresse qu'à l'instance, mais il peut être utile de préserver le module afin de le mettre ultérieurement en cache, de le partager avec un autre worker ou window via postMessage(), ou tout simplement pour créer d'autres instances.

+
+ +
+

Note : Un chargement supplémentaire du module nécessite un object  de type {{jsxref("WebAssembly.Module")}} comme argument, et retourne une promesse contenant directement un objet de type instance comme résultat. Voir Second overload example.

+
+ +

Mise en marche du code webassembly

+ +

Une fois l'instance webassembly disponible au sein de Javascript, vous pouvez commencer à utiliser les fonctionnalités exportées, accessibles via la propriété {{jsxref("WebAssembly.Instance/exports", "WebAssembly.Instance.exports")}}. Votre code peut s'organsier de la manière suivante:

+ +
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)());
+})
+ +
+

Note : Pour plus d'informations sur la façon dont fonctionne l'exportation au sein d'un module webassembly, lisez Using the WebAssembly JavaScript API, et Understanding WebAssembly text format.

+
+ +

En utilisant XMLHttpRequest

+ +

XMLHttpRequest est plus ancien que Fetch, mais peut toujours être utiliser afin récupérer un array buffer. En supposant que notre module se nome simple.wasm:

+ +
    +
  1. Créer une nouvel instance {{domxref("XMLHttpRequest()")}}, afin d'utiliser la méthode {{domxref("XMLHttpRequest.open","open()")}} nécessaire pour ouvrir une requête. Paramètrer la requête avec une méthode GET, et y déclarer le chemin du fichier que nous souhaiter récupérer.
  2. +
  3. L'étape essentielle est içi de définir la réponse comme une réponse de type 'arraybuffer' en utilisant  la propriété {{domxref("XMLHttpRequest.responseType","responseType")}}.
  4. +
  5. Ensuite, la requête est envoyée à l'aide de la méthode {{domxref("XMLHttpRequest.send()")}}.
  6. +
  7. Enfin l'event handler {{domxref("XMLHttpRequest.onload", "onload")}} se charge d'invoquer une fonction lorsque la réponse a terminé de se télécharger — au sein de cette fonction, la propriété {{domxref("XMLHttpRequest.response", "response")}} nous donne accès à un array buffer. Celui ci est fournit à notre méthode {{jsxref("WebAssembly.instantiate()")}} d'un manière similaire à ce qui est fait avec la méthode Fetch().
  8. +
+ +

Le code final est le suivant:

+ +
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();
+  });
+};
+ +
+

Note : Vous pouvez retrouver un autre exemple sur xhr-wasm.html.

+
diff --git a/files/fr/webassembly/using_the_javascript_api/index.html b/files/fr/webassembly/using_the_javascript_api/index.html deleted file mode 100644 index 7e200a4247..0000000000 --- a/files/fr/webassembly/using_the_javascript_api/index.html +++ /dev/null @@ -1,292 +0,0 @@ ---- -title: Utiliser l'API JavaScript de WebAssembly -slug: WebAssembly/Using_the_JavaScript_API -translation_of: WebAssembly/Using_the_JavaScript_API ---- -
{{WebAssemblySidebar}}
- -

Si vous avez déjà compilé un module depuis un autre langage en utilisant des outils comme Emscripten, ou chargé et éxecuté vous-même le code, l'étape suivante est d'en apprendre plus à propos des autres fonctionnalités de l'API JavaScript WebAssembly. Cet article vous enseigne ce que vous aurez besoin de connaître.

- -
-

Note : Si vous n'êtes pas familier avec les concepts de base mentionnés dans cet article et vous avez besoin de plus d'explication, lisez  d'abord WebAssembly concepts.

-
- -

Quelques exemples simples

- -

Parcourons quelques exemples illustrant l'utilisation de l'API Webassembly Javascript, et en particulier la manière dont elle peut être utilisé pour charger un module wasm au sein d'une page web. 

- -
-

Note : Vous pouvez trouver des exemples de code dans notre repo GitHub  webassembly-examples.

-
- -

Préparation

- -
    -
  1. Premièrement nous avons besoin d'un module wasm ! Récupérez notre fichier simple.wasm et sauvegardez une copie dans un nouveau document sur votre machine locale.
  2. -
  3. Ensuite, assurez-vous d'utiliser un navigateur supportant WebAssembly. Firefox 52+ et Chrome 57+ supportent WebAssembly par défaut.
  4. -
  5. Pour poursuivre, créez un simple fichier nommé index.html dans le même dossier que votre fichier wasm (vous pouvez utiliser notre template simple si vous n'en avez pas de facilement accessible).
  6. -
  7. Maintenant, pour nous aider à comprendre ce qui se passe ici, regardons la représentation textuelle de notre module wasm  (que nous rencontrons aussi dans Converting WebAssembly format to wasm): -
    (module
    -  (func $i (import "imports" "imported_func") (param i32))
    -  (func (export "exported_func")
    -    i32.const 42
    -    call $i))
    -
  8. -
  9. À la deuxième ligne, vous pouvez constater l'import d'un namespace à deux niveaux  — la fonction interne $i est importée depuis  imports.imported_func.  Dans notre JavaScript, notre namespace doit reprendre ce format à deux niveaux lors de l'écriture de l'objet à importer dans le module wasm. Pour ce faire, créez un élément <script></script> dans votre fichier HTML, puis ajoutez le code suivant: -
    var importObject = {
    -  imports: {
    -      imported_func: function(arg) {
    -        console.log(arg);
    -      }
    -    }
    -  };
    -
  10. -
- -

Streaming de notre module webassembly

- -

Il est dorénavant possible dans Firefox 58 de compiler et instancier les modules Webassembly directement à partir des ressources initiales. Il est nécessaire dans ce cas d'utiliser les méthodes {{jsxref("WebAssembly.compileStreaming()")}} et {{jsxref("WebAssembly.instantiateStreaming()")}}. Ces méthodes en streaming sont plus facile d'utilisation que leurs contreparties synchrones, car elles traduisent directement le bytecode en instances de type Module/Instance, sans nécessiter la manipulation d'une réponse intermédiaire {{domxref("Response")}} en un {{domxref("ArrayBuffer")}}.

- -

Cet exemple (voir notre démo sur GitHub instantiate-streaming.html, et également view it live) montre comment utiliser  instantiateStreaming() pour récupérer un module wasm, le compiler, l'instancier afin d'avoir accès aux fonctions exportées qu'il contient et d'y importer des fonctions Javascript, le tout en une seule et même étape.  

- -

Ajoutez le code suivant à votre script, en dessous du premier bloc:

- -
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
-.then(obj => obj.instance.exports.exported_func());
- -

Le résultat net de l'ensemble du code est que l'appel à exported_func, notre fonction exportée Webassembly, entraîne à son tour l'appel à imported_func notre fonction importée Javscript, qui logue la valeur 42 fournie à l'instance WebAssembly dans la console. Si vous sauvegardez l'exemple et chargez le code dans un navigateur qui supporte WebAssembly, vous pourrez le voir en action.

- -

Note: Cet exemple interminable et tarabiscoté semble aboutir à un résultat de faible importance, il permet néanmoins d'illustrer les possibilités offertes par l'utilisation conjointe d'un code WebAssembly et d'un code Javscript dans une application web. Comme il est précisé ailleurs, l'objectif de WebAssembly n'est pas de remplacer Javascript; à vrai dire les deux sont conçus pour fonctionner de concert, chacun tirant parti des forces de l'autre.

- -

Chargement de notre module wasm sans streaming

- -

Si vous ne pouvez pas ou ne souhaitez pas utiliser les méthodes en streaming décrites ci-dessus, vous pouvez utiliser à la place les méthodes synchrones {{jsxref("WebAssembly.compile")}} / {{jsxref("WebAssembly.instantiate")}}.

- -

Ces méthodes n'accèdent pas directement au bytecode, elles requièrent une étape supplémentaire afin de transformer la réponse en un {{domxref("ArrayBuffer")}} , et cela avant les étapes de compilation/instanciation du module wasm.

- -

Le code équivalent à l'exemple précédent prend la forme suivante:

- -
fetch('simple.wasm').then(response =>
-  response.arrayBuffer()
-).then(bytes =>
-  WebAssembly.instantiate(bytes, importObject)
-).then(results => {
-  results.instance.exports.exported_func();
-});
- -

Visualiser wasm dans l'outil de développement 

- -

In Firefox 54+, the Developer Tool Debugger Panel has functionality to expose the text representation of any wasm code included in a web page. To view it, you can go to the Debugger Panel and click on the “wasm://” entry.

- -

- -

Starting soon in Firefox, in addition to viewing WebAssembly as text, developers will be able to debug (place breakpoints, inspect the callstack, single-step, etc.) WebAssembly using the text format. See WebAssembly debugging with Firefox DevTools for a video preview.

- -

Memory

- -

Dans le modèle mémoire bas niveau de WebAssembly, la mémoire est représentée comme une suite continue de bytes non typés appelée Linear Memory. Cette mémoire linéaire est accessible en écriture et  en lecture par des instructions load et store à l'intérieur du module. Dans ce modèle de mémoire, les instructions load et store peuvent accéder à n'importe quel byte de la mémoire linéaire, ce qui est nécessaire à une réprésentation fidèle de concepts C/C++ comme les pointeurs.

- -

Cependant contrairement à une implémentation native d'un programe C/C++ dans laquelle l'espace de mémoire disponible recouvre celle de l'ensemble du processus, la mémoire accessible par une instance particulière de WebAssembly est un espace mémoire spécifique  — potentiellement très réduit — contenu dans une objet mémoire WebAssembly. Ceci permet à une application web unique d'utiliser des librairies indépendantes — Chacune d'entre elles pouvant utiliser en interne WebAssembly— avec des espaces mémoires séparés qui sont complètement isolés les uns des autres.

- -

Dans Javascript, une instance Memory peut être pensée comme un ArrayBuffer redimensionnable. De la même manière que pour les ArrayBuffers, une application web peut créer de nombreux objets Memory indépendants. Vous pouvez en créer un en utilisant le constructeur {{jsxref("WebAssembly.Memory()")}}, qui prend comme arguments la taille initiale ainsi que la taille maximale de l'espace mémoire à créer.

- -

Explorons ces concepts à travers un exemple rapide.

- -
    -
  1. -

    Créez une autre page HTML (copiez pour cela notre simple template) et appelez la memory.html. Ajoutez un élement <script></script> à la page.

    -
  2. -
  3. -

    Maintenant ajoutez la ligne suivante en haut de votre script, afin de créer une instance mémoire:

    - -
    var memory = new WebAssembly.Memory({initial:10, maximum:100});
    - -

    L'unité pour initial et maximum correspond à une page WebAssembly — soit une taille fixe de 64 KB. Cela signifie que l'instance mémoire ci-dessus à une taille initiale de 64 KB, et une taille maximum de 6.4 MB.

    - -

    WebAssembly memory expose ses bytes par l'intermédiaire d'un tampon getter/setter qui retourne un ArrayBuffer. Par exemple, pour écrire  42 directement dans l'espace du premier mot de la mémoire linéaire, vous pouvez faire cela:

    - -
    new Uint32Array(memory.buffer)[0] = 42;
    - -

    Vous pouvez retourner cette même valeur en utilisant:

    - -
    new Uint32Array(memory.buffer)[0]
    -
  4. -
  5. -

    À vous d'essayer — Enregistrez ce que vous avez rédigé jusqu'à maintenant, chargez-le dans votre navigateur, puis essayez d'entrer les deux lignes ci-dessus dans votre Javscript console.

    -
  6. -
- -

Redimensionner la mémoire

- -

Une instance de mémoire peut être agrandie par appel à la méthode {{jsxref("Memory.prototype.grow()")}}, qui prend comme argument la taille de mémoire à ajouter (en unité de page WebAssembly).

- -
memory.grow(1);
- -

Si une valeur maximum a été fournie à la création de l'instance mémoire, les tentatives d'augmenter l'espace mémoire au delà de cette valeur maximum aboutiront à une exception de type  {{jsxref("WebAssembly.RangeError")}}. Le moteur Javsacript utilise cette valeur limite supérieure pour réserver d'avance un espace mémoire suffisant, ce qui permet de rendre les redimensionnements mémoires plus efficaces.

- -

Note: En raison du caractère immuable de la longueur de byte d'un {{domxref("ArrayBuffer")}}, après une opération {{jsxref("Memory.prototype.grow()")}} réussie, le buffer getter retourne un nouvel objet ArrayBuffer (avec la nouvelle longeur de byte du buffer) et tous les objets ArrayBuffer précédents se retrouve en état "dissocié", ou déconnectés de l'espace mémoire dont ils étaient issus initialement.

- -

Tout comme les fonctions, les espaces mémoires linéaires peuvent être définis à l'intérieur du module, ou bien importés. De manière similaire aux fonctions, un module peut également exporter sa mémoire. Cela signifie que Javascript peut accéder à la mémoire d'une instance WebAssembly soit en créant un nouveau WebAssembly.Memory afin de le passer en import à cette instance, soit en recevant un export Memory (via Instance.prototype.exports).

- -

Exemple avancé pour l'utilisation mémoire

- -

Essayons de clarifier les affirmations ci-dessus à l'aide d'un exemple plus abouti —  à savoir un module WebAssembly qui importe une instance mémoire telle que définie plus tôt, et qui l'alimente d'un tableau d'entiers, pour en faire la somme totale. Vous pouvez trouver cela dans ce fichier memory.wasm.

- -
    -
  1. -

    Faites une copie locale de memory.wasm dans le même dossier que précédement.

    - -

    Note: Vous pouvez trouver la représentation textuelle du module sur memory.wat.

    -
  2. -
  3. -

    Retournez à votre fichier memory.html, et récupérez, compilez, et instancier votre module wasm comme précédement — Ajoutez à la fin de votre script les lignes suivantes:

    - -
    WebAssembly.instantiateStreaming(fetch('memory.wasm'), { js: { mem: memory } })
    -.then(results => {
    -  // add code here
    -});
    -
  4. -
  5. -

    Puisque ce module exporte sa mémoire, nous pouvons utiliser la fonction exportée accumulate() à partir du champ instance (de type Instance) de la valeur de retour results du module pour créer et alimenter l'instance mémoire du module (mem) avec un tableau. Ajoutez les lignes suivantes à votre code à l'emplacement indiqué dans le snippet précédent.

    - -
    var i32 = new Uint32Array(memory.buffer);
    -
    -for (var i = 0; i < 10; i++) {
    -  i32[i] = i;
    -}
    -
    -var sum = results.instance.exports.accumulate(0, 10);
    -console.log(sum);
    -
  6. -
- -

Note: vous pouvez remarquer que nous avons créé la vue {{domxref("Uint32Array")}} sur le champ buffer de l'objet Memory (Memory.prototype.buffer), et pas sur l'objet Memory lui même.

- -

Les imports Memory fonctionnent de la même manière que les imports fonctions, à la différence prés que les objets Memory véhiculent des valeurs au lieu de fonctions Javscripts. Les imports Memory sont utiles pour deux raisons:

- - - -

Note: Vous pouvez trouver une démo complete à memory.html (à voir également live) .

- -

Tables

- -

Une Table WebAssembly est un tableau de références typées redimensionnable qui peut être accédé à la fois par du code Javscript et par du code WebAssembly. Memory fournit un tableau de bytes bruts redimensionnable, mais il n'est pas prudent d'y stocker des références, car une référence est une valeur considérée comme sûre par le moteur Javascript, valeur dont les bytes ne doivent être accessibles ni en lecture, ni en écriture par le contenu pour des raisons de sécurité, de portabilité, et de stabilité.

- -

Les Tables possèdent un type, qui limite les types de références qui peuvent être contenues dans la table. Dans la version actuelle de WebAssembly, il n'existe qu'un seul type de références — functions — et de fait seul ce type de références est donc valide. Dans de prochaines versions, d'autres types de références seront ajoutés.  

- -

Les références de type fonction sont nécessaires afin de compiler des languages comme C/C++ qui permettent l'implémentation de pointeurs sur fonctions. Dans une implémentation native en C/C++, un pointeur sur fonction est représenté par une adresse brute associée au code de la fonction contenue dans l'espace d'adressage virtuel du processus. Pour les raisons de sécurités mentionnées plus haut, cette référence dans WebAssembly ne peut être stockée directement en mémoire linéaire. Les références de fonctions sont stockées dans une table et leurs index, qui sont des entiers, peuvent être placés en mémoire linéaire et véhiculés de manière sûre. 

- -

Lorsque l'appel à un pointeur sur fonction est nécessaire, le caller WebAssembly fournit l'index de la référence à appeler. La valeur de cet index est controlée par rapport au valeurs limites données à l'instantiation de la table (safety bounds checked), et cela avant que l'appel par référence à la fonction soit effectué. Autrement dit, les tables sont actuellement des primitives bas niveau utilisées pour compiler des fonctionnalités de language de programmation bas niveau, de manière sûre et portable.

- -

Les Tables peuvent être modifiées via Table.prototype.set(), which updates one of the values in a table, and Table.prototype.grow(), which increases the number of values that can be stored in a table.  This allows the indirectly-callable set of functions to change over time, which is necessary for dynamic linking techniques.  The mutations are immediately accessible via Table.prototype.get() in JavaScript, and to wasm modules.

- -

Un exemple de table

- -

Envisageons un exemple basique d'utilisation d'une table — un module WebAssembly qui crée et exporte une table contenant 2 éléments: l'élement 0 retourne 13 et l'élément 1 retourne 42. Vous retrouvez cela dans le fichier table.wasm.

- -
    -
  1. -

    Faites une copie locale de table.wasm dans un nouveau dossier.

    - -

    Note: vous pouvez voir une réprésentation textuelle du module sur table.wat.

    -
  2. -
  3. -

    Créez une nouvelle copie du template HTML dans le même dossier et nommez le table.html.

    -
  4. -
  5. -

    Comme précédement, récupérez, compilez, et instanciez le module wasm — ajoutez les lignes suivantes à l'intérieur d'un élement {{htmlelement("script")}} au bas du body html:

    - -
    WebAssembly.instantiateStreaming(fetch('table.wasm'))
    -.then(function(results) {
    -  // add code here
    -});
    -
  6. -
  7. -

    Maintenant accédez aux données contenues dans la table — ajoutez les lignes suivantes dans votre code à la place indiquée dans le snippet précédent:

    - -
    var tbl = results.instance.exports.tbl;
    -console.log(tbl.get(0)());  // 13
    -console.log(tbl.get(1)());  // 42
    -
  8. -
- -

Ce code accède à chaque fonction référencée contenue dans la table, et l' instancie afin d'imprimer sa valeur de retour dans la console — à noter que chaque référence de fonction est obtenue à l'aide de la méthode Table.prototype.get(), suivie d'une paire suplémentaire de parenthèses pour finaliser l'invocation de la fonction.

- -

Note: Vous pouvez retoruver la démo complète sur table.html (voir également live).

- -

Globals

- -

WebAssembly fournit la capacité de créer des instances de variables globales, depuis Javascript et importable/exportable à partir d'une ou plusieurs instances de {{jsxref("WebAssembly.Module")}}. C'est très utile, car cela rend possible la mise en place d'un lien dynamique entre de multiple modules WebAssembly.  

- -

Pour créer une instance globale WebAssembly à partir de Javascript, vous pouvez utiliser le constructeur {{jsxref("WebAssembly.Global()")}}, de la manière suivante:

- -
const global = new WebAssembly.Global({value:'i32', mutable:true}, 0);
- -

Vous pouvez remarquer que ce constructeur prend deux paramètres:

- - - -

Finalement comment tout cela fonctionne? Dans l'exemple suivant nous définissons une variable globale "mutable" de type i32, avec une valeur de 0.

- -

La valeur de la variable globale est ensuite changée en 42 en utilisant la propriété Global.value, puis en 43 en utilisant cette fois la fonction exportée de l'instance du module global.wasm  incGlobal() (cette fonction ajoute 1 à la valeur qui lui est donnée et retourne la nouvelle valeur).

- -
const output = document.getElementById('output');
-
-function assertEq(msg, got, expected) {
-    output.innerHTML += `Testing ${msg}: `;
-    if (got !== expected)
-        output.innerHTML += `FAIL!<br>Got: ${got}<br>Expected: ${expected}<br>`;
-    else
-        output.innerHTML += `SUCCESS! Got: ${got}<br>`;
-}
-
-assertEq("WebAssembly.Global exists", typeof WebAssembly.Global, "function");
-
-const global = new WebAssembly.Global({value:'i32', mutable:true}, 0);
-
-WebAssembly.instantiateStreaming(fetch('global.wasm'), { js: { global } })
-.then(({instance}) => {
-    assertEq("getting initial value from wasm", instance.exports.getGlobal(), 0);
-    global.value = 42;
-    assertEq("getting JS-updated value from wasm", instance.exports.getGlobal(), 42);
-    instance.exports.incGlobal();
-    assertEq("getting wasm-updated value from JS", global.value, 43);
-});
- -

Note: Vous pouvez voir cet exemple en live sur GitHub; voir également le code source.

- -

Multiplicité

- -

Maintenant que nous avons présenté l'utilisation des principaux composants de WebAssembly, il est temps de dire quelques mots sur le concept de multiplicité. Ce dernier donne à WebAssembly un certains nombre d'avantages en terme d'efficience architecturale:

- - - -

Vous pouvez voir la mise en application du concept de multiplicité dans notre article Understanding text format — voir en particulier la section Mutating tables and dynamic linking.

- -

Résumé

- -

Cet article  a couvert les bases de l'utilisation de l'API WebAssembly Javascript nécessaires à l'inclusion d'un module WebAssembly dans un contexte javascript, afin d'utiliser les fonctions du module dans ce contexte,  et de se familiairiser avec la manipulation de la mémoire et des tables WebAssembly. Nous avons terminé en évoquant le concept de multiplicité.

- -

A voir également

- - diff --git a/files/fr/webassembly/using_the_javascript_api/index.md b/files/fr/webassembly/using_the_javascript_api/index.md new file mode 100644 index 0000000000..7e200a4247 --- /dev/null +++ b/files/fr/webassembly/using_the_javascript_api/index.md @@ -0,0 +1,292 @@ +--- +title: Utiliser l'API JavaScript de WebAssembly +slug: WebAssembly/Using_the_JavaScript_API +translation_of: WebAssembly/Using_the_JavaScript_API +--- +
{{WebAssemblySidebar}}
+ +

Si vous avez déjà compilé un module depuis un autre langage en utilisant des outils comme Emscripten, ou chargé et éxecuté vous-même le code, l'étape suivante est d'en apprendre plus à propos des autres fonctionnalités de l'API JavaScript WebAssembly. Cet article vous enseigne ce que vous aurez besoin de connaître.

+ +
+

Note : Si vous n'êtes pas familier avec les concepts de base mentionnés dans cet article et vous avez besoin de plus d'explication, lisez  d'abord WebAssembly concepts.

+
+ +

Quelques exemples simples

+ +

Parcourons quelques exemples illustrant l'utilisation de l'API Webassembly Javascript, et en particulier la manière dont elle peut être utilisé pour charger un module wasm au sein d'une page web. 

+ +
+

Note : Vous pouvez trouver des exemples de code dans notre repo GitHub  webassembly-examples.

+
+ +

Préparation

+ +
    +
  1. Premièrement nous avons besoin d'un module wasm ! Récupérez notre fichier simple.wasm et sauvegardez une copie dans un nouveau document sur votre machine locale.
  2. +
  3. Ensuite, assurez-vous d'utiliser un navigateur supportant WebAssembly. Firefox 52+ et Chrome 57+ supportent WebAssembly par défaut.
  4. +
  5. Pour poursuivre, créez un simple fichier nommé index.html dans le même dossier que votre fichier wasm (vous pouvez utiliser notre template simple si vous n'en avez pas de facilement accessible).
  6. +
  7. Maintenant, pour nous aider à comprendre ce qui se passe ici, regardons la représentation textuelle de notre module wasm  (que nous rencontrons aussi dans Converting WebAssembly format to wasm): +
    (module
    +  (func $i (import "imports" "imported_func") (param i32))
    +  (func (export "exported_func")
    +    i32.const 42
    +    call $i))
    +
  8. +
  9. À la deuxième ligne, vous pouvez constater l'import d'un namespace à deux niveaux  — la fonction interne $i est importée depuis  imports.imported_func.  Dans notre JavaScript, notre namespace doit reprendre ce format à deux niveaux lors de l'écriture de l'objet à importer dans le module wasm. Pour ce faire, créez un élément <script></script> dans votre fichier HTML, puis ajoutez le code suivant: +
    var importObject = {
    +  imports: {
    +      imported_func: function(arg) {
    +        console.log(arg);
    +      }
    +    }
    +  };
    +
  10. +
+ +

Streaming de notre module webassembly

+ +

Il est dorénavant possible dans Firefox 58 de compiler et instancier les modules Webassembly directement à partir des ressources initiales. Il est nécessaire dans ce cas d'utiliser les méthodes {{jsxref("WebAssembly.compileStreaming()")}} et {{jsxref("WebAssembly.instantiateStreaming()")}}. Ces méthodes en streaming sont plus facile d'utilisation que leurs contreparties synchrones, car elles traduisent directement le bytecode en instances de type Module/Instance, sans nécessiter la manipulation d'une réponse intermédiaire {{domxref("Response")}} en un {{domxref("ArrayBuffer")}}.

+ +

Cet exemple (voir notre démo sur GitHub instantiate-streaming.html, et également view it live) montre comment utiliser  instantiateStreaming() pour récupérer un module wasm, le compiler, l'instancier afin d'avoir accès aux fonctions exportées qu'il contient et d'y importer des fonctions Javascript, le tout en une seule et même étape.  

+ +

Ajoutez le code suivant à votre script, en dessous du premier bloc:

+ +
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
+.then(obj => obj.instance.exports.exported_func());
+ +

Le résultat net de l'ensemble du code est que l'appel à exported_func, notre fonction exportée Webassembly, entraîne à son tour l'appel à imported_func notre fonction importée Javscript, qui logue la valeur 42 fournie à l'instance WebAssembly dans la console. Si vous sauvegardez l'exemple et chargez le code dans un navigateur qui supporte WebAssembly, vous pourrez le voir en action.

+ +

Note: Cet exemple interminable et tarabiscoté semble aboutir à un résultat de faible importance, il permet néanmoins d'illustrer les possibilités offertes par l'utilisation conjointe d'un code WebAssembly et d'un code Javscript dans une application web. Comme il est précisé ailleurs, l'objectif de WebAssembly n'est pas de remplacer Javascript; à vrai dire les deux sont conçus pour fonctionner de concert, chacun tirant parti des forces de l'autre.

+ +

Chargement de notre module wasm sans streaming

+ +

Si vous ne pouvez pas ou ne souhaitez pas utiliser les méthodes en streaming décrites ci-dessus, vous pouvez utiliser à la place les méthodes synchrones {{jsxref("WebAssembly.compile")}} / {{jsxref("WebAssembly.instantiate")}}.

+ +

Ces méthodes n'accèdent pas directement au bytecode, elles requièrent une étape supplémentaire afin de transformer la réponse en un {{domxref("ArrayBuffer")}} , et cela avant les étapes de compilation/instanciation du module wasm.

+ +

Le code équivalent à l'exemple précédent prend la forme suivante:

+ +
fetch('simple.wasm').then(response =>
+  response.arrayBuffer()
+).then(bytes =>
+  WebAssembly.instantiate(bytes, importObject)
+).then(results => {
+  results.instance.exports.exported_func();
+});
+ +

Visualiser wasm dans l'outil de développement 

+ +

In Firefox 54+, the Developer Tool Debugger Panel has functionality to expose the text representation of any wasm code included in a web page. To view it, you can go to the Debugger Panel and click on the “wasm://” entry.

+ +

+ +

Starting soon in Firefox, in addition to viewing WebAssembly as text, developers will be able to debug (place breakpoints, inspect the callstack, single-step, etc.) WebAssembly using the text format. See WebAssembly debugging with Firefox DevTools for a video preview.

+ +

Memory

+ +

Dans le modèle mémoire bas niveau de WebAssembly, la mémoire est représentée comme une suite continue de bytes non typés appelée Linear Memory. Cette mémoire linéaire est accessible en écriture et  en lecture par des instructions load et store à l'intérieur du module. Dans ce modèle de mémoire, les instructions load et store peuvent accéder à n'importe quel byte de la mémoire linéaire, ce qui est nécessaire à une réprésentation fidèle de concepts C/C++ comme les pointeurs.

+ +

Cependant contrairement à une implémentation native d'un programe C/C++ dans laquelle l'espace de mémoire disponible recouvre celle de l'ensemble du processus, la mémoire accessible par une instance particulière de WebAssembly est un espace mémoire spécifique  — potentiellement très réduit — contenu dans une objet mémoire WebAssembly. Ceci permet à une application web unique d'utiliser des librairies indépendantes — Chacune d'entre elles pouvant utiliser en interne WebAssembly— avec des espaces mémoires séparés qui sont complètement isolés les uns des autres.

+ +

Dans Javascript, une instance Memory peut être pensée comme un ArrayBuffer redimensionnable. De la même manière que pour les ArrayBuffers, une application web peut créer de nombreux objets Memory indépendants. Vous pouvez en créer un en utilisant le constructeur {{jsxref("WebAssembly.Memory()")}}, qui prend comme arguments la taille initiale ainsi que la taille maximale de l'espace mémoire à créer.

+ +

Explorons ces concepts à travers un exemple rapide.

+ +
    +
  1. +

    Créez une autre page HTML (copiez pour cela notre simple template) et appelez la memory.html. Ajoutez un élement <script></script> à la page.

    +
  2. +
  3. +

    Maintenant ajoutez la ligne suivante en haut de votre script, afin de créer une instance mémoire:

    + +
    var memory = new WebAssembly.Memory({initial:10, maximum:100});
    + +

    L'unité pour initial et maximum correspond à une page WebAssembly — soit une taille fixe de 64 KB. Cela signifie que l'instance mémoire ci-dessus à une taille initiale de 64 KB, et une taille maximum de 6.4 MB.

    + +

    WebAssembly memory expose ses bytes par l'intermédiaire d'un tampon getter/setter qui retourne un ArrayBuffer. Par exemple, pour écrire  42 directement dans l'espace du premier mot de la mémoire linéaire, vous pouvez faire cela:

    + +
    new Uint32Array(memory.buffer)[0] = 42;
    + +

    Vous pouvez retourner cette même valeur en utilisant:

    + +
    new Uint32Array(memory.buffer)[0]
    +
  4. +
  5. +

    À vous d'essayer — Enregistrez ce que vous avez rédigé jusqu'à maintenant, chargez-le dans votre navigateur, puis essayez d'entrer les deux lignes ci-dessus dans votre Javscript console.

    +
  6. +
+ +

Redimensionner la mémoire

+ +

Une instance de mémoire peut être agrandie par appel à la méthode {{jsxref("Memory.prototype.grow()")}}, qui prend comme argument la taille de mémoire à ajouter (en unité de page WebAssembly).

+ +
memory.grow(1);
+ +

Si une valeur maximum a été fournie à la création de l'instance mémoire, les tentatives d'augmenter l'espace mémoire au delà de cette valeur maximum aboutiront à une exception de type  {{jsxref("WebAssembly.RangeError")}}. Le moteur Javsacript utilise cette valeur limite supérieure pour réserver d'avance un espace mémoire suffisant, ce qui permet de rendre les redimensionnements mémoires plus efficaces.

+ +

Note: En raison du caractère immuable de la longueur de byte d'un {{domxref("ArrayBuffer")}}, après une opération {{jsxref("Memory.prototype.grow()")}} réussie, le buffer getter retourne un nouvel objet ArrayBuffer (avec la nouvelle longeur de byte du buffer) et tous les objets ArrayBuffer précédents se retrouve en état "dissocié", ou déconnectés de l'espace mémoire dont ils étaient issus initialement.

+ +

Tout comme les fonctions, les espaces mémoires linéaires peuvent être définis à l'intérieur du module, ou bien importés. De manière similaire aux fonctions, un module peut également exporter sa mémoire. Cela signifie que Javascript peut accéder à la mémoire d'une instance WebAssembly soit en créant un nouveau WebAssembly.Memory afin de le passer en import à cette instance, soit en recevant un export Memory (via Instance.prototype.exports).

+ +

Exemple avancé pour l'utilisation mémoire

+ +

Essayons de clarifier les affirmations ci-dessus à l'aide d'un exemple plus abouti —  à savoir un module WebAssembly qui importe une instance mémoire telle que définie plus tôt, et qui l'alimente d'un tableau d'entiers, pour en faire la somme totale. Vous pouvez trouver cela dans ce fichier memory.wasm.

+ +
    +
  1. +

    Faites une copie locale de memory.wasm dans le même dossier que précédement.

    + +

    Note: Vous pouvez trouver la représentation textuelle du module sur memory.wat.

    +
  2. +
  3. +

    Retournez à votre fichier memory.html, et récupérez, compilez, et instancier votre module wasm comme précédement — Ajoutez à la fin de votre script les lignes suivantes:

    + +
    WebAssembly.instantiateStreaming(fetch('memory.wasm'), { js: { mem: memory } })
    +.then(results => {
    +  // add code here
    +});
    +
  4. +
  5. +

    Puisque ce module exporte sa mémoire, nous pouvons utiliser la fonction exportée accumulate() à partir du champ instance (de type Instance) de la valeur de retour results du module pour créer et alimenter l'instance mémoire du module (mem) avec un tableau. Ajoutez les lignes suivantes à votre code à l'emplacement indiqué dans le snippet précédent.

    + +
    var i32 = new Uint32Array(memory.buffer);
    +
    +for (var i = 0; i < 10; i++) {
    +  i32[i] = i;
    +}
    +
    +var sum = results.instance.exports.accumulate(0, 10);
    +console.log(sum);
    +
  6. +
+ +

Note: vous pouvez remarquer que nous avons créé la vue {{domxref("Uint32Array")}} sur le champ buffer de l'objet Memory (Memory.prototype.buffer), et pas sur l'objet Memory lui même.

+ +

Les imports Memory fonctionnent de la même manière que les imports fonctions, à la différence prés que les objets Memory véhiculent des valeurs au lieu de fonctions Javscripts. Les imports Memory sont utiles pour deux raisons:

+ + + +

Note: Vous pouvez trouver une démo complete à memory.html (à voir également live) .

+ +

Tables

+ +

Une Table WebAssembly est un tableau de références typées redimensionnable qui peut être accédé à la fois par du code Javscript et par du code WebAssembly. Memory fournit un tableau de bytes bruts redimensionnable, mais il n'est pas prudent d'y stocker des références, car une référence est une valeur considérée comme sûre par le moteur Javascript, valeur dont les bytes ne doivent être accessibles ni en lecture, ni en écriture par le contenu pour des raisons de sécurité, de portabilité, et de stabilité.

+ +

Les Tables possèdent un type, qui limite les types de références qui peuvent être contenues dans la table. Dans la version actuelle de WebAssembly, il n'existe qu'un seul type de références — functions — et de fait seul ce type de références est donc valide. Dans de prochaines versions, d'autres types de références seront ajoutés.  

+ +

Les références de type fonction sont nécessaires afin de compiler des languages comme C/C++ qui permettent l'implémentation de pointeurs sur fonctions. Dans une implémentation native en C/C++, un pointeur sur fonction est représenté par une adresse brute associée au code de la fonction contenue dans l'espace d'adressage virtuel du processus. Pour les raisons de sécurités mentionnées plus haut, cette référence dans WebAssembly ne peut être stockée directement en mémoire linéaire. Les références de fonctions sont stockées dans une table et leurs index, qui sont des entiers, peuvent être placés en mémoire linéaire et véhiculés de manière sûre. 

+ +

Lorsque l'appel à un pointeur sur fonction est nécessaire, le caller WebAssembly fournit l'index de la référence à appeler. La valeur de cet index est controlée par rapport au valeurs limites données à l'instantiation de la table (safety bounds checked), et cela avant que l'appel par référence à la fonction soit effectué. Autrement dit, les tables sont actuellement des primitives bas niveau utilisées pour compiler des fonctionnalités de language de programmation bas niveau, de manière sûre et portable.

+ +

Les Tables peuvent être modifiées via Table.prototype.set(), which updates one of the values in a table, and Table.prototype.grow(), which increases the number of values that can be stored in a table.  This allows the indirectly-callable set of functions to change over time, which is necessary for dynamic linking techniques.  The mutations are immediately accessible via Table.prototype.get() in JavaScript, and to wasm modules.

+ +

Un exemple de table

+ +

Envisageons un exemple basique d'utilisation d'une table — un module WebAssembly qui crée et exporte une table contenant 2 éléments: l'élement 0 retourne 13 et l'élément 1 retourne 42. Vous retrouvez cela dans le fichier table.wasm.

+ +
    +
  1. +

    Faites une copie locale de table.wasm dans un nouveau dossier.

    + +

    Note: vous pouvez voir une réprésentation textuelle du module sur table.wat.

    +
  2. +
  3. +

    Créez une nouvelle copie du template HTML dans le même dossier et nommez le table.html.

    +
  4. +
  5. +

    Comme précédement, récupérez, compilez, et instanciez le module wasm — ajoutez les lignes suivantes à l'intérieur d'un élement {{htmlelement("script")}} au bas du body html:

    + +
    WebAssembly.instantiateStreaming(fetch('table.wasm'))
    +.then(function(results) {
    +  // add code here
    +});
    +
  6. +
  7. +

    Maintenant accédez aux données contenues dans la table — ajoutez les lignes suivantes dans votre code à la place indiquée dans le snippet précédent:

    + +
    var tbl = results.instance.exports.tbl;
    +console.log(tbl.get(0)());  // 13
    +console.log(tbl.get(1)());  // 42
    +
  8. +
+ +

Ce code accède à chaque fonction référencée contenue dans la table, et l' instancie afin d'imprimer sa valeur de retour dans la console — à noter que chaque référence de fonction est obtenue à l'aide de la méthode Table.prototype.get(), suivie d'une paire suplémentaire de parenthèses pour finaliser l'invocation de la fonction.

+ +

Note: Vous pouvez retoruver la démo complète sur table.html (voir également live).

+ +

Globals

+ +

WebAssembly fournit la capacité de créer des instances de variables globales, depuis Javascript et importable/exportable à partir d'une ou plusieurs instances de {{jsxref("WebAssembly.Module")}}. C'est très utile, car cela rend possible la mise en place d'un lien dynamique entre de multiple modules WebAssembly.  

+ +

Pour créer une instance globale WebAssembly à partir de Javascript, vous pouvez utiliser le constructeur {{jsxref("WebAssembly.Global()")}}, de la manière suivante:

+ +
const global = new WebAssembly.Global({value:'i32', mutable:true}, 0);
+ +

Vous pouvez remarquer que ce constructeur prend deux paramètres:

+ + + +

Finalement comment tout cela fonctionne? Dans l'exemple suivant nous définissons une variable globale "mutable" de type i32, avec une valeur de 0.

+ +

La valeur de la variable globale est ensuite changée en 42 en utilisant la propriété Global.value, puis en 43 en utilisant cette fois la fonction exportée de l'instance du module global.wasm  incGlobal() (cette fonction ajoute 1 à la valeur qui lui est donnée et retourne la nouvelle valeur).

+ +
const output = document.getElementById('output');
+
+function assertEq(msg, got, expected) {
+    output.innerHTML += `Testing ${msg}: `;
+    if (got !== expected)
+        output.innerHTML += `FAIL!<br>Got: ${got}<br>Expected: ${expected}<br>`;
+    else
+        output.innerHTML += `SUCCESS! Got: ${got}<br>`;
+}
+
+assertEq("WebAssembly.Global exists", typeof WebAssembly.Global, "function");
+
+const global = new WebAssembly.Global({value:'i32', mutable:true}, 0);
+
+WebAssembly.instantiateStreaming(fetch('global.wasm'), { js: { global } })
+.then(({instance}) => {
+    assertEq("getting initial value from wasm", instance.exports.getGlobal(), 0);
+    global.value = 42;
+    assertEq("getting JS-updated value from wasm", instance.exports.getGlobal(), 42);
+    instance.exports.incGlobal();
+    assertEq("getting wasm-updated value from JS", global.value, 43);
+});
+ +

Note: Vous pouvez voir cet exemple en live sur GitHub; voir également le code source.

+ +

Multiplicité

+ +

Maintenant que nous avons présenté l'utilisation des principaux composants de WebAssembly, il est temps de dire quelques mots sur le concept de multiplicité. Ce dernier donne à WebAssembly un certains nombre d'avantages en terme d'efficience architecturale:

+ + + +

Vous pouvez voir la mise en application du concept de multiplicité dans notre article Understanding text format — voir en particulier la section Mutating tables and dynamic linking.

+ +

Résumé

+ +

Cet article  a couvert les bases de l'utilisation de l'API WebAssembly Javascript nécessaires à l'inclusion d'un module WebAssembly dans un contexte javascript, afin d'utiliser les fonctions du module dans ce contexte,  et de se familiairiser avec la manipulation de la mémoire et des tables WebAssembly. Nous avons terminé en évoquant le concept de multiplicité.

+ +

A voir également

+ + -- cgit v1.2.3-54-g00ecf