## FAQ мигрировал на https://github.com/WebAssembly-Enthusiasts/info/blob/master/FAQ/ru.md ### Введение Данный FAQ был специально создан для телеграм сообщества https://t.me/WebAssembly_ru. Он базируется на [статье от Andre Weissflog](https://floooh.github.io/2017/06/09/webassembly-demystified.html), но так же содержит множество моих дополнений и мыслей, которые могут быть уже не слишком актуальны на момент прочтения. Прошу это учитывать. ### 0. Какие цели у WebAssembly? - Определение переносимого двоичного формата с эффективным размером и временем загрузки, который будет служить целью компиляции и выполняться с предсказуемой скоростью и детерменированным поведением в рамках среды выполнения; - Позволить портирование и исполнение в web уже имеющегося кода отличного от JavaScript; - При всем этом не нарушая целостности уже существующей веб-экосистемы. ### 1. WebAssembly это нативный код CPU? **Нет!** WebAssembly - это цель компиляции и промежуточный формат, который скорее похож на байткод в .NET, LLVM IR или Java, нежели нативный машинный код. Если вам не нравится ассоциации с .NET или Java-байткодом, то по-другому это можно представить себе как некий портативный набор инструкций для виртуального процессора (ISA). ### 2. WebAssembly это ассемблерный код? **Нет!** "ассемблерный код" обычно означает текстовое представление определенного набора команд центрального процессора. WebAssembly в своей типичной форме не является ни текстовым представлением, ни специфичным для процессора бинарным представлением, хотя спецификация WASM определяет и текстовое представление имеющие одно из расширений: `.wat` или `.wast`. Безусловно вы можете писать код используя wat синтаксис и собирать его в бинарный модуль с помощью [wat2wasm](https://webassembly.github.io/wabt/demo/wat2wasm/), но это стоит делать лишь в академических целях или для изучения новых возможностей, недоступных пока в компиляторах высокого уровня. В действительности, WebAssembly - это цель компиляции, так же как и нативный код для x86 или ARM. ### 3. WebAssembly это очередной "Java Applets"/ActiveX/Flash/Silverlight? **Нет!** WebAssembly отличается от Java-апплетов тем, что он использует существующие части виртуальной машины JavaScript и ее среду изоляции (sandbox), вместо добавления другой громоздкой виртуальной машины посредством плагинов или расширений и тем самым снижая надежность и безопасность системы в целом. WebAssembly также **не позволяет** вызывать нативный код или системные вызовы напрямую, минуя слои безопасности самого браузера или другой виртуальной машины, как это делали Flash или Java-апплеты (через JNI). Плагины ActiveX были встроенными библиотеками нативного кода, в которых безопасность строилась на доверии к третьей стороне. Для WebAssembly доверие возлагается исключительно на производителя самого браузера и только на него. Кроме того, большинство этих плагинов имели свои виртуальные машины, которые создавались для конкретных языков. Например, Java Applets - для Java, Flash - для ActionScript, Silverlight - для C#. WebAssembly же - это унивирсальная виртуальная машина c открытым стандартом, готовая принять в свои объятия любой язык, будь то Haskell, PHP или TypeScript. ### 4. WebAssembly это угроза для безопасности? Надо ли опасаться вирусов? **Нет!** Если только вы не считаете JavaScript угрозой безопасности для браузера =) WebAssembly примерно так же безопасен, как и JavaScript, поскольку он работает в той же песочнице. Типичные реализации WebAssembly только добавляют довольно небольшой модуль синтаксического анализа и загрузчика к существующему JavaScript движку. Например, в WebKit, WebAssembly, составляет всего около 10 тыс строк из 432 тыс строк кода для всего движка JavaScriptCore. Таким образом, всего лишь ~2% от всего JavaScript-движка - это новая поверхность атаки, специфичная для WebAssembly. Кроме того, WebAssembly не позволяет напрямую обращаться к Web API или любому другому внешнему интерфейсу системы без явного импорта внутри WebAssembly сборки и некоторого "склеивающего кода" со стороны хоста. ### 5. Могу ли я вызывать tcp-сокеты/операции ввода-вывода/DOM/WebGL и другие API браузера или ОС из под WebAssembly напрямую? **Нет!** WebAssembly работает внутри изолированной программной среды браузера или другой VM и может получать доступ только к веб-API только косвенно через JavaScript. Однако emscripten SDK (C++) и web-sys (Rust) предоставляют обертки для многих распространенных API, что упрощает перенос существующего кода C / C++ / Rust (например, конвертировать TcpSockets-в-WebSockets, OpenGL-в-WebGL, OpenAL-в-WebAudio и т.д.). В дальнейшем, когда будет реализован [interface-types (webidl-bindings) proposal](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md) всеми браузерами, всего вышеперечисленного не потребуется, и можно будет обращаться непосредственно к Web API или любому другому интерфейсу (в случае со standalone VM) непосредственно через WebIDL а так же [WASI](https://gist.github.com/MaxGraey/326b1c04d66de3beb247c2c1e6358fd0#14-%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-wasi) интерфейс. ### 6. Могу ли я загрузить или создать нативную DLL-библиотеку в WebAssembly? **Нет!** Динамические библиотеки, которые используются в операционной системе являются машинным кодом и, следовательно, не будут работать (без эмуляции соответсвуюшего процессора). Стоит так же заметить, что Blazor, может действительно загружать файлы с расширением `.dll` в браузере, но это CIL-библиотеки Mono-рантайма которые выполняются в режиме интерпретации. В то же время WebAssembly будет поддерживать динамическую линковку между Wasm-модулями, что позволит повторно использовать модули совместно используемого кода (идея состоит в том, чтобы уменьшить размер загрузки, перемещая общий код в отдельный модуль, который может быть впоследствии закэширован). ### 7. Могу ли я запустить программу или отдельный процесс из WebAssembly? **Нет!** По той же причине, почему нельзя загружать DLL. ### 8. Можно ли использовать WebAssembly для обхода блокировщиков рекламы? **Нет!** WebAssembly может делать только то, что и JavaScript. Даже если реклама не загружает изображения, а отображает ее контент "процедурно" с помощью кода WebAssembly, сам WebAssembly-модуль должен быть сперва загружен с какого-либо адреса (обычно это сервер рекламной сети), и это может быть перехвачено и заблокировано Ad-блокерами. ### …но я ведь не могу посмотреть исходный код?! Это уже стало давно проблематично даже для JavaScript, с тех пор как все начали использовать минификаторы и обфускаторы. Тем не менее, большинство браузеров сейчас умеют отображать wasm-модули в текстовом представлении, что порой куда более понятней, чем минифицированный и обфусцированный JavaScript-код. Кроме того, браузеры и инструменты сборки давно уже поддерживают source maps для WebAssembly и ведутся работы над поддержкой [DWARF](https://en.wikipedia.org/wiki/DWARF) секций что позволит делать полноценную символьную отладку. ### 9. WebAssembly это раздолье для криптомайнеров? Могу ли я запретить WebAssembly в своем браузере? **Нет!** Вы не сможете запретить исполняться WebAssembly если только не запретите исполнение самого JavaScript в браузере. Насчет майнеров. Первые криптовалютные майнеры в браузере появились еще в 2012 году, задолго до WebAssembly или asm.js и использовали новую тогда технолугию WebGL 1.0 (точнее GLSL язык) и конечно же JavaScript. После этого были майнеры использующие asm.js и некоторые из них используют его до сих пор, если ваш браузер не поддерживает WebAssembly. Стало быть WebAssembly ни в коей мере не является главным инициатором активности браузерных майнеров. На данный момент производители браузеров стремяться мониторить активность скриптов и автоматически блокировать такие майнеры, но пока не слишком успешно. Также в этом немного помогают блокировщики рекламы. ### 10. Я простой frontend-разработчик, выходит мне теперь необходимо изучать C++ или Rust? **Нет!** Одно из важных преимуществ WebAssembly - это создание сборок, которые можно вызывать из JavaScript. Исполняющий код (например, манипуляции с изображениями, игры, физические и графические движки, криптография и т.д.) может быть реализован в виде модулей WebAssembly, но при этом вызываться из-под JavaScript. Использование такого WebAssembly-модуля не будет сильно отличаться от использования обычной JavaScript-библиотеки, вы зачастую даже не будете об этом подозревать. Так что написание тех частей приложения, которые впоследствии будут компилироваться в wasm-модуль можно поручить системным разработчикам, уже знакомыми с одним из таких языков. Кроме того, активно развивается TypeScript-подобный язык [AssemblyScript](https://github.com/AssemblyScript/assemblyscript) способный производить WebAssembly-модуль и с которым большинство JavaScript/TypeScript разработчиков будут себя чувствовать в комфортной и знакомой среде. Полный список языков, поддерживающих WebAssembly можно посмотреть [здесь](https://github.com/appcypher/awesome-wasm-langs#contents). ### 11. Может ли WebAssembly манипулировать DOM? Мы уже частично затронули этот вопрос. И здесь мы имеем неоднозначный ответ - и да, и нет. WebAssembly не может получить прямой доступ к DOM, но может вызывать вспомогательный код на JavaScript, и этот код уже может предоставлять доступ к DOM. В emscripten это так же просто, как прямое встраивание кода JavaScript в код C++. Но такое взаимодействие между WebAssembly и JavaScript налагает дополнительные расходы. В последнее время браузеры стремятся сократить время этого взаимодействия, но если для простых типов это осуществимо, то ссылочные типы по-прежнему требуют структурное клонирование и дополнительные затраты на сериализацию и десереализацию в случае со структурами или объектами. Может возникнуть очень заманчивая идея создать свою реактивную библиотеку работы с DOM (или реализовать лишь diff-алгоритм для Virtual DOM) например для Rust, С++ или Go. [Не делайте этого](https://stackoverflow.com/questions/59015066/using-rustwebassembly-for-web-development-how-to-solve-the-extra-cost-of-wasm)! По крайней мере пока. Как показывает опыт таких экспериментальных библиотек как yew и asm-dom это зачастую медленее даже самых медлительных JavaScript-библиотек или фреймворков, не говоря уже о непосредственной работе с vanilla DOM без дополнительных абстракций. ### 12. WebAssembly бесполезен для языков требующих Сборщик Мусора (GC)? И да, и нет. Текущая MVP версия WebAssembly не предпологает встроенный сборщик мусора, тем самым ограничивая языки с наличием таковых, но это не мешает таким языкам как C#, Go, Java или Kotlin включать их в сборку вместе с остальным рантаймом, что они и делают. Безусловно это увеличивает размер wasm-модуля в сравнении с Rust или C++, которые не требуют GC. Кроме того существует предложение для расширения MVP включающее [Сборщик Мусора](https://github.com/WebAssembly/gc/blob/master/proposals/gc/Overview.md) и над которым сейчас активно работают основные производители браузеров. ### 13. WebAssembly существенно ускоряет код по сравнению с аналогичным, но на JavaScript? И да, и нет. Это зависит от нескольких факторов: - от выбора языка/компилятора и его настроек; - от текущих задач, которые вы стремитесь решить. Как мы уже выяснили манипуляции с DOM у WebAssembly явно не будут быстрее. Зато игры, криптография, эмуляторы, CAD-системы, DSP, кодирование/декодирование мультимедиа определенно да! Особенно если учесть, что в будущем WebAssembly будет поддерживать SIMD-комманды недоступные для JavaScript и уже поддерживает (пока только Chrome) атомарные инструкции и потоки, работающие с разделяемой памятью [SharedArrayBuffer](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer); - от того, как часто вы вызываете методы хоста (Web API) из под WebAssembly или экспортируемые методы wasm на стороне хоста; - и наконец, от [скорости оптимизирующих AOT/JIT-компиляторов](https://00f.net/2019/10/22/updated-webassembly-benchmark/) самих виртуальных машин. ### 14. Что такое WASI? Префикс "Web" в названии WebAssembly может навести на мысль, что эта технология создавалась исключительно для веба, но это не так. На данный момент уже существует огромное множество [standalone рантаймов для WebAssembly](https://github.com/appcypher/awesome-wasm-runtimes#webassembly-runtimes) способные исполнять wasm не в самом браузере а непосредственно в ОС или в нативном приложении. WASI (WebAssembly System Interface) - это проект ABI от Mozilla, который определяет стандартизированный интерфейс взаимодействия ОС с wasm-модулем (такой себе POSIX только для wasm). WASI дает возможность получить доступ к таким функциям как файловая система, сетевые сокеты, таймеры и генераторы случайных чисел. Развитие ABI предполагает независимость от браузера, JavaScript и WebAPI. При этом проект обеспечивает надлежащий уровень изоляции от основной системы и позволяет определять полномочия приложения в стиле CloudABI и Capsicum. Файлы, каталоги, сокеты и другие ресурсы ассоциируются со специальным типом файловых дескрипторов, а для взаимодействия с каждым из ресурсов приложения должен иметь полномочия. Последние обрабатываются иерархически, то есть доступ к каталогу автоматически открывает и доступ ко всем файлам в нем. Кроме того существует polyfill WASI для браузеров и готовиться для node.js. Все это дает возможность писать модули с единым интерефейсом как для десктопных так и для браузерных приложений. Стоит также отметить, что на данном этапе это довольно базовая спецификация, не описывающая пока криптографию, API для работы с GPU, асинхронный I/O, TLS и т.д. кроме работы с процессами, так что IPC и fork не планируются. ### 15. WebAssembly это конец гегемонии и смерть JavaScript? **Нет!** Определенно нет! При всех очевидных преимуществах WebAssembly будет слишком смело ожидать, что то огромное колличество библиотек, фреймворков и инструментов уже созданных для JavaScript экосистемы вдруг начнет переписываться на Rust, C++ или любой другой поддерживающий wasm язык, а огромная армия frontend-разработчиков незамедлительно ринется осваивать системное програмирование и соответствующие ему языки, особенно, если учесть, что в этой области порог вхождения несопостовимо выше чем у JavaScript. Кроме того, как мы уже выяснили далеко не для всех задач WebAssembly целесообразен. Языку Cи уже почти 50 лет и за это время возникло довольно много его надмножеств и прямых конкурентов, которые должны были покончить с ним, но как мы [видим](https://github.blog/2018-11-15-state-of-the-octoverse-top-programming-languages/) этого не произошло и он до сих пор остается в десятке наиболее часто используемых языков. Еще одна важная особенность JavaScript состоит в том, что это интерпретируемый динамичный язык, поддерживающий очень многие функции полностью или частично недоступные языкам с AOT-компиляцией. Например, в игровой индустрии по-прежнему очень популярны Lua, JS, Python которые используются для описания скриптовых сцен да и игровой механики в целом. Кроме того, JavaScript давно вышел за пределы браузера и используется для бэкенда (node.js, deno), мобильной разработки (ReactNative, NativeScript, Cordova) и даже для программирования логики встраиваемых (IoT) устройств. Будем надеяться и WebAssembly постигнет такой же успех! #### Полезные ресурсы - https://webassembly.github.io/spec/core - https://github.com/WebAssembly/proposals - https://github.com/mbasso/awesome-wasm - https://github.com/appcypher/awesome-wasm-langs#awesome-webassembly-languages- - https://github.com/appcypher/awesome-wasm-runtimes#awesome-webassembly-runtimes- - https://hacks.mozilla.org/author/lclarkmozilla-com - https://madewithwebassembly.com - https://wasmbyexample.dev - https://webassembly.studio #### Автор - Max Graey @ 2020 - Telegram: @maxgraey - Twitter: https://twitter.com/MaxGraey