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