WebAssembly ( Wasm ) определяет переносимый формат двоичного кода и соответствующий текстовый формат для исполняемых программ [2], а также программные интерфейсы для облегчения связи между такими программами и их хост-средой. [3] [4] [5] [6]
Основная цель WebAssembly — способствовать созданию высокопроизводительных приложений на веб-страницах , но он также разработан для использования в не-веб-средах. [7] Это открытый стандарт [8] [9], предназначенный для поддержки любого языка в любой операционной системе, [10] и на практике многие из самых популярных языков уже имеют по крайней мере некоторый уровень поддержки.
Анонсированный в 2015 году и впервые выпущенный в марте 2017 года , WebAssembly стал рекомендацией Консорциума Всемирной паутины 5 декабря 2019 года [11] [12] [13] и получил премию Programming Languages Software Award от ACM SIGPLAN в 2021 году. [14] Консорциум Всемирной паутины (W3C) поддерживает стандарт при участии Mozilla , Microsoft , Google , Apple , Fastly , Intel и Red Hat . [15] [16]
Название WebAssembly призвано казаться синонимом языка ассемблера . Название предполагает перенос ассемблероподобного программирования в Интернет , где оно будет выполняться на стороне клиента — компьютером пользователя веб-сайта через веб-браузер пользователя . Чтобы достичь этого, WebAssembly должен быть гораздо более аппаратно-независимым, чем настоящий язык ассемблера.
WebAssembly был впервые анонсирован в 2015 году [17], а первой демонстрацией стало выполнение Unity 's Angry Bots в Firefox , [18], Google Chrome , [19] и Microsoft Edge . [20] Предшественниками технологий были asm.js от Mozilla и Google Native Client , [21] [22] , а первоначальная реализация была основана на наборе функций asm.js. [23] Файл asm.js уже обеспечивает скорость выполнения кода, близкую к скорости выполнения нативного кода [24] [25], и может считаться жизнеспособной альтернативой для браузеров, которые не поддерживают WebAssembly или отключили его по соображениям безопасности.
В марте 2017 года было объявлено, что разработка минимально жизнеспособного продукта (MVP) завершена, а фаза предварительного просмотра завершена. [26] В конце сентября 2017 года Safari 11 был выпущен с поддержкой. В феврале 2018 года рабочая группа WebAssembly опубликовала три общедоступных рабочих проекта для Core Specification, JavaScript Interface и Web API. [27] [28] [29] [30]
В июне 2019 года был выпущен Chrome 75 с потоками WebAssembly, включенными по умолчанию. [31]
С апреля 2022 года [обновлять]WebAssembly 2.0 находился в стадии черновика [32] [33], в который было добавлено множество инструкций, связанных с SIMD , и новый тип данных v128 с возможностью функций возвращать несколько значений, а также инициализировать/копировать массовую память.
Хотя WebAssembly изначально был разработан для обеспечения скорости выполнения кода, близкой к скорости машинного кода в веб-браузере, он считался ценным и за его пределами, в более общих контекстах. [34] [35] Поскольку среды выполнения WebAssembly (RE) представляют собой низкоуровневые виртуальные стековые машины (похожие на JVM или Flash VM ), которые могут быть встроены в хост-приложения, некоторые реализации создают автономные среды выполнения, такие как Wasmtime и Wasmer . [9] [10] Среды выполнения WebAssembly встроены в серверы приложений для размещения «серверных» приложений WebAssembly и в другие приложения для поддержки архитектур расширений программного обеспечения на основе подключаемых модулей , например, «WebAssembly для прокси» (proxy-wasm), которая определяет ABI на основе WebAssembly для расширения прокси-серверов . [36] [37]
В ноябре 2017 года Mozilla заявила о поддержке «во всех основных браузерах» [38] после того, как WebAssembly был включен по умолчанию в Edge 16. [39] Эта поддержка также включает мобильные веб-браузеры для iOS и Android. По состоянию на март 2024 года [обновлять]99% отслеживаемых веб-браузеров поддерживают WebAssembly (версия 1.0), [40] больше, чем для его предшественника asm.js. [ 41] Для некоторых расширений из проекта стандарта 2.0 поддержка может быть ниже, но все равно более 90% веб-браузеров могут уже поддерживать, например, для расширения ссылочных типов. [42]
Реализации WebAssembly обычно используют либо компиляцию до начала (AOT), либо компиляцию точно в срок (JIT), но также могут использовать интерпретатор . Хотя первые реализации появились в веб-браузерах , существуют также небраузерные реализации для общего назначения, включая Wasmer, [10] Wasmtime [43] или WAMR, [16] wasm3, WAVM и многие другие. [44]
Поскольку исполняемые файлы WebAssembly предварительно скомпилированы, для их создания можно использовать различные языки программирования. [45] Это достигается либо путем прямой компиляции в Wasm, либо путем реализации соответствующих виртуальных машин в Wasm. Сообщается, что около 40 языков программирования поддерживают Wasm в качестве цели компиляции. [46]
Emscripten компилирует C и C++ в Wasm [26], используя Binaryen и LLVM в качестве бэкэнда. [47] Emscripten SDK может компилировать исходный код любого языка, поддерживаемого LLVM (например , C , C++ или Rust и т. д.), в двоичный файл, который запускается в той же «песочнице», что и код JavaScript. [примечание 1] Emscripten предоставляет привязки для нескольких часто используемых интерфейсов среды, таких как WebGL .
Начиная с версии 8, автономный Clang может компилировать C и C++ в Wasm. [52] Первоначальной целью была поддержка компиляции из C и C++ , [53] хотя также появляется поддержка других исходных языков, таких как Rust , языки .NET [54] [55] [46] и AssemblyScript [56] ( подобные TypeScript ).
После выпуска MVP WebAssembly добавил поддержку многопоточности и сборки мусора , [57] что позволило более эффективно компилировать языки программирования со сборкой мусора, такие как C# (поддерживается через Blazor ), F# (поддерживается через Bolero [58] с помощью Blazor) и Python . [59]
Некоторые другие языки имеют некоторую поддержку, включая Python , [60] Julia , [61] [62] [63] Ruby [64] и Ring . [65] [66]
Ряд систем могут компилировать Java и другие языки JVM в JavaScript и WebAssembly. К ним относятся CheerpJ, [67] JWebAssembly [68] и TeaVM. [69] Kotlin напрямую поддерживает WebAssembly. [70] [71]
Веб-браузеры не позволяют коду WebAssembly напрямую манипулировать Document Object Model . Для этого код Wasm должен подчиняться JavaScript . [примечание 2]
В опросе разработчиков, проведенном в октябре 2023 года, менее половины из 303 участников были удовлетворены состоянием WebAssembly. Подавляющее большинство указало на необходимость улучшения в четырех областях: WASI, поддержка отладки, интеграция с JavaScript и API браузера, а также инструменты сборки. [74]
Для интенсивного выделения памяти в WebAssembly существуют «серьезные ограничения, которые делают невозможным надежное развертывание многих приложений в мобильных браузерах [...] В настоящее время выделение более ~300 МБ памяти не является надежным ни в Chrome на Android без использования специфичных для Chrome обходных путей, ни в Safari на iOS». [75]
Все основные браузеры разрешают WebAssembly, если Content-Security-Policy не указана или если используется «unsafe-eval», но в противном случае ведут себя по-разному. [76] Chrome требует «unsafe-eval», [77] [78] хотя рабочий поток может быть обходным решением. [78]
В июне 2018 года исследователь безопасности представил возможность использования WebAssembly для обхода браузерных мер по смягчению уязвимостей Spectre и Meltdown после добавления поддержки потоков с общей памятью. Из-за этой проблемы разработчики WebAssembly приостановили эту функцию. [79] [80] [81] Однако для того, чтобы исследовать эти будущие расширения языка, Google Chrome добавил экспериментальную поддержку предложения потоков WebAssembly в октябре 2018 года. [82]
WebAssembly подвергался критике за то, что позволял разработчикам вредоносного ПО , мошенникам и фишинговым атакам с большей легкостью скрывать улики; WebAssembly присутствует на компьютере пользователя только в скомпилированной форме, что «[затрудняет] обнаружение вредоносного ПО». [83] Скорость и легкая возможность сокрытия в WebAssembly привели к его использованию для скрытого майнинга криптовалют на устройстве посетителя веб-сайта. [83] [84] [79] Coinhive , ныне несуществующий сервис, облегчающий майнинг криптовалют в браузерах посетителей веб-сайта, утверждает, что их «майнер использует WebAssembly и работает примерно с 65% производительности собственного майнера». [79] Исследование, проведенное в июне 2019 года Техническим университетом Брауншвейга, проанализировало использование WebAssembly на 1 миллионе лучших веб-сайтов Alexa и обнаружило, что преобладающим использованием был вредоносный майнинг криптовалюты, и что вредоносное ПО составляло более половины исследованных веб-сайтов, использующих WebAssembly. [85] [86] Исследование, проведенное в апреле 2021 года Университетом Штутгарта, показало, что с тех пор майнинг криптовалюты был отодвинут на второй план, упав до менее 1% всех модулей WebAssembly, собранных из широкого спектра источников, включая также 1 миллион лучших веб-сайтов Alexa. [87]
Поскольку WebAssembly поддерживает только структурированный поток управления , он пригоден для методов проверки безопасности, включая символическое выполнение . [88]
WebAssembly System Interface (WASI) — это простой интерфейс ( ABI и API ), разработанный Mozilla и предназначенный для переносимости на любую платформу. [89] Он предоставляет функции, подобные POSIX , такие как файловый ввод-вывод, ограниченный безопасностью на основе возможностей . [90] [91] Существуют дополнительные предлагаемые ABI/API. [92] [93]
На WASI повлияли CloudABI и Capsicum . [ по мнению кого? ]
Соломон Хайкс, соучредитель Docker , написал в 2019 году: «Если бы WASM+WASI существовал в 2008 году, нам не пришлось бы создавать Docker. Вот насколько он важен. WebAssembly на сервере — это будущее вычислений». [94]
Общий стандарт содержит основные спецификации для JavaScript API и сведения о внедрении. [5]
Код Wasm (двоичный код, т. е. байт-код) предназначен для запуска на портативной виртуальной стековой машине (ВМ). [95] ВМ разработана для более быстрого анализа и выполнения, чем JavaScript, и для компактного представления кода. [53] Любая внешняя функциональность (например, системные вызовы ), которая может ожидаться двоичным кодом Wasm, не предусмотрена стандартом. Он скорее предоставляет способ предоставления интерфейса через модули хост-средой, в которой работает ВМ. [96] [9]
Программа Wasm разработана как отдельный модуль, содержащий наборы различных значений, определенных Wasm, и определений типов программ. Они предоставляются в двоичном или текстовом формате (см. ниже), которые имеют общую структуру. [97] Такой модуль может предоставлять функцию запуска, которая выполняется при создании экземпляра двоичного файла wasm.
Основной стандарт для двоичного формата программы Wasm определяет архитектуру набора инструкций (ISA), состоящую из определенных двоичных кодировок типов операций, которые выполняются виртуальной машиной (без указания того, как именно они должны выполняться). [98] Список инструкций включает стандартные инструкции загрузки/сохранения памяти, числовые, параметрические, инструкции управления потоком и инструкции переменных, специфичные для Wasm. [99]
Количество опкодов, используемых в исходном стандарте (MVP), было немного меньше 200 из 256 возможных опкодов. Последующие версии WebAssembly увеличили количество опкодов немного больше 200. Предложение WebAssembly SIMD (для параллельной обработки) вводит альтернативный префикс опкода (0xfd) для 128-битного SIMD. Конкатенация префикса SIMD и опкода, который допустим после префикса SIMD, образует опкод SIMD. Опкоды SIMD приносят дополнительные 236 инструкций для возможности SIMD «минимально жизнеспособного продукта» (MVP) (всего около 436 инструкций). [100] [101] Эти инструкции, «завершенные коды операций» [102], включены по умолчанию в Google V8 (в Google Chrome), движке SpiderMonkey в Mozilla Firefox и движке JavaScriptCore в Safari от Apple [103] , а также есть некоторые дополнительные предложения по инструкциям для более позднего «post SIMD MVP», и есть также отдельное предложение «relaxed-simd» на рассмотрении. [104]
Эти коды операций SIMD также переносимы и транслируются в собственные наборы инструкций, такие как x64 и ARM. Напротив, ни JVM Java , ни CIL не поддерживают SIMD на уровне кодов операций , т. е. в стандарте; оба имеют некоторые параллельные API, которые обеспечивают ускорение SIMD. Существует расширение для Java, добавляющее встроенные функции для x64 SIMD, [105] , которое непереносимо, т. е. не может использоваться на ARM или смартфонах. Смартфоны могут поддерживать SIMD, вызывая ассемблерный код с SIMD, и C# имеет аналогичную поддержку.
В марте 2017 года группа сообщества WebAssembly достигла консенсуса по первоначальному (MVP) двоичному формату, JavaScript API и эталонному интерпретатору. [106] Она определяет двоичный формат WebAssembly ( .wasm
), который не предназначен для использования людьми, а также понятный человеку текстовый формат WebAssembly ( .wat
), который напоминает нечто среднее между S-выражениями и традиционными языками ассемблера.
В таблице ниже показан пример функции факториала , написанной на языке C , и соответствующий ей код WebAssembly после компиляции, представленный как в текстовом формате .wat (текстовое представление WebAssembly, понятное человеку), так и в двоичном формате .wasm (необработанный байт-код , представленный ниже в шестнадцатеричном виде ), который выполняется веб-браузером или средой выполнения, поддерживающей WebAssembly.
Все целочисленные константы кодируются с использованием кодировки LEB128 переменной длины, которая экономит место . [107]
Текстовый формат WebAssembly более канонически записан в свернутом формате с использованием S-выражений . Для инструкций и выражений этот формат является чисто синтаксическим сахаром и не имеет поведенческих различий с линейным форматом. [108] С помощью wasm2wat
код выше декомпилируется в:
( module ( type $t0 ( func ( param i64 ) ( result i64 ))) ( func $f0 ( type $t0 ) ( param $p0 i64 ) ( result i64 ) ( if $I0 ( result i64 ) ;; $I0 — неиспользуемое имя метки ( i64.eqz ( local.get $p0 )) ;; имя $p0 здесь такое же, как 0 ( then ( i64.const 1 )) ( else ( i64.mul ( local.get $p0 ) ( call $f0 ;; имя $f0 здесь такое же, как 0 ( i64.sub ( local.get $p0 ) ( i64.const 1 ))))))))
Модуль неявно генерируется компилятором. Функция ссылается на запись таблицы типов в двоичном файле, отсюда раздел типов и type
выдаваемый декомпилятором. [109] Компилятор и декомпилятор могут быть доступны онлайн. [110]
.wasm
файлов, которые затем могут быть выполнены в веб-браузере. [48] [49] [50] Несмотря на то, что Emscripten может использовать различные языки при использовании Clang , могут возникнуть некоторые проблемы. [51]WebAssembly можно считать структурированной стековой машиной ; машиной, в которой большинство вычислений используют стек значений, но поток управления выражается в структурированных конструкциях, таких как блоки, if и циклы. На практике реализации не должны поддерживать фактический стек значений или фактические структуры данных для управления; им нужно только вести себя так, как если бы они это делали.
— это открытый стандарт...
— это ... формат кода
WebAssembly — это язык программирования, имеющий несколько конкретных представлений (двоичный формат и текстовый формат). Оба соответствуют общей структуре.
эта спецификация дополнена дополнительными документами, определяющими интерфейсы для конкретных сред встраивания, таких как Web. Каждый из них будет определять интерфейс прикладного программирования (API) WebAssembly, подходящий для данной среды.
Его главная цель — обеспечить высокопроизводительные приложения в Интернете, но он не делает никаких предположений, специфичных для Интернета, и не предоставляет специфичных для Интернета функций, поэтому его можно использовать и в других средах.
Хотя Интернет является основной мотивацией для WebAssembly, ничто в его конструкции не зависит от Интернета или среды JavaScript. Это открытый стандарт, специально разработанный для встраивания в несколько контекстов, и мы ожидаем, что в будущем появятся автономные реализации.
Скомпилируйте все в WebAssembly. Запустите его на любой ОС или встройте в другие языки.
если отбросить единственный результат, где asm.js показал себя лучше, он выполняется примерно на 70% от скорости собственного кода C++.
{{cite book}}
: CS1 maint: несколько имен: список авторов ( ссылка )Цель этого крейта — предоставить привязки Rust к веб-API и обеспечить высокую степень взаимодействия между Rust и JavaScript.
привязки API для веб-API. Это процедурно сгенерированный контейнер из браузера WebIDL, который обеспечивает привязку ко всем API, которые браузер предоставляет в сети.
В этой статье использован текст из свободного контента . Лицензия Apache License 2.0 (лицензионное заявление/разрешение). Текст взят из Text Format, jfbastien; rossberg-chromium; kripken; titzer; s3ththompson; sunfishcode; lukewagner; flagxor; enricobacis; c3d; binji; andrewosh, GitHub. WebAssembly/design.