До 30 ноября

Скидки до 81 000 руб и вторая профессия в подарок!

Главная | Все статьи | Код

Введение в интерфейсы WebAssembly

Время чтения статьи ~7 минут
Введение в интерфейсы WebAssembly главное изображение

WebAssembly — портируемый бинарный формат. Это значит, что один и тот же файл может быть запущен везде. Но каждая платформа, на которой мы захотим запускать этот самый «один и тот же файл», должна уметь выполнять Wasm-код — и делать это максимально быстро и максимально безопасно.

Wasmer — это среда исполнения WebAssembly, написанная на Rust. И среда эта — встраиваемая. Она может быть включена в состав программ на Rust, а ещё её можно подключить из других языков: PHP (php-ext-wasm), Python (PyPI:wasmer), Ruby (Gem:wasmer) и других.

Wasmer полностью сфокусирован на запуске модулей WebAssembly на стороне сервера. Мы начинали с запуска сгенерированных с помощью Emscripten модулей, но постепенно добавляли поддержку других ABI (application binary interface, двоичный интерфейс приложений) — WASI, Wascap и так далее.

Вы можете запускать разные программы с каждым ABI, например, Nginx (Emscripten) и Cowsay (WASI).

Со временем мы поняли, что среда исполнения выполняла много проверок перед запуском экземпляра приложения, чтобы убедиться, что модуль совместим с определенным ABI (Emscripen или WASI). Это означает проверку соответствия импортов и экспортов модуля ожиданиям среды. Например, речь идёт о проверке сигнатур функций или совпадении глобальных типов.

Оказывается, эти проверки важны не только потому, что позволяют убедиться в совместимости модуля со средой исполнения. Они также полезны тем, что позволяют убедиться в совместимости модуля с конкретным API.

Это может быть ключом к созданию экосистемы плагинов для любой программы, использующей WebAssembly как часть системы плагинов, в которой каждый модуль должен быть совместимым с определённым интерфейсом, например, с заголовочными файлами в C.

С помощью интерфейсов WebAssembly и WAPM (WebAssembly Package Manager) вы можете легко использовать всю экосистему WAPM для создания, верификации и распространения плагинов.

Поэтому мы решили поработать над способами проверки и предложить их как стандарт определения наборов импортов и экспортов, которые должны быть в модуле.

Покажите мне интерфейсы Wasm

Интерфейсы WebAssembly созданы под влияением ЛИСП-подобного текстового формата Wasm. Мы намеренно настаивали, чтобы формат не зависел от будущих предложений, так как хотели, чтобы интерфейсы были близки к внутренним форматам Wasm (только четыре типа: i32, i64, f32, f64).

Ниже представлены интерфейсы WebAssembly для WASI:


