| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/fr/docs/WebAssembly/Guides/Using_the_JavaScript_API | [Back] [Original] |
Get to know MDN better
Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.
Si vous avez dj compil un module depuis un autre langage en utilisant des outils comme Emscripten, ou charg et xecut vous-mme le code, l'tape suivante est d'en apprendre plus propos des autres fonctionnalits de l'API JavaScript WebAssembly. Cet article vous enseigne ce que vous aurez besoin de connatre.
Note : Si vous n'tes pas familier avec les concepts de base mentionns dans cet article et vous avez besoin de plus d'explication, lisez d'abord les concepts de WebAssembly.
Parcourons quelques exemples illustrant l'utilisation de l'API Webassembly JavaScript, et en particulier la manire 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 (angl.).
Premirement nous avons besoin d'un module wasm ! Rcuprez notre fichier simple.wasm (angl.) et sauvegardez une copie dans un nouveau document sur votre machine locale.
Ensuite, crons un fichier HTML simple appel index.html dans le mme dossier que votre fichier Wasm (vous pouvez utiliser notre modle simple (angl.) si vous n'en avez pas dj un sous la main).
Maintenant, pour nous aider comprendre ce qui se passe ici, regardons la reprsentation textuelle de notre module Wasm (que l'on retrouve aussi dans Conversion du format WebAssembly en Wasm) :
(module
(func $i (import "my_namespace" "imported_func") (param i32))
(func (export "exported_func")
i32.const 42
call $i))
la deuxime ligne, vous pouvez constater l'import d'un namespace deux niveaux la fonction interne $i est importe depuis my_namespace.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, crez un lment <script></script> dans votre fichier HTML, puis ajoutez le code suivant :
const importObject = {
my_namespace: { imported_func: (arg) => console.log(arg) },
};
Il est dornavant possible dans Firefox 58 de compiler et instancier les modules Webassembly directement partir des ressources initiales. Il est ncessaire dans ce cas d'utiliser les mthodes WebAssembly.compileStreaming() et WebAssembly.instantiateStreaming(). Ces mthodes en streaming sont plus facile d'utilisation que leurs contreparties synchrones, car elles traduisent directement le bytecode en instances de type Module/Instance, sans ncessiter la manipulation d'une rponse intermdiaire Response en un ArrayBuffer.
Cet exemple (voir notre dmo sur GitHub instantiate-streaming.html (angl.), et galement en direct (angl.)) montre comment utiliser instantiateStreaming() pour rcuprer un module wasm, le compiler, l'instancier afin d'avoir accs aux fonctions exportes qu'il contient et d'y importer des fonctions JavaScript, le tout en une seule et mme 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 rsultat net de l'ensemble du code est que l'appel exported_func, notre fonction exporte Webassembly, entrane son tour l'appel imported_func notre fonction importe JavaScript, 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 rsultat de faible importance, il permet nanmoins d'illustrer les possibilits offertes par l'utilisation conjointe d'un code WebAssembly et d'un code JavaScript dans une application web. Comme il est prcis ailleurs, l'objectif de WebAssembly n'est pas de remplacer JavaScript; vrai dire les deux sont conus pour fonctionner de concert, chacun tirant parti des forces de l'autre.
Si vous ne pouvez pas ou ne souhaitez pas utiliser les mthodes de diffusion dcrites ci-dessus, vous pouvez utiliser la place les mthodes non diffuses WebAssembly.compile() / WebAssembly.instantiate().
Ces mthodes n'accdent pas directement au bytecode, elles ncessitent donc une tape supplmentaire pour transformer la rponse en un ArrayBuffer avant de compiler/instancier le module Wasm.
Le code quivalent ressemblerait ceci :
fetch("simple.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => WebAssembly.instantiate(bytes, importObject))
.then((results) => {
results.instance.exports.exported_func();
});
partir de Firefox 54+, le panneau Dbogueur des outils de dveloppement permet d'afficher la reprsentation textuelle de tout code Wasm inclus dans une page web. Pour la visualiser, rendez-vous dans le panneau Dbogueur et cliquez sur l'entre wasm:// .
[Panneau du dbogueur des outils de dveloppement mettant en vidence un module.]
En plus de visualiser WebAssembly sous forme de texte, les dveloppeureuses peuvent dboguer (poser des points d'arrt, inspecter la pile d'appels, excuter pas pas, etc.) WebAssembly en utilisant le format texte.
Dans le modle mmoire bas niveau de WebAssembly, la mmoire est reprsente comme une plage contigu d'octets non typs appele mmoire linair (angl.)e qui est lue et crite par des instructions de chargement et de stockage (angl.) l'intrieur du module. Dans ce modle de mmoire, toute instruction de chargement ou de stockage peut accder n'importe quel octet de toute la mmoire linaire, ce qui est ncessaire pour reprsenter fidlement des concepts C/C++ comme les pointeurs.
Contrairement un programme C/C++ natif, cependant, o la plage de mmoire disponible couvre l'ensemble du processus, la mmoire accessible par une instance particulire de WebAssembly est limite une plage spcifique potentiellement trs rduite contenue dans un objet Memory WebAssembly. Cela permet une application web unique d'utiliser plusieurs bibliothques indpendantes chacune utilisant WebAssembly en interne avec des mmoires spares totalement isoles les unes des autres. De plus, les implmentations rcentes peuvent aussi crer des mmoires partages, qui peuvent tre transfres entre les contextes Window et Worker l'aide de postMessage(), et utilises plusieurs endroits.
En JavaScript, une instance Memory peut tre considre comme un ArrayBuffer redimensionnable (ou SharedArrayBuffer, dans le cas des mmoires partages) et, tout comme pour les ArrayBuffer, une application web peut crer de nombreux objets Memory indpendants. Vous pouvez en crer un l'aide du constructeur WebAssembly.Memory(), qui prend comme arguments une taille initiale et (optionnellement) une taille maximale et une proprit shared qui indique s'il s'agit d'une mmoire partage ou non.
Commenons explorer cela l'aide d'un exemple rapide.
Crez une autre page HTML (copiez pour cela notre modle simple (angl.)) et appelez la memory.html. Ajoutez un lement <script></script> la page.
Maintenant ajoutez la ligne suivante en haut de votre script, afin de crer une instance mmoire :
const 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 mmoire ci-dessus une taille initiale de 64 KB, et une taille maximum de 6.4 MB.
WebAssembly memory expose ses bytes par l'intermdiaire d'un tampon getter/setter qui retourne un ArrayBuffer. Par exemple, pour crire 42 directement dans l'espace du premier mot de la mmoire linaire, vous pouvez faire cela :
const data = new DataView(memory.buffer);
data.setUint32(0, 42, true);
Vous pouvez retourner cette mme valeur en utilisant :
data.getUint32(0, true);
vous d'essayer Enregistrez ce que vous avez rdig jusqu' maintenant, chargez-le dans votre navigateur, puis essayez d'entrer les deux lignes ci-dessus dans votre javascript console.
Une instance de mmoire peut tre agrandie par appel la mthode Memory.prototype.grow(), qui prend comme argument la taille de mmoire ajouter (en unit de page WebAssembly).
memory.grow(1);
Si une valeur maximum a t fournie la cration de l'instance mmoire, les tentatives d'augmenter l'espace mmoire au del de cette valeur maximum aboutiront une exception de type RangeError. Le moteur JavaScript utilise cette valeur limite suprieure pour rserver d'avance un espace mmoire suffisant, ce qui permet de rendre les redimensionnements mmoires plus efficaces.
Note: En raison du caractre immuable de la longueur de byte d'un ArrayBuffer, aprs une opration Memory.prototype.grow() russie, le buffer getter retourne un nouvel objet ArrayBuffer (avec la nouvelle longeur de byte du buffer) et tous les objets ArrayBuffer prcdents se retrouve en tat dissoci , ou dconnects de l'espace mmoire dont ils taient issus initialement.
Tout comme les fonctions, les espaces mmoires linaires peuvent tre dfinis l'intrieur du module, ou bien imports. De manire similaire aux fonctions, un module peut galement exporter sa mmoire. Cela signifie que JavaScript peut accder la mmoire d'une instance WebAssembly soit en crant un nouveau WebAssembly.Memory afin de le passer en import cette instance, soit en recevant un export Memory (via Instance.prototype.exports).
Essayons de clarifier les affirmations ci-dessus l'aide d'un exemple plus abouti savoir un module WebAssembly qui importe une instance mmoire telle que dfinie plus tt, et qui l'alimente d'un tableau d'entiers, pour en faire la somme totale. Vous pouvez trouver cela dans ce fichier memory.wasm (angl.).
Faites une copie locale de memory.wasm dans le mme dossier que prcdement.
Note : Vous pouvez trouver la reprsentation textuelle du module sur memory.wat (angl.).
Retournez votre fichier memory.html, et rcuprez, compilez, et instancier votre module wasm comme prcdement Ajoutez la fin de votre script les lignes suivantes :
WebAssembly.instantiateStreaming(fetch("memory.wasm"), {
js: { mem: memory },
}).then((results) => {
// et du code ici
});
Puisque ce module exporte sa mmoire, nous pouvons utiliser la fonction exporte accumulate() partir du champ instance (de type Instance) de la valeur de retour results du module pour crer et alimenter l'instance mmoire du module (mem) avec un tableau. Ajoutez les lignes suivantes votre code l'emplacement indiqu dans le snippet prcdent.
const summands = new DataView(memory.buffer);
for (let i = 0; i < 10; i++) {
summands.setUint32(i * 4, i, true);
}
const sum = results.instance.exports.accumulate(0, 10);
console.log(sum);
Notez que nous crons la vue DataView sur le tampon de l'objet Memory (Memory.prototype.buffer), et non sur l'objet Memory lui-mme.
Les imports Memory fonctionnent de la mme manire que les imports fonctions, la diffrence prs que les objets Memory vhiculent des valeurs au lieu de fonctions javascripts. Les imports Memory sont utiles pour deux raisons :
Note : Vous pouvez trouver une dmo complete memory.html (angl.) ( voir galement en direct (angl.)).
Une Table WebAssembly est un tableau de rfrences types redimensionnable qui peut tre accd la fois par du code JavaScript et par du code WebAssembly. Memory fournit un tableau d'octets bruts redimensionnable, mais il n'est pas prudent d'y stocker des rfrences, car une rfrence est une valeur considre comme sre 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 scurit, de portabilit, et de stabilit.
Les tableaux possdent un type, qui limite les types de rfrences qui peuvent tre contenues dans le tableau. Dans la version actuelle de WebAssembly, il n'existe qu'un seul type de rfrences fonctions et de fait seul ce type de rfrences est donc valide. Dans de prochaines versions, d'autres types de rfrences seront ajouts.
Les rfrences de type fonction sont ncessaires afin de compiler des languages comme C/C++ qui permettent l'implmentation de pointeurs sur fonctions. Dans une implmentation native en C/C++, un pointeur sur fonction est reprsent par une adresse brute associe au code de la fonction contenue dans l'espace d'adressage virtuel du processus. Pour les raisons de scurits mentionnes plus haut, cette rfrence dans WebAssembly ne peut tre stocke directement en mmoire linaire. Les rfrences de fonctions sont stockes dans un tableau et leurs index, qui sont des entiers, peuvent tre placs en mmoire linaire et vhiculs de manire sre.
Lorsque l'appel un pointeur sur fonction est ncessaire, le caller WebAssembly fournit l'index de la rfrence appeler. La valeur de cet index est controle par rapport au valeurs limites donnes l'instantiation du tableau (safety bounds checked), et cela avant que l'appel par rfrence la fonction soit effectu. Autrement dit, les tableaux sont actuellement des primitives bas niveau utilises pour compiler des fonctionnalits de language de programmation bas niveau, de manire sre et portable.
Les tableaux peuvent tre modifis via Table.prototype.set(), qui met jour l'une des valeurs dans un tableau, et Table.prototype.grow(), qui augmente le nombre de valeurs pouvant tre stockes dans un tableau. Cela permet l'ensemble des fonctions appelables indirectement d'voluer au fil du temps, ce qui est ncessaire pour les techniques de liaison dynamique (angl.). Les mutations sont immdiatement accessibles via Table.prototype.get() en JavaScript, et dans les modules wasm.
Envisageons un exemple basique d'utilisation d'un tableau un module WebAssembly qui cre et exporte un tableau contenant 2 lments: l'lement 0 retourne 13 et l'lment 1 retourne 42. Vous retrouvez cela dans le fichier table.wasm (angl.).
Faites une copie locale de table.wasm dans un nouveau dossier.
Note : Vous pouvez voir une rprsentation textuelle du module sur table.wat (angl.).
Crez une nouvelle copie du modle HTML (angl.) dans le mme dossier et nommez le table.html.
Comme prcdement, rcuprez, compilez, et instanciez le module wasm ajoutez les lignes suivantes l'intrieur d'un lement <script> au bas du corps HTML :
WebAssembly.instantiateStreaming(fetch("table.wasm")).then((results) => {
// et du code ici
});
Maintenant accdez aux donnes contenues dans le tableau ajoutez les lignes suivantes dans votre code la place indique dans le snippet prcdent :
const tbl = results.instance.exports.tbl;
console.log(tbl.get(0)()); // 13
console.log(tbl.get(1)()); // 42
Ce code accde chaque fonction rfrence contenue dans la table, et l' instancie afin d'imprimer sa valeur de retour dans la console noter que chaque rfrence de fonction est obtenue l'aide de la mthode Table.prototype.get(), suivie d'une paire suplmentaire de parenthses pour finaliser l'invocation de la fonction.
Note : Vous pouvez retoruver la dmo complte sur table.html (angl.) (voir galement en direct (angl.)).
WebAssembly fournit la capacit de crer des instances de variables globales, depuis JavaScript et importable/exportable partir d'une ou plusieurs instances de WebAssembly.Module. C'est trs utile, car cela rend possible la mise en place d'un lien dynamique entre de multiple modules WebAssembly.
Pour crer une instance globale WebAssembly partir de JavaScript, vous pouvez utiliser le constructeur WebAssembly.Global(), de la manire suivante:
const global = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
Vous pouvez remarquer que ce constructeur prend deux paramtres :
Un objet qui comprend deux proprits dcrivant la variable globale:
value: correspond au type de donne de la variable globale instancie. Type de donne qui peut tre n'importe quel type compatible avec les modules WebAssembly modules i32, i64, f32, ou f64.mutable: un boolen definissant si la valeur est "mutable" ou non.Une valeur correspondant la valeur prise par la variable. Cela peut tre n'importe quelle valeur condition qu'elle soit compatible avec le type de donne spcifi.
Finalement comment tout cela fonctionne? Dans l'exemple suivant nous dfinissons une variable globale "mutable" de type i32, avec une valeur de 0.
La valeur de la variable globale est ensuite change en 42 en utilisant la proprit Global.value, puis en 43 en utilisant cette fois la fonction exporte de l'instance du module global.wasm incGlobal() (cette fonction ajoute 1 la valeur qui lui est donne et retourne la nouvelle valeur).
const output = document.getElementById("output");
function assertEq(msg, got, expected) {
output.innerHTML += `Teste ${msg} : `;
if (got !== expected)
output.innerHTML += `ECHEC !<br>A obtenu : ${got}<br>Attendu : ${expected}<br>`;
else output.innerHTML += `SUCCS ! A obtenu : ${got}<br>`;
}
assertEq("WebAssembly.Global existe", typeof WebAssembly.Global, "function");
const global = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
WebAssembly.instantiateStreaming(fetch("global.wasm"), { js: { global } }).then(
({ instance }) => {
assertEq(
"obtention de la valeur initiale depuis wasm",
instance.exports.getGlobal(),
0,
);
global.value = 42;
assertEq(
"obtention de la valeur mise jour depuis JS dans wasm",
instance.exports.getGlobal(),
42,
);
instance.exports.incGlobal();
assertEq(
"obtention de la valeur mise jour depuis wasm dans JS",
global.value,
43,
);
},
);
Note : Vous pouvez voir cet exemple en direct sur GitHub (angl.) ; voir galement le code source (angl.).
Maintenant que nous avons prsent l'utilisation des principaux composants de WebAssembly, il est temps d'aborder le concept de multiplicit. Celui-ci offre WebAssembly de nombreux avantages en termes d'efficience architecturale :
Vous pouvez voir la multiplicit en action dans notre article Comprendre le format texte voir la section Mutation des tables et liaison dynamique.
Cet article a couvert les bases de l'utilisation de l'API WebAssembly JavaScript ncessaires 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 mmoire et des tableaux WebAssembly. Nous avons termin en voquant le concept de multiplicit.
Cette page a t modifie le 26 dc. 2025 par les contributeurices du MDN.
Certaines parties de ce contenu sont protges par le droit d'auteur 19982026 des contributeurs individuels de mozilla.org. Contenu disponible sous une licence Creative Commons.
| Web Proxy Viewer | New URL | Original Page |