INTEGRITY Документация

Wasm в JavaScript

Wasm можно использовать в Worker, написанном на JavaScript или TypeScript, импортировав модуль Wasm и создав его экземпляр с помощью WebAssembly.instantiate(). Это можно использовать для ускорения вычислительно затратных операций, не связанных со значительным объёмом операций ввода-вывода.

В этом руководстве показаны основы взаимодействия Wasm и JavaScript.

Простой модуль Wasm

В этом руководстве вы используете WebAssembly Text Format, чтобы создать простой модуль Wasm и разобраться в том, как работают импорты и экспорты. На практике код в этом формате обычно не пишут. Вместо этого используют выбранный язык программирования и компилируют его напрямую в WebAssembly Binary Format (.wasm).

Ознакомьтесь со следующим примером модуля (;; обозначает комментарий):

;; src/simple.wat
(module
  ;; Import a function from JavaScript named `imported_func`
  ;; which takes a single i32 argument and assign to
  ;; variable $i
  (func $i (import "imports" "imported_func") (param i32))
  ;; Export a function named `exported_func` which takes a
  ;; single i32 argument and returns an i32
  (func (export "exported_func") (param $input i32) (result i32)
    ;; Invoke `imported_func` with $input as argument
    local.get $input
    call $i
    ;; Return $input
    local.get $input
    return
  )
)

Использование wat2wasm, преобразуйте формат WAT в WebAssembly Binary Format:

wat2wasm src/simple.wat -o src/simple.wasm

Bundling

Wrangler упакует любой модуль Wasm, имя которого оканчивается на .wasm или .wasm?module, чтобы он был доступен во время выполнения внутри вашего Worker. Это выполняется с помощью правила сборки по умолчанию, которое можно настроить в конфигурационный файл Wrangler. См. Сборка в Wrangler, где это описано подробнее.

Используйте из JavaScript

После преобразования формата WAT в WebAssembly Binary Format импортируйте и используйте модуль Wasm в существующем Worker на JavaScript или TypeScript:

import mod from "./simple.wasm";

// Define imports available to Wasm instance.
const importObject = {
	imports: {
		imported_func: (arg: number) => {
			console.log(`Hello from JavaScript: ${arg}`);
		},
	},
};

// Create instance of WebAssembly Module `mod`, supplying
// the expected imports in `importObject`. This should be
// done at the top level of the script to avoid instantiation on every request.
const instance = await WebAssembly.instantiate(mod, importObject);

export default {
	async fetch() {
		// Invoke the `exported_func` from our Wasm Instance with
		// an argument.
		const retval = instance.exports.exported_func(42);
		// Return the return value!
		return new Response(`Success: ${retval}`);
	},
};

При вызове этот Worker должен логировать Hello from JavaScript: 42 и вернуть Success: 42, демонстрируя возможность вызывать методы Wasm с аргументами из JavaScript и наоборот.

Следующие шаги

На практике вы, скорее всего, будете компилировать выбранный язык (например, Rust) в бинарные файлы WebAssembly. Многие языки предоставляют bindgen чтобы упростить взаимодействие между JavaScript и Wasm. Эти инструменты могут интегрироваться с вашим сборщиком JavaScript и предоставлять API, отличный от WebAssembly API, для инициализации и вызова вашего модуля Wasm. В качестве примера см. Rust wasm-bindgen документация.

Если вы хотите написать весь Worker на Rust, Workers предоставляет многие из тех же Runtime API и привязки при использовании workers-rs крейт. Подробнее см. в Руководство по Workers для Rust.