(interface "wasi_unstable"

  ;; Функции импорта

  (func (import "wasi_unstable" "args_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "args_sizes_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "clock_res_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "clock_time_get") (param i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "environ_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "environ_sizes_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_advise") (param i32 i64 i64 i32) (result i32))

  (func (import "wasi_unstable" "fd_allocate") (param i32 i64 i64) (result i32))

  (func (import "wasi_unstable" "fd_close") (param i32) (result i32))

  (func (import "wasi_unstable" "fd_datasync") (param i32) (result i32))

  (func (import "wasi_unstable" "fd_fdstat_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_fdstat_set_flags") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_fdstat_set_rights") (param i32 i64 i64) (result i32))

  (func (import "wasi_unstable" "fd_filestat_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_filestat_set_size") (param i32 i64) (result i32))

  (func (import "wasi_unstable" "fd_filestat_set_times") (param i32 i64 i64 i32) (result i32))

  (func (import "wasi_unstable" "fd_pread") (param i32 i32 i32 i64 i32) (result i32))

  (func (import "wasi_unstable" "fd_prestat_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_prestat_dir_name") (param i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_pwrite") (param i32 i32 i32 i64 i32) (result i32))

  (func (import "wasi_unstable" "fd_read") (param i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_readdir") (param i32 i32 i32 i64 i32) (result i32))

  (func (import "wasi_unstable" "fd_renumber") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_seek") (param i32 i64 i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_sync") (param i32) (result i32))

  (func (import "wasi_unstable" "fd_tell") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "fd_write") (param i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_create_directory") (param i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_filestat_get") (param i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_filestat_set_times") (param i32 i32 i32 i32 i64 i64 i32) (result i32))

  (func (import "wasi_unstable" "path_link") (param i32 i32 i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_open") (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_readlink") (param i32 i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_remove_directory") (param i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_rename") (param i32 i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_symlink") (param i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "path_unlink_file") (param i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "poll_oneoff") (param i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "proc_exit") (param i32))

  (func (import "wasi_unstable" "proc_raise") (param i32) (result i32))

  (func (import "wasi_unstable" "random_get") (param i32 i32) (result i32))

  (func (import "wasi_unstable" "sched_yield") (result i32))

  (func (import "wasi_unstable" "sock_recv") (param i32 i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "sock_send") (param i32 i32 i32 i32 i32) (result i32))

  (func (import "wasi_unstable" "sock_shutdown") (param i32 i32) (result i32))

)

Это значит, что модуль, в котором реализуется интерфейс WASI, должен быть совместимым с представленными сигнатурами.

Как использовать интерфейсы Wasm

Некоторые проекты уже используют представленный синтаксис для определения модулей WebAssembly. Пионером интеграции интерфейсов Wasm стал WAPM.

Если вы используете wapm cli, модули будут автоматически проверяться с помощью имеющегося интерфейса перед публикацией в реестре. Так мы убеждаемся в совместимости новых модулей с ABI, которые они призваны реализовывать.

В настоящее время в WAPM доступны такие интерфейсы:

  • WASI. Это модульный системный интерфейс Wasm (WASI — WebAssembly System Interface). Он сфокусирован на безопасности и портативности.
  • Wascap. Это набор стандартов и соглашений, которые заполняют пробел в облачной среде модулей Wasm.

Ручная проверка интерфейса модуля

Когда вы используете WAPM и поле interfaces в кофигурациях, мы проверяем модуль на совместимость с интерфейсом. Также мы создали бинарный файл wasm-interface, который доступен на WAPM:

wapm install -g wasm-interface
# Run the checks
wasm-interface --dir=. check wasi-module.wasm -i interface.wai

Автоматическая проверка интерфейсов для модуля с помощью WAPM

Публиковать модули для WASI или Wascap очень просто. Убедитесь, что используете последнюю версию wasmer и wapm с помощью команды wasmer self-update.

Отредактируйте файл wapm.toml и добавьте секцию [module.interfaces]:

[package]
name = "example-cli"
version = "0.0.1"
description = "An example WASI cli app"
repository = "https://github.com/wapm-packages/example-cli"
homepage = "https://github.com/wapm-packages/example-cli"

[[module]]
name = "example-cli"
source = "example-cli.wasm"

[module.interfaces]

# We indicate this module uses the WASI interface here

wasi = "0.0.0-unstable"

интерфейс

Как только вы добавите новый интерфейс в модуль и опубликуете его на WAPM, он появится в UI. Смотрите тег WASI рядом с названием.

Как создать новый интерфейс с помощью WAPM

Скоро каждый желающий сможет создавать новые интерфейсы WebAssembly на WAPM. Мы решили начать с ручного создания новых интерфейсов, чтобы ускорить итерации при необходимости небольших изменений синтаксиса.

Адаптированный перевод статьи Introducing WebAssembly Interfaces by Syrus Akbary. Мнение автора оригинальной публикации может не совпадать с мнением администрации «Хекслета».

Аватар пользователя Дмитрий Дементий
Дмитрий Дементий 14 октября 2019
0
Рекомендуемые программы
профессия
Осваивайте разработку веб-страниц, оживляйте дизайн макетов, публикуйте сайты и приложения. Отслеживайте ошибки в интерфейсе и устраняйте их
10 месяцев
с нуля
Старт 28 ноября
профессия
Обучитесь разработке бэкенда сайтов и веб-приложений — серверной части, которая отвечает за логику и базы данных
10 месяцев
с нуля
Старт 28 ноября
профессия
Выполняйте ручное тестирование веб-приложений, находите ошибки в продукте. Узнайте все о тест-дизайне.
4 месяца
с нуля
Старт 28 ноября
профессия
Научитесь разработке веб-приложений, сайтов и программного обеспечения на языке Java, программируйте и используйте структуры данных
10 месяцев
с нуля
Старт 28 ноября
профессия
новый
Собирайте, анализируйте и интерпретируйте данные, улучшайте бизнес-процессы и продукт компании. Обучитесь работе с библиотеками Python
9 месяцев
с нуля
Старт 28 ноября
профессия
Занимайтесь созданием сайтов, веб-приложений, сервисов и их интеграцией с внутренними бизнес-системами на бекенд-языке PHP
10 месяцев
с нуля
Старт 28 ноября
профессия
Создание веб-приложений со скоростью света
5 месяцев
c опытом
Старт 28 ноября
профессия
Обучитесь разработке визуальной части сайта — фронтенда, а также реализации серверной — бэкенда. Освойте HTML, CSS, JavaScript
16 месяцев
с нуля
Старт 28 ноября
профессия
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 28 ноября
профессия
новый
Организовывайте процесс автоматизации тестирования на проекте, обучитесь языку программирования JavaScript, начните управлять процессом тестирования
8 месяцев
c опытом
Старт 28 ноября