Comportement de WebAssembly selon les plateformes de navigateur
Portabilité de WebAssembly, différences valides entre plateformes et tests de versions sans confondre correction et vitesse.
Vous voulez la documentation structurée pour Plateforme ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
WebAssembly fournit aux navigateurs un format portable pour exécuter des modules compilés, mais la portabilité ne signifie pas que tous les navigateurs et hôtes ont les mêmes fonctions, ressources ou performances. Le contrat utile est plus précis : un module peut dépendre des instructions et services hôtes fournis par son environnement pris en charge. Consignez ces besoins avant de comparer des versions. La décision porte alors sur la compatibilité d’une tâche applicative, sans supposer que le format efface les différences entre plateformes. La spécification WebAssembly Core définit le comportement portable des instructions ; le navigateur fournit le contexte web autour du module.
Un module contient des instructions typées et peut déclarer de la mémoire et des imports qui le relient à son hôte. La spécification définit le comportement des instructions principales prises en charge, tandis que la page et le navigateur offrent des services comme les entrées, le stockage et l’affichage. Un module limité à un jeu courant de fonctions et à des entrées contrôlées se transporte plus facilement qu’un module dépendant de fonctions facultatives ou de services propres à l’hôte. Cette frontière permet de distinguer ce qui voyage avec le module de ce qui doit être vérifié dans l’application qui l’intègre.
La disponibilité des fonctions fait partie du contrat. Un compilateur peut produire des instructions qu’un runtime ancien ne prend pas en charge, même si le programme source semble inchangé. Le support progresse à des rythmes différents selon les navigateurs ; le format seul ne garantit donc pas la présence de chaque instruction. Rendez visible le jeu minimal de fonctions dans le processus de compilation. Si des fonctions facultatives sont nécessaires, fournissez une compilation visant une base plus large ou un repli applicatif, puis testez la sélection faite par la page.
Les imports relient le module à des comportements que le cœur de WebAssembly ne définit pas. La page peut fournir des fonctions d’accès aux données ou des services applicatifs, qui suivent leurs propres contrats. Les règles d’import de la spécification Core définissent leur déclaration, mais des imports correspondants ne garantissent pas des capacités hôtes équivalentes entre navigateurs. Limitez cette interface et documentez ses entrées et sorties autorisées.
Il faut distinguer les étapes : validate() vérifie les octets du module, compile() crée un WebAssembly.Module et instantiate() résout les imports et crée une instance. L’instanciation exige aussi un module valide (spécification Core). Gérez chaque échec comme un état applicatif distinct et gardez l’entrée d’origine. Si le module est facultatif, attendez que sa tâche soit demandée ; la fin du chargement ne prouve rien sur l’ordinateur de l’utilisateur.
L’artefact du module doit aussi être traité comme une interface versionnée. Ses fonctions exportées et services importés constituent un contrat avec la page, comme une requête réseau ou un enregistrement stocké. Une section personnalisée peut contenir des informations de débogage ou des données tierces, mais ces métadonnées facultatives sont ignorées par la sémantique de WebAssembly ; elles ne remplacent ni le versionnage applicatif ni une décision de publication. Conservez la description d’interface de la page dans le contrat applicatif. Une mise à jour du compilateur peut changer le binaire sans changer ce contrat ; comparez donc le comportement plutôt que d’exiger des octets identiques.
Sources de différences valides
L’hôte fournit des ressources et des fonctions importées. L’accès aux fichiers, aux horloges, au réseau, au stockage et aux services applicatifs suit donc des contrats distincts. Les limites de ressources et l’ordonnancement varient aussi. La vitesse n’est pas constante d’un appareil à l’autre ; un changement de performance ne doit pas être confondu avec un changement de sémantique du module. Pour vérifier la correction, comparez le résultat au contrat du module et de l’application, pas à une durée mesurée sur un autre système.
Certaines opérations numériques sont précisément définies, tandis que d’autres laissent une marge aux implémentations. Les conversions entre valeurs WebAssembly et JavaScript, ainsi que l’analyse ou la sérialisation des données par l’application, peuvent aussi modifier le résultat. Si un parcours dépend d’une valeur numérique précise, identifiez l’opération et la représentation. Ne supposez pas que tous les runtimes renvoient exactement les mêmes valeurs dans chaque détail et n’élargissez pas une règle de comparaison avant d’avoir vérifié la norme pertinente et le besoin métier.
Les modules dépendent également des ressources disponibles. Les allocations mémoire, l’agrandissement des tables, l’usage de la pile et le volume d’entrée peuvent déterminer si une tâche aboutit. Les navigateurs peuvent imposer des limites pour leur stabilité, mais celles-ci ne décrivent pas la mémoire physique de l’hôte. Traitez une allocation impossible comme une contrainte de ressources, pas comme une identité d’appareil. L’application peut borner la charge, préserver les entrées et proposer une autre voie si la tâche ne peut pas continuer.
Des fonctions facultatives peuvent dépendre du contexte de déploiement. Par exemple, la politique de sécurité de la page ou la configuration des workers peut ne pas fournir les conditions requises par un module. Un parcours qui fonctionne dans une page de test locale peut être refusé dans le produit. Testez le contexte réel de déploiement, notamment la politique de la page et l’usage des workers, et consignez le besoin concerné. C’est plus utile que de recueillir des propriétés sans rapport avec le runtime.
Les hypothèses de concurrence appartiennent aussi au contrat de déploiement. Un module utilisant la mémoire partagée ou la coordination entre workers peut exiger des conditions de page inutiles à un module mono-thread. Si le produit accepte les deux parcours, vérifiez la sélection et leur respect du même contrat de données visible par l’utilisateur. La voie mono-thread peut répondre différemment tout en fournissant un résultat valide pour une tâche délimitée. Ne rendez pas toute la fonction indisponible parce qu’un parcours de concurrence facultatif ne peut pas s’exécuter. Précisez le contexte pris en charge et testez le repli sous la même politique de déploiement que le parcours principal.
Il est utile de distinguer trois frontières à l’origine des différences : le module compilé, l’implémentation WebAssembly du navigateur et les services hôtes fournis par l’application. Si seul l’artefact a changé, une nouvelle cible de compilation ou révision de source peut expliquer le résultat. Si l’artefact est fixe mais qu’un service importé a changé, examinez l’intégration de la page. Si les deux restent inchangés et que le comportement varie selon la version du navigateur, le runtime devient un point de comparaison pertinent. Cette méthode ne présume pas la cause ; elle ordonne l’examen des preuves et évite d’attribuer toute différence de plateforme au navigateur.
Confidentialité et reproductibilité
WebAssembly est un format d’exécution, pas une frontière de confidentialité. Un module peut traiter des informations localement, mais les imports hôtes et l’application déterminent si les entrées ou résultats sont ensuite conservés ou transmis. Examinez tout le parcours, de la collecte à la mémoire du module, aux valeurs renvoyées, aux journaux, aux exports et à la suppression. Le fait qu’un calcul se soit déroulé dans le navigateur ne prouve pas que le parcours entier soit resté local ou que l’application n’ait rien gardé.
Limitez les données transmises au module à ce que sa tâche exige. Le module compilé est livré au client et doit être considéré comme du code applicatif inspectable, pas comme un endroit où cacher des identifiants ou des dossiers privés. Les opérations sensibles doivent disposer d’une autorisation appropriée, et l’hôte ne doit exposer que les services nécessaires à la tâche de l’utilisateur. Lorsqu’une tâche est annulée ou qu’une vue est fermée, arrêtez le travail si possible et libérez les références qui conservent ses données d’entrée.
Pour reproduire un résultat, gardez fixes l’artefact, les options de compilation, les imports, les entrées et les fonctions requises du navigateur. Un module qui lit une horloge, reçoit des données aléatoires d’un service hôte ou consulte un stockage modifiable peut raisonnablement produire des résultats différents entre exécutions. Ces entrées appartiennent au contrat applicatif. Les tests doivent les contrôler si la répétabilité est nécessaire, ou prévoir explicitement leurs variations si le parcours utilisateur en dépend.
Les informations de capacité peuvent aider l’application à choisir un parcours compatible, mais ne doivent pas devenir par défaut un registre d’identité persistant. Si des diagnostics sont nécessaires, associez-les à un problème signalé par l’utilisateur, conservez seulement la version et le résultat requis pour le reproduire, puis supprimez le dossier quand le besoin de support prend fin. Évitez de recueillir des mesures de temps ou de ressources sans rapport. La vérification reste ainsi centrée sur une tâche reproductible, pas sur la classification de l’environnement.
Les dépendances incluses dans le module nécessitent une revue ordinaire de confidentialité et de maintenance. Des bibliothèques peuvent traiter les entrées ou formater les sorties, et la compilation ne modifie ni leurs licences ni leur historique de mises à jour. Conservez les dépendances sources et les options du compilateur utilisées pour l’artefact livré. Les mainteneurs pourront ainsi comprendre les changements lors d’une mise à jour de bibliothèque, sans considérer le binaire comme opaque ni recueillir de détails sur les machines des utilisateurs. Si une dépendance ajoute un accès réseau ou une persistance côté application, examinez ce comportement. La compilation ne supprime pas la responsabilité de comprendre le flux de données du logiciel livré.
Présentez prudemment l’exécution locale. Un module exécuté dans le navigateur peut garder un calcul intermédiaire sur l’appareil, mais l’application peut tout de même envoyer les entrées avant l’exécution ou les résultats après celle-ci. La page peut aussi charger le module et le modèle depuis une origine distante. Examinez le réseau et le stockage autour du module au lieu de déduire le traitement des données du format d’exécution. Si l’application propose un parcours hors ligne, testez-le sans réseau et précisez quelles fonctions restent disponibles. La description doit refléter le comportement réel du produit, et non une promesse générale liée à WebAssembly.
Compatibilité du module
Documentez le jeu minimal de fonctions WebAssembly requis par le module et les imports hôtes dont la page a besoin. Gardez ces exigences avec la révision du module afin qu’une compilation ultérieure ne relève pas silencieusement la version minimale du navigateur. Pour les fonctions facultatives, prévoyez une autre compilation ou un repli dans la page. Une note de compatibilité doit indiquer le parcours utilisateur testé, sans laisser entendre que le format garantit à lui seul le support dans tous les navigateurs.
Testez tout le parcours autour du module : chargement, instanciation, imports hôtes, entrées représentatives, interprétation du résultat et échecs attendus. Une instanciation réussie ne garantit pas un résultat acceptable pour l’utilisateur. De même, l’échec peut venir d’une conversion d’entrée ou de l’intégration hôte plutôt que d’une instruction WebAssembly manquante. Séparez ces cas dans la suite pour que la maintenance traite la bonne frontière.
Lorsque des nombres passent entre WebAssembly et JavaScript, définissez leur représentation et leur plage. Décidez si l’interface utilise des entiers, des nombres à virgule flottante, des tampons d’octets ou des enregistrements structurés, puis testez les conversions aux deux extrémités. La sérialisation et le stockage ajoutent leurs propres règles de représentation. Pour une comptabilité décimale exacte, choisissez une représentation adaptée et définissez l’arrondi à l’interface au lieu de dépendre d’un comportement fortuit d’un runtime.
Le repli fait partie de la compatibilité. Si une fonction requise manque, l’application peut choisir un module visant une base plus large, une solution limitée ou un message d’explication. Testez ce parcours avec les mêmes entrées et vérifiez qu’il ne perd pas le travail en cours. Si la précision du résultat ou la charge admise diffère, expliquez ce compromis. Un repli présent dans les sources mais inaccessible depuis la page déployée n’aide pas l’utilisateur.
L’interface publique du module doit aussi définir la mémoire et sa propriété. L’appelant doit savoir si un tampon est copié, emprunté pendant une opération limitée ou conservé ensuite selon l’interface utilisée. Documentez cette responsabilité afin que la page ne réutilise ni ne supprime les données pendant que le module en dépend. À la fin ou à l’annulation, libérez les références applicatives et rendez l’interface prête pour une autre tâche. Testez les usages répétés, pas seulement un appel réussi : certains problèmes de cycle de vie n’apparaissent qu’après plusieurs opérations.
L’interface publique du module doit rester assez stable pour que ses appelants traitent les erreurs. Définissez les échecs qui peuvent être renvoyés comme résultats ordinaires et ceux qui empêchent le module de continuer. La page doit les traduire en état récupérable au lieu de laisser un enregistrement à moitié modifié ou un contrôle désactivé. Ne faites pas d’une chaîne de message propre à un runtime le contrat de l’application. Utilisez la forme de retour documentée et la gestion d’état applicative, puis testez-les dans chaque navigateur pris en charge. L’implémentation peut ainsi évoluer sans lier la récupération visible à une formulation fortuite.
Comparer les versions du navigateur
Comparez une version candidate avec le même artefact, la même révision applicative, les mêmes imports, entrées et contexte de déploiement. Consignez la version et le résultat fonctionnel de chaque parcours requis. Si le module ou la suite change aussi, gardez l’ancien artefact et les attentes précédentes jusqu’à compréhension de l’écart. Changer plusieurs variables ensemble rend difficile l’attribution du résultat au navigateur, au compilateur, à l’application ou au test.
Séparez les preuves de correction de celles de performance. Un module plus lent peut satisfaire son contrat fonctionnel, et une exécution rapide ne prouve pas que son résultat soit correct. Si la réactivité compte pour les utilisateurs, mesurez une tâche applicative représentative et précisez la charge et l’environnement. Ne réutilisez pas la durée comme étiquette de navigateur ou d’appareil. L’ordonnancement, l’activité de fond, l’état d’alimentation et le runtime changent eux aussi le temps observé.
Lorsqu’un test change, réduisez-le à une petite entrée et consultez l’exigence pertinente de la spécification. Un comportement strictement défini et une opération qui permet une approximation appellent des interprétations différentes. Avant d’attribuer le résultat à une version du navigateur, vérifiez les conversions applicatives, les imports, les options de compilation et les données hôtes. Une reproduction réduite pose une question de compatibilité circonscrite, sans demander de données utilisateur ni d’inventaire sans rapport.
Appliquez la même discipline aux mises à jour du compilateur et à la livraison du module. Le compilateur peut changer le jeu de fonctions ou l’artefact sans que le navigateur change. Si l’application livre plusieurs variantes, testez leur sélection et la mise en cache afin que chaque environnement pris en charge reçoive le fichier voulu après déploiement. Réexaminez la plage de navigateurs supportés lorsque le produit évolue. Cette pratique complète la validation des versions du navigateur et reste distincte des signaux de timing du navigateur.
Les notes d’une mise à jour du module doivent décrire la tâche applicative concernée, tout changement du contrat d’entrée ou de sortie et la plage de navigateurs testée. Si les utilisateurs doivent actualiser un cache hors ligne ou reprendre une tâche interrompue, expliquez-le avant le déploiement. Les mainteneurs ont besoin de l’artefact et de sa provenance de compilation ; les utilisateurs doivent savoir si leur parcours et leurs données enregistrées sont concernés. Mettez à jour le relevé de compatibilité lorsque la plage prise en charge change et réexaminez-le si le module dépend d’une nouvelle fonction.
Avant d’élargir la plage prise en charge, définissez les versions du navigateur et fonctions du module que l’application s’engage à maintenir. Testez la base la plus ancienne et la version candidate, puis conservez les résultats avec les révisions du module et de l’application. Un déploiement limité peut commencer si le produit permet de comparer les résultats et de récupérer après un problème. Si le module change des données utiles à l’utilisateur, prévoyez une migration ou une nouvelle tentative claire. Ne retirez les anciennes variantes qu’une fois la politique de support et le cache compatibles avec le public visé. La maintenance suit ainsi un engagement explicite, et non le navigateur le plus récent de l’équipe de développement.
Sources publiques
- Spécification WebAssembly Core, version 2 : imports
- Spécification WebAssembly Core, version 2 : validation
- Spécification WebAssembly Core, version 2 : instanciation
- Spécification WebAssembly Core, version 2 : sections personnalisées
- MDN : WebAssembly.validate()
- MDN : WebAssembly.compile()
- MDN : WebAssembly.instantiate()
Articles Connexes
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.