wasmer Documentation

Fast and lightweight sandboxes for your apps and AI agents

21,185 stars Rust Rust 60 files · ~56,022 tokens #emscripten#linux#macos#rust#wasi#wasix#wasm#wasmer
RAW Doc

Technical Documentation: wasmerio/wasmer

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Wasmer runs your apps in fast, secure, and lightweight sandboxes: locally,
in the cloud, or in your browser.

  • Secure by default. You control file, network, and environment access.
  • Lightweight. Fast startup with a small memory footprint.
  • Ready to run. Python, JavaScript, Bash, and more from the registry.
  • Embeddable. Add sandboxes to your app with the Wasmer SDK.

Run your first sandbox

Install the CLI on macOS or Linux:

sh
curl https://get.wasmer.io -sSfL | sh

Windows and other installation options

Windows (PowerShell)

powershell
iwr https://win.wasmer.io -useb | iex

Homebrew (macOS / Linux)

sh
brew install wasmer

See the installation guide for more options.

Run Python in a sandbox:

sh
wasmer run python/python -- -c "print('Hello from Wasmer')"
text
Hello from Wasmer

Or try a shell command and Cowsay:

sh
wasmer run wasmer/bash -- -c "echo 'Hello from Wasmer'"
wasmer run syrusakbary/cowsay -- "Hello from Wasmer"

Wasmer downloads the package and caches it for future runs. Use -- to separate
Wasmer options from the arguments passed to your program. To work with local
files, grant access to a directory with --volume; enable host networking with
--net when your program needs it. See the
CLI guide for details.

No installation needed: open wasmer.sh to try a sandbox
in your browser.

Wasmer SDK

Create a sandbox, choose your tools, and run code directly in your app with the
Wasmer SDK.

Install the SDK

JavaScript / TypeScript (Node.js 20 or newer):

sh
npm install @wasmer/sdk

Rust

The Rust SDK currently uses a source dependency. Clone
wasmerio/wasmer-sdk, then point your
application at its rust directory:

toml
[dependencies]
wasmer-sdk = { path = "../wasmer-sdk/rust" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Follow the Rust setup guide
for the required toolchain and workspace patches. Crates.io publishing is
currently disabled.

Python

sh
python -m pip install wasmer-sdk

The SDK's Python wheels support macOS and Linux on Intel and ARM64.
See the Python guide.

Swift (iOS and macOS)

Use Swift 6 or newer. The SDK supports macOS 12+ and iOS 27+; iOS apps require
Xcode 27 or newer.

Add the package to your Package.swift dependencies:

swift
.package(
    url: "https://github.com/wasmerio/wasmer-sdk.git",
    revision: "wasmer-sdk-swift-v0.4.0"
)

Then add the product to your target's dependencies:

swift
.product(name: "WasmerSDK", package: "wasmer-sdk")

In Xcode, you can instead add the repository URL, select
wasmer-sdk-swift-v0.4.0 as a revision, and choose the WasmerSDK product.
SwiftPM downloads the prebuilt macOS binaries and iOS runtime resources.

For iOS, set the deployment target to iOS 27.0 and allow local networking
in your app's Info.plist:

xml
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Both platforms use import WasmerSDK and the same API. On iOS, the SDK manages
a hidden WKWebView; your app does not need to display one. See the
Swift guide and
iOS setup guide
for more details.

Run code in a sandbox

JavaScript / TypeScript

Save this as sandbox.mjs:

javascript
import { Wasmer } from "@wasmer/sdk/node";

const wasmer = new Wasmer();
const sandbox = await wasmer.sandboxes.create({
  packages: ["python/python@=3.13.20"],
});

const output = await sandbox
  .command("python", ["-c", "print('Hello from Wasmer')"])
  .run();

console.log(output.text());

Run it with node sandbox.mjs. Python executes inside the sandbox; you don't
need Python installed on the host. See the
JavaScript guide.

Python example

Save this as sandbox.py:

python
import asyncio

from wasmer_sdk import Wasmer


async def main():
    wasmer = Wasmer()
    sandbox = await wasmer.sandboxes.create(
        packages=["python/python@=3.13.20"],
    )
    output = await sandbox.command(
        "python", ["-c", "print('Hello from Wasmer')"]
    ).run()
    print(output.text())


asyncio.run(main())

Run it with python sandbox.py. See the
Python guide.

Swift example (iOS and macOS)

Use this code in an async throws context:

swift
import WasmerSDK

let wasmer = try Wasmer()
let sandbox = try await wasmer.sandboxes.create(
    packages: ["python/python@=3.13.20"]
)
let output = try await sandbox.command(
    "python", ["-c", "print('Hello from Swift!')"]
).run(timeout: 30)
print(try output.text())

See the Swift guide
for embedding in an iOS or macOS app and more examples.

JavaScript in the browser

Use the same JavaScript sandbox API with the @wasmer/sdk/browser import.
Execution happens in the browser. Your page needs cross-origin isolation
(Cross-Origin-Opener-Policy: same-origin and
Cross-Origin-Embedder-Policy: require-corp) for worker-backed execution.
Follow the browser setup guide
or explore wasmer.sh.

Rust example

rust
use wasmer_sdk::{Result, Wasmer};

#[tokio::main]
async fn main() -> Result<()> {
    let wasmer = Wasmer::new()?;
    let sandbox = wasmer
        .sandboxes()
        .create()
        .package("python/python@=3.13.20")
        .await?;

    let output = sandbox
        .command("python")
        .args(["-c", "print('Hello from Wasmer')"])
        .run()
        .await?;

    println!("{}", output.text()?);
    Ok(())
}

See the Rust guide
for workspace setup and more examples.

Go further

Build more with the sandbox API:

  • Commands. Run code and capture output.
  • Processes. Stream output and manage long-running tasks.
  • Files. Read and write the sandbox workspace.
  • Tools. Combine languages and packages in one sandbox.
  • Services. Run servers with explicit network access.

The SDK is currently alpha. See the language guides for platform support and
capabilities, and the SDK examples
for Python scripts, an Edge.js HTTP server, PostgreSQL, and multiple tools sharing
one sandbox.

Software you can run

Start with packages from the registry:

Software Package
Python python/python
JavaScript / Node.js-compatible apps wasmer/edgejs
Bash wasmer/bash
PHP php/php
PostgreSQL wasmer/pglite
SQLite sqlite/sqlite
FFmpeg wasmer/ffmpeg

Explore more packages,
package your own software, or
deploy an application to Wasmer Edge.

Develop and contribute

This repository contains the Wasmer runtime and CLI that power the sandbox
experience. The sandbox SDKs live in
wasmerio/wasmer-sdk.
For lower-level WebAssembly embedding, see the Rust API
and C API.

Contributions are welcome. For guidance on getting started, read
Contributing to Complex Projects.
Wasmer is MIT licensed.

Community

Get help, share what you're building, and meet other Wasmer users:

Discord ·
X ·
LinkedIn ·
Blog

Community translations (may describe an earlier version)

中文 ·
Deutsch ·
Español ·
Français ·
日本語 ·
한국어


Overview (`assets/README.md`)

Wasmer Documentation Assets

This directory contains documentation assets.

logo.svg contains the Wasmer wordmark from the inline Logo SVG on
wasmer.io, retrieved on September 17, 2026. The original
view box and path geometry are preserved; website-specific attributes are removed.
logo-white.svg uses the same paths with a white fill for dark backgrounds.
The root README uses these SVGs; the PNGs remain for older documentation.


Overview (`benches/README.md`)

Wasmer Benches

This directory contains small, punctual benches. Other benchmarks are
landing somewhere else. We will update this section soon.


Overview (`docs/README.md`)

Wasmer Documentation

Wasmer provides multiple documentations. Here are some pointers:

For contributors, one document per concern:
CONTRIBUTING.md, ARCHITECTURE.md,
BUILD.md, TEST.md,
SECURITY.md. The root AGENTS.md indexes
them for coding agents and covers debugging the runtime.


Overview (`examples/README.md`)

Wasmer Examples

This directory contains a collection of examples. This isn't an
exhaustive collection though, if one example is missing, please ask,
we will be happy to fulfill your needs!

Handy Diagrams

As a quick introduction to Wasmer's main workflows, here are three
diagrams. We hope it provides an overview of how the crates assemble
together.

  1. Module compilation, illustrates how WebAssembly bytes are
    validated, parsed, and compiled, with the help of the
    wasmer::Module, wasmer_engine::Engine, and
    wasmer_compiler::Compiler API.

  2. Module serialization, illustrates how a module can be
    serialized and deserialized, with the help of
    wasmer::Module::serialize and wasmer::Module::deserialize. The
    important part is that the engine can changed between those two
    steps, and thus how a headless engine can be used for the
    deserialization.

  3. Module instantiation, illustrates what happens when
    wasmer::Instance::new is called.

Examples

The examples are written in a difficulty/discovery order. Concepts that
are explained in an example is not necessarily re-explained in a next
example.

Basics

  1. Hello World, explains the core concepts of the Wasmer
    API for compiling and executing WebAssembly.

    Keywords: introduction, instance, module.

    Execute the example

    shell
    $ cargo run --example hello-world --release --features "cranelift"
  2. Instantiating a module, explains the basics of using Wasmer
    and how to create an instance out of a Wasm module.

    Keywords: instance, module.

    Execute the example

    shell
    $ cargo run --example instance --release --features "cranelift"
  3. Handling errors, explains the basics of interacting with
    Wasm module memory.

    Keywords: instance, error.

    Execute the example

    shell
    $ cargo run --example errors --release --features "cranelift"
  4. Interacting with memory, explains the basics of interacting with
    Wasm module memory.

    Keywords: memory, module.

    Execute the example

    shell
    $ cargo run --example memory --release --features "cranelift"

Exports

  1. Exported global, explains how to work with
    exported globals: get/set their value, have information about their
    type.

    Keywords: export, global.

    Execute the example

    shell
    $ cargo run --example exported-global --release --features "cranelift"
  2. Exported function, explains how to get and
    how to call an exported function. They come in 2 flavors: dynamic,
    and “static”/native. The pros and cons are discussed briefly.

    Keywords: export, function, dynamic, static, native.

    Execute the example

    shell
    $ cargo run --example exported-function --release --features "cranelift"
  3. Exported memory, explains how to read from
    and write to exported memory.

    Keywords: export, memory.

    Execute the example

    shell
    $ cargo run --example exported-memory --release --features "cranelift"

Imports

  1. Imported global, explains how to work with
    imported globals: create globals, import them, get/set their value.

    Keywords: import, global.

    Execute the example

    shell
    $ cargo run --example imported-global --release --features "cranelift"
  2. Imported function, explains how to define
    an imported function. They come in 2 flavors: dynamic,
    and “static”/native.

    Keywords: import, function, dynamic, static, native.

    Execute the example

    shell
    $ cargo run --example imported-function --release --features "cranelift"

Externs

  1. Table, explains how to use Wasm Tables from the Wasmer API.

    Keywords: basic, table, call_indirect

    Execute the example

    shell
    $ cargo run --example table --release --features "cranelift"
  2. Memory, explains how to use Wasm Memories from
    the Wasmer API. Memory example is a work in progress.

    Keywords: basic, memory

    Execute the example

    shell
    $ cargo run --example memory --release --features "cranelift"

Tunables

  1. Limit memory, explains how to use Tunables to limit the
    size of an exported Wasm memory

    Keywords: basic, tunables, memory

    Execute the example

    shell
    $ cargo run --example tunables-limit-memory --release --features "cranelift"

Engines

  1. Engine, explains what an engine is and how to set it up. The
    example completes itself with the compilation of the Wasm module, its
    instantiation, and finally, by calling an exported function.

    Keywords: engine, in-memory, executable code.

    Execute the example

    shell
    $ cargo run --example engine --release --features "cranelift"
  2. Headless engines, explains what a headless
    engine is, what problem it does solve, and what are the benefits of
    it. The example completes itself with the instantiation of a
    pre-compiled Wasm module, and finally, by calling an exported
    function.

    Keywords: native, engine, constrained environment, ahead-of-time
    compilation, cross-compilation, executable code, serialization.

    Execute the example

    shell
    $ cargo run --example engine-headless --release --features "cranelift"
  3. Cross-compilation, illustrates the power
    of the abstraction over the engines and the compilers, such as it
    is possible to cross-compile a Wasm module for a custom target.

    Keywords: engine, compiler, cross-compilation.

    Execute the example

    shell
    $ cargo run --example cross-compilation --release --features "cranelift"
  4. Features, illustrates how to enable WebAssembly
    features that aren't yet stable.

    Keywords: engine, features.

    Execute the example

    shell
    $ cargo run --example features --release --features "cranelift"

Compilers

  1. Singlepass compiler, explains how to use
    the wasmer-compiler-singlepass compiler.

    Keywords: compiler, singlepass.

    Execute the example

    shell
    $ cargo run --example compiler-singlepass --release --features "singlepass"
  2. Cranelift compiler, explains how to use
    the wasmer-compiler-cranelift compiler.

    Keywords: compiler, cranelift.

    Execute the example

    shell
    $ cargo run --example compiler-cranelift --release --features "cranelift"
  3. LLVM compiler, explains how to use the
    wasmer-compiler-llvm compiler.

    Keywords: compiler, llvm.

    Execute the example

    shell
    $ cargo run --example compiler-llvm --release --features "llvm"

Integrations

  1. WASI, explains how to use the WebAssembly System
    Interface
    (WASI), i.e. the wasmer-wasi crate.

    Keywords: wasi, system, interface

    Execute the example

    shell
    $ cargo run --example wasi --release --features "cranelift,wasi"
  2. WASI Pipes, builds on the WASI example to show off
    stdio piping in Wasmer.

    Keywords: wasi, system, interface

    Execute the example

    shell
    $ cargo run --example wasi-pipes --release --features "cranelift,wasi"

Overview (`fuzz/README.md`)

Wasmer Fuzz Testing

Fuzz testing is:

An automated testing technique that involves providing invalid,
unexpected, or random data as inputs to a program.

We use fuzz testing to automatically discover bugs in the Wasmer runtime.

This fuzz/ directory contains the configuration and the fuzz tests
for Wasmer. To generate and to run the fuzz tests, we use the
cargo-fuzz library.

Installation

You may need to install the cargo-fuzz library to get the cargo fuzz subcommand. Use

sh
$ cargo install cargo-fuzz

cargo-fuzz is documented in the Rust Fuzz
Book
.

Running a fuzzer

This directory provides multiple fuzzers, like for example validate. You can run it with:

sh
$ cargo fuzz run validate

Another example with the cranelift fuzzer:

sh
$ cargo fuzz run cranelift

See the
fuzz/fuzz_targets
directory for the full list of fuzzers.

You should see output that looks something like this:

text
#1408022        NEW    cov: 115073 ft: 503843 corp: 4659/1807Kb lim: 4096 exec/s: 889 rss: 857Mb L: 2588/4096 MS: 1 ChangeASCIIInt-
#1408273        NEW    cov: 115073 ft: 503844 corp: 4660/1808Kb lim: 4096 exec/s: 888 rss: 857Mb L: 1197/4096 MS: 1 ShuffleBytes-
#1408534        NEW    cov: 115073 ft: 503866 corp: 4661/1809Kb lim: 4096 exec/s: 886 rss: 857Mb L: 977/4096 MS: 1 ShuffleBytes-
#1408540        NEW    cov: 115073 ft: 503869 corp: 4662/1811Kb lim: 4096 exec/s: 886 rss: 857Mb L: 2067/4096 MS: 1 ChangeBit-
#1408831        NEW    cov: 115073 ft: 503945 corp: 4663/1811Kb lim: 4096 exec/s: 885 rss: 857Mb L: 460/4096 MS: 1 CMP- DE: "\x16\x00\x00\x00\x00\x00\x00\x00"-
#1408977        NEW    cov: 115073 ft: 503946 corp: 4664/1813Kb lim: 4096 exec/s: 885 rss: 857Mb L: 1972/4096 MS: 1 ShuffleBytes-
#1408999        NEW    cov: 115073 ft: 503949 corp: 4665/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 964/4096 MS: 2 ChangeBit-ShuffleBytes-
#1409040        NEW    cov: 115073 ft: 503950 corp: 4666/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 90/4096 MS: 1 ChangeBit-
#1409042        NEW    cov: 115073 ft: 503951 corp: 4667/1814Kb lim: 4096 exec/s: 884 rss: 857Mb L: 174/4096 MS: 2 ChangeByte-ChangeASCIIInt-

It will continue to generate random inputs forever, until it finds a
bug or is terminated. The testcases for bugs it finds go into
fuzz/artifacts/cranelift and you can rerun the fuzzer on a
single input by passing it on the command line cargo fuzz run cranelift /path/to/testcase.

The corpus

Each fuzzer has an individual corpus under fuzz/corpus/test_name,
created on first run if not already present. The fuzzers use
wasm-smith which means that the testcase files are random number
seeds input to the Wasm generator, not .wasm files themselves. In
order to debug a testcase, you may find that you need to convert it
into a .wasm file. Using the standalone wasm-smith tool doesn't
work for this purpose because we use a custom configuration to our
wasm_smith::Module. Instead, our fuzzers use an environment variable
DUMP_TESTCASE=path. For example:

sh
$ DUMP_TESTCASE=/tmp/crash.wasm cargo fuzz run --features=singlepass singlepass fuzz/artifacts/singlepass/crash-0966412eab4f89c52ce5d681807c8030349470f6

Overview (`lib/README.md`)

The Wasmer runtime crates

The philosophy of Wasmer is to be very modular by design. It's
composed of a set of crates. We can group them as follows:

  • api — The public Rust or JS API exposes everything a user needs to use Wasmer
    programmatically through the wasmer crate,
  • c-api — The public C API exposes everything a C user needs to use
    Wasmer programmatically,
  • cache — The traits and types to cache compiled WebAssembly
    modules,
  • cli — The Wasmer CLI itself,
  • compiler — The base for the compiler implementations, it defines
    the framework for the compilers and provides everything they need:
    • compiler-cranelift — A WebAssembly compiler based on the
      Cranelift compiler infrastructure,
    • compiler-llvm — A WebAssembly compiler based on the LLVM
      compiler infrastructure; recommended for runtime speed
      performance,
    • compiler-singlepass — A WebAssembly compiler based on our own
      compilation infrastructure; recommended for compilation-time speed
      performance.
  • derive — A set of procedural macros used inside Wasmer,
  • ABI:
    • wasi — WASI ABI implementation inside Wasmer:
      • wasi-types — All the WASI types,
  • engine — The general abstraction for creating an engine, which is
    responsible of leading the compiling and running flow. Using the
    same compiler, the runtime performance will be approximately the
    same, however the way it stores and loads the executable code will
    differ:
    • engine — stores the code in a custom file format, and
      loads it in memory,
    • object — A library to cross-generate native objects for various
      platforms.
  • middlewares — A collection of middlewares, like metering that
    tracks how many operators are executed in total and putting a limit
    on the total number of operators executed,
  • types — The basic structures to use WebAssembly,
  • vm — The Wasmer VM runtime library, the low-level base of
    everything.

Overview (`docs/cn/README.md`)

Wasmer 提供基于 WebAssembly 的超轻量级容器,其可以在任何地方运行:从桌面到云、以及 IoT 设备,并且也能嵌入到 任何编程语言 中.

其他语言的 Readme: 🇩🇪 Deutsch-德語 • 🇬🇧 English-英文 • 🇪🇸 Español-西班牙语 • 🇫🇷 Français-法语 • 🇯🇵 日本語-日文.

特性

  • 快速又安全. Wasmer在完全沙盒化的环境中以“接近本机”的速度运行 WebAssembly。

  • 可插拔. Wasmer 可以根据你的需求支持不同的编译框架 (LLVM,Cranelift ...).

  • 通用的. 你可以在任何平台(macOS, Linux and Windows) 和芯片组运行 Wasmer.

  • 符合标准. 运行时通过了官方WebAssembly测试集 支持WASI 和Emscripten.

快速开始

Wasmer 不需要安装其他依赖. 你可以使用以下安装程序进行安装:

sh
curl https://get.wasmer.io -sSfL | sh

使用Powershell (Windows)

powershell
iwr https://win.wasmer.io -useb | iex

有关更多安装选项,请参见 wasmer-install: Homebrew, Scoop, Cargo...

执行WebAssembly文件

安装Wasmer之后,你已经准备好执行第一个WebAssembly文件了! 🎉

您可以通过运行 QuickJS 开始: qjs.wasm

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3

接下来是你可以做的:

语言整合

📦 Wasmer 运行时能以库的形式嵌入到不同的语言,因此你可以在任何地方使用WebAssembly.

  语言 程序包 文档
Rust logo Rust wasmer Rust crate 文档
C logo C [wasm.h header] 文档
![C++ logo] C++ [wasm.hh header] 文档
C# logo C# WasmerSharp NuGet package 文档
D logo D wasmer Dub package 文档
Python logo Python wasmer PyPI package 文档
JS logo Javascript @wasmerio NPM packages 文档
Go logo Go wasmer Go package 文档
PHP logo PHP wasm PECL package 文档
Ruby logo Ruby wasmer Ruby Gem 文档
Java logo Java wasmer/wasmer-jni Bintray package 文档
Elixir logo Elixir wasmex hex package 文档
R logo R 没有已发布的软件包 文档
Postgres logo Postgres 没有已发布的软件包 文档
Swift 没有已发布的软件包
Zig logo Zig no published package
Ocaml logo OCaml wasmer OCaml package

👋 缺少语言?

贡献

我们欢迎任何形式的贡献,尤其是来自社区新成员的贡献 💜

你可以在我们的出色文档 中学习如何构建 Wasmer 运行时!

测试

想要测试吗? 参考 Wasmer 文档.

社区

Wasmer 拥有一个由出色的开发人员和贡献者组成的社区。 欢迎你,请加入我们! 👋

频道


Overview (`docs/de/README.md`)

Wasmer ist eine schnelle und sichere WebAssembly Runtime, die das Ausführen von
schlanken Containern überall ermöglicht: auf dem Desktop in der Cloud, so wie auf Edge und IoT Geräten.

Die README ist auch in folgenden Sprachen verfügbar:
🇨🇳 中文-Chinesisch •
🇬🇧 English-Englisch •
🇪🇸 Español-Spanisch •
🇫🇷 Français-Französisch •
🇯🇵 日本語-Japanisch
.

Leistungsmerkmale

  • Standardmäßig sicher. Kein Datei-, Netzwerk- oder Umgebungszugriff, sofern nicht explizit aktiviert.
  • Unterstützt WASI und Emscripten standardmäßig.
  • Schnell. Führt WebAssembly in nahezu nativer Geschwindigkeit aus.
  • Einbettbar in mehrere Programmiersprachen
  • Kompatibel mit den neuesten Empfehlungen für WebAssembly (SIMD, Referenztypen, Threads, ...)

Installation

Wasmer CLI wird als eine einzige ausführbare Datei ohne Abhängigkeiten ausgeliefert.

sh
curl https://get.wasmer.io -sSfL | sh

Weitere Installationsmöglichkeiten (Powershell, Brew, Cargo, ...)

Wasmer kann über verschiedene Paketmanager installiert werden. Wählen Sie den für Ihre Umgebung am besten geeigneten aus:

  • Powershell (Windows)

    powershell
    iwr https://win.wasmer.io -useb | iex
  • Homebrew (macOS, Linux)

    sh
    brew install wasmer
  • Scoop (Windows)

    sh
    scoop install wasmer
  • Chocolatey (Windows)

    sh
    choco install wasmer
  • Cargo

    Notiz: Alle verfügbaren Merkmale sind in der wasmer-cli
    crate Dokumentation

    beschrieben.

    sh
    cargo install wasmer-cli

Suchen Sie nach weiteren Installationsmöglichkeiten? Im wasmer-install
Repository
können Si mehr erfahren!

Schnellstart

Sie können beginnen,
QuickJS auszuführen, eine kleine und
einbettbare Javascript Engine, die als WebAssembly Modul kompiliert ist: (qjs.wasm):

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3

Folgendes können Sie als nächstes tun:

📦 Unterstützte Sprachen

Die Wasmer-Laufzeit kann als Bibliothek eingebettet in verschiedenen
Sprachen
verwendet werden, so dass Sie WebAssembly überall einsetzen können.

Sprache Paket Dokumentation
Rust logo Rust wasmer Rust crate Lernen
C logo C/C++ wasmer.h header Lernen
C# logo C# [WasmerSharp NuGet Paket] Lernen
D logo D [wasmer Dub Paket] Lernen
Python logo Python [wasmer PyPI Paket] Lernen
JS logo Javascript [@wasmerio NPM Paket] Lernen
Go logo Go [wasmer Go Paket] Lernen
PHP logo PHP [wasm PECL Paket] Lernen
Ruby logo Ruby wasmer Ruby Gem Lernen
Java logo Java [wasmer/wasmer-jni Bintray Paket] Lernen
Elixir logo Elixir [wasmex hex Paket] Lernen
R logo R kein Paket veröffentlicht Lernen
Postgres logo Postgres kein Paket veröffentlicht Lernen
Swift kein Paket veröffentlicht
Zig logo Zig kein Paket veröffentlicht
Dart logo Dart [wasm pub Paket]
Ocaml logo OCaml wasmer OCaml package

👋  Fehlt eine Sprache?

Unterstützen

Wir sind dankbar für Ihre Hilfe! 💜

Lesen Sie in unserer Dokumentation nach, wie man Wasmer aus dem
Quellcode kompiliert
oder testen Sie Änderungen.

Community

Wasmer hat eine wunderbare Community von Entwicklern und Mitwirkenden. Sie sind herzlich willkommen, bitte machen Sie mit! 👋


Overview (`docs/es/README.md`)

Wasmer hace posible tener contenedores ultraligeros basados en WebAssembly que pueden ser ejecutados en cualquier sitio: desde tu ordenador hasta la nube y dispositivos de IoT, además de poder ser ejecutados en cualquier lenguaje de programación.

This README is also available in: 🇩🇪 Deutsch-Alemán • 🇬🇧 English-Inglés • 🇫🇷 Français-Francés • 🇨🇳 中文-Chino • 🇯🇵 日本語-japonés.

Funcionalidades

  • Rápido y Seguro. Wasmer ejecuta WebAssembly a velocidades nativas en un entorno completamente protegido.

  • Extendible. Wasmer soporta diferentes métodos de compilación dependiendo de tus necesidades (LLVM, Cranelift...).

  • Universal. Puedes ejecutar Wasmer en cualquier platforma (macOS, Linux y Windows) y chip.

  • Respeta los estándares. Wasmer pasa los tests oficiales de WebAssembly siendo compatible con WASI y Emscripten.

Empezamos?

Wasmer no requiere ninguna dependencia. Puedes instalarlo con uno de estos instaladores:

sh
curl https://get.wasmer.io -sSfL | sh

Con PowerShell (Windows)

powershell
iwr https://win.wasmer.io -useb | iex

Visita wasmer-install para más opciones de instalación: Homebrew, Scoop, Cargo...

Ejecuta un archivo WebAssembly

¡Después de instalar Wasmer deberías estar listo para ejecutar tu primer módulo de WebAssembly! 🎉

Puedes empezar corriendo QuickJS: qjs.wasm

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >

Esto es lo que puedes hacer:

Integraciones en diferentes Lenguajes

📦 Wasmer puede ser usado como una librería integrada en diferentes lenguajes de programación, para que puedas ejecutar WebAssembly en cualquier sitio.

  Lenguaje Librería Documentación
Rust logo Rust wasmer en crates.io Documentación
C logo C/C++ cabecera wasmer.h Documentación
C# logo C# WasmerSharp en NuGet Documentación
D logo D [wasmer en Dug] Documentación
Python logo Python wasmer en PyPI Documentación
JS logo Javascript @wasmerio en NPM Documentación
Go logo Go wasmer en Go Documentación
PHP logo PHP wasm en PECL Documentación
Ruby logo Ruby wasmer en Ruby Gems Documentación
Java logo Java wasmer/wasmer-jni en Bintray Documentación
Elixir logo Elixir wasmex en hex Documentación
R logo R sin paquete publicado Documentación
Postgres logo Postgres sin paquete publicado Documentación
Swift sin paquete publicado
Zig logo Zig no published package
Ocaml logo OCaml wasmer OCaml package

👋 Falta algún lenguaje?

Contribuye

Damos la bienvenida a cualquier forma de contribución, especialmente a los nuevos miembros de la comunidad 💜

¡Puedes ver cómo crear el binario de Wasmer con nuestros increíbles documentos!

Tests

¿Quieres testear? Los documentos de Wasmer te enseñarán cómo.

Comunidad

Wasmer tiene una comunidad increíble de desarrolladores y colaboradores ¡Bienvenido, únete a nosotros! 👋

Medios


Overview (`docs/fr/README.md`)

Wasmer permet l'utilisation de conteneurs super légers basés sur WebAssembly qui peuvent fonctionner n'importe où : du bureau au cloud en passant par les appareils IoT, et également intégrés dans une multitude de langages de programmation.

This readme is also available in: 🇩🇪 Deutsch-Allemand • 🇬🇧 English-Anglaise • 🇪🇸 Español-Espagnol • 🇨🇳 中文-Chinoise • 🇯🇵 日本語-japonais

Fonctionnalités

  • Rapide et sûr. Wasmer exécute WebAssembly à une vitesse quasi native dans un environnement entièrement contrôlé (bac à sable, sandbox).

  • Modulaire. Wasmer prend en charge différents frameworks de compilation pour répondre au mieux à vos besoins (LLVM, Cranelift ...).

  • Universel. Vous pouvez exécuter Wasmer sur n'importe quelle plate-forme (macOS, Linux et Windows) et processeur.

  • Conforme aux normes. Wasmer passe la suite de tests officielle de WebAssembly prenant en charge WASI et Emscripten

Quickstart

Wasmer est livré sans aucune dépendance. Vous pouvez l'installer à l'aide des programmes d'installation ci-dessous :

sh
curl https://get.wasmer.io -sSfL | sh

Avec PowerShell (Windows)

powershell
iwr https://win.wasmer.io -useb | iex

Voir wasmer-install pour plus d'options d'installation: Homebrew, Scoop, Cargo...

Exécution d'un fichier WebAssembly

Après avoir installé Wasmer, vous devriez être prêt à exécuter votre premier fichier WebAssemby ! 🎉

Vous pouvez commencer par exécuter QuickJS : qjs.wasm

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >

Voici ce que vous pouvez faire ensuite

Intégrations

📦 Wasmer peut être utilisé comme une bibliothèque intégrée dans différents langages, vous pouvez donc utiliser WebAssembly n'import où.

  Langage de programmation Package Docs
Rust logo Rust wasmer Rust crate Docs
C logo C/C++ wasmer.h headers Docs
C# logo C# WasmerSharp NuGet package Docs
D logo D wasmer Dub package Docs
Python logo Python wasmer PyPI package Docs
JS logo Javascript @wasmerio NPM packages Docs
Go logo Go wasmer Go package Docs
PHP logo PHP wasm PECL package Docs
Ruby logo Ruby wasmer Ruby Gem Docs
Java logo Java wasmer/wasmer-jni Bintray package Docs
Elixir logo Elixir wasmex hex package Docs
R logo R no published package Docs
Postgres logo Postgres no published package Docs
Swift no published package
Zig logo Zig no published package
Ocaml logo OCaml wasmer OCaml package

👋 Il manque un langage ?

Contribuer

Nous accueillons toutes formes de contributions, en particulier de la part des nouveaux membres de notre communauté. 💜

Vous pouvez vérifier comment compiler Wasmer dans notre documentation!

Test

Vous voulez des tests ? La documentation de Wasmer vous montrera comment les exécuter.

Communauté

Wasmer a une incroyable communauté de développeurs et de contributeurs. Bienvenue et rejoignez-nous ! 👋

Canaux de communications


Overview (`docs/ja/README.md`)

Wasmer は、WebAssembly をベースとした非常に軽量なコンテナを実現します。デスクトップからクラウドや IoT デバイス上まで、どんな環境でも実行でき、さらに任意のプログラミング言語に埋め込むこともできます。

この readme は、次の言語でも利用可能です。🇩🇪 Deutsch-ドイツ語 • 🇨🇳 中文-Chinese • 🇬🇧 English-英語 • 🇪🇸 Español-Spanish • 🇫🇷 Français-French

機能

  • 高速かつ安全。WebAssembly を完全なサンドボックス環境内でネイティブに近いスピードで実行します。

  • プラガブル。異なるコンパイルフレームワーク (LLVM、Cranelift など...) をサポートしているため、ニーズに合った最適なフレームワークを選択できます。

  • ユニバーサル。どんなプラットフォーム上 (macOS、Linux、Windows) でも、どんなチップセット上でも実行できます。

  • 標準に準拠。ランタイムは公式の WebAssembly テストスイートに通っており、WASI と Emscripten をサポートします。

クイックスタート

Wasmer は依存関係なしで動作します。以下のコマンドでインストーラーを使用してインストールできます。

sh
curl https://get.wasmer.io -sSfL | sh

PowerShell の場合 (Windows)

powershell
iwr https://win.wasmer.io -useb | iex

Homebrew、Scoop、Cargo など、他のインストール方法については、wasmer-install を参照してください。

WebAssembly ファイルの実行

Wasmer をインストールしたら、初めての WebAssembly ファイルの実行準備が完了です! 🎉

QuickJS (qjs.wasm) を実行することで、すぐに始められます。

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs >

次にできること

他の言語とのインテグレーション

📦 Wasmer ランタイムは他の言語に組み込んで使用できるため、WebAssembly はどんな場所でも利用できます。

  Language Package Docs
Rust logo Rust wasmer Rust crate Docs
C logo C/C++ wasmer.h headers Docs
C# logo C# WasmerSharp NuGet package Docs
D logo D wasmer Dub package Docs
Python logo Python wasmer PyPI package Docs
JS logo Javascript @wasmerio NPM packages Docs
Go logo Go wasmer Go package Docs
PHP logo PHP wasm PECL package Docs
Ruby logo Ruby wasmer Ruby Gem Docs
Java logo Java wasmer/wasmer-jni Bintray package Docs
Elixir logo Elixir wasmex hex package Docs
R logo R 公開パッケージなし Docs
Postgres logo Postgres 公開パッケージなし Docs
Swift 公開パッケージなし
Zig logo Zig no published package
Ocaml logo OCaml wasmer OCaml package

👋 言語が見当たらない?

コントリビューション

どんな形での貢献も歓迎です。コミュニティの新しいメンバーからの貢献は特に歓迎します。 💜

Wasmer ランタイムのビルド方法は、素晴らしいドキュメントで確認できます!

テスト

テストを実行したいですか? Wasmer docs で方法を説明しています。

コミュニティ

Wasmer には、開発者とコントリビューターの素晴らしいコミュニティがあります。ようこそ! あなたも是非参加してください! 👋

チャンネル


Overview (`docs/ko/README.md`)

Wasmer는 초경량 컨테이너 를 Desktop에서부터 Cloud, Edge, IoT 기기들까지 어디에서나 실행할 수 있는 빠르고 안전한 WebAssembly 런타임 입니다.

이 문서는 아래와 같은 언어들을 지원합니다.:
🇨🇳 中 文 -Chinese •
🇩🇪 Deutsch-German •
🇪🇸 Español-Spanish •
🇫🇷 Français-French •
🇯🇵 日本 語 -Japanese
.
🇰🇷 한국어 -Korean_.

특징

  • 기본적으로 안전합니다. 명시적으로 설정하지 않는 한 파일, 네트워크 또는 환경에 액세스할 수 없습니다.
  • WASI와 Emscripten을 즉시 지원합니다.
  • 빠릅니다. native에 가까운 속도로 WebAssembly를 실행합니다.
  • 여러 프로그래밍 언어에 임베디드 가능합니다.
  • 최신 WebAssembly 제안(SIMD, Reference Types, Threads, ...)을 준수합니다.

설치

Wasmer CLI는 종속성이 없는 단일 실행 파일로 제공됩니다.

sh
curl https://get.wasmer.io -sSfL | sh

다른 설치 옵션 (Powershell, Brew, Cargo, ...)

Wasmer는 다양한 패키지 매니저를 통해 설치 할 수 있습니다. 환경에 가장 적합한 것을 선택하십시오.:

  • Powershell (Windows)

    powershell
    iwr https://win.wasmer.io -useb | iex
  • Homebrew (macOS, Linux)

    sh
    brew install wasmer
  • Scoop (Windows)

    sh
    scoop install wasmer
  • Chocolatey (Windows)

    sh
    choco install wasmer
  • Cargo

    Note: 사용 가능한 모든 기능은 wasmer-cli
    crate docs
    문서에 설명되어 있습니다.

    sh
    cargo install wasmer-cli

더 많은 설치 옵션을 찾고 계십니까? 자세한 내용은 the wasmer-install
repository
를 참조하십시오!

빠른 시작

WebAssembly 모듈(qjs.wasm)로 컴파일된
작고 포함 가능한 Javascript 엔진인 QuickJS를 실행하여 시작할 수 있습니다.:

bash
$ wasmer qjs.wasm
QuickJS - Type "\h" for help
qjs > const i = 1 + 2;
qjs > console.log("hello " + i);
hello 3

다음에 할 수 있는 일 :

📦 다른 언어와의 통합

Wasmer 런타임은 다른 언어에 내장된 라이브러리로 사용할 수 있으므로 어디에서나 WebAssembly를 사용할 수 있습니다.

Language Package Documentation
Rust logo Rust wasmer Rust crate Learn
C logo C/C++ wasmer.h header Learn
C# logo C# WasmerSharp NuGet package Learn
D logo D wasmer Dub package Learn
Python logo Python wasmer PyPI package Learn
JS logo Javascript @wasmerio NPM packages Learn
Go logo Go wasmer Go package Learn
PHP logo PHP wasm PECL package Learn
Ruby logo Ruby wasmer Ruby Gem Learn
Java logo Java wasmer/wasmer-jni Bintray package Learn
Elixir logo Elixir wasmex hex package Learn
R logo R 공개 패키지 없음 Learn
Postgres logo Postgres 공개 패키지 없음 Learn
Swift 공개 패키지 없음
Zig logo Zig 공개 패키지 없음
Dart logo Dart wasm pub package
Lisp under heavy development - no published package
Ocaml logo OCaml wasmer OCaml package

👋  없는 언어가 있습니까?

기여

도움을 주셔서 감사합니다! 💜

Wasmer를 빌드하거나 변경 사항을 테스트하는 방법에 대한 문서를 확인하십시오.

커뮤니티

Wasmer에는 개발자의 기여가 있는 훌륭한 커뮤니티가 있습니다. 환영합니다! 꼭 참여해주세요! 👋


Overview (`lib/api/README.md`)

`wasmer` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer)

Wasmer is the most popular
WebAssembly runtime for Rust. It supports JIT (Just
In Time), AOT (Ahead Of Time) compilation, an experimental interpreter as well
as pluggable compilers suited to your needs.

It's designed to be safe and secure, and runnable in any kind of environment.

Usage

Here is a small example of using Wasmer to run a WebAssembly module
written with its WAT format (textual format):

rust
use wasmer::{Store, Module, Instance, Value, imports};

fn main() -> anyhow::Result<()> {
    let module_wat = r#"
    (module
    (type $t0 (func (param i32) (result i32)))
    (func $add_one (export "add_one") (type $t0) (param $p0 i32) (result i32)
        local.get $p0
        i32.const 1
        i32.add))
    "#;

    let mut store = Store::default();
    let module = Module::new(&store, &module_wat)?;
    // The module doesn't import anything, so we create an empty import object.
    let import_object = imports! {};
    let instance = Instance::new(&mut store, &module, &import_object)?;

    let add_one = instance.exports.get_function("add_one")?;
    let result = add_one.call(&mut store, &[Value::I32(42)])?;
    assert_eq!(result[0], Value::I32(43));

    Ok(())
}

Discover the full collection of examples.

Features

Wasmer is not only fast, but also designed to be highly customizable:

  • Pluggable compilers — A compiler is used by the engine to
    transform WebAssembly into executable code:

  • Headless mode — Once a WebAssembly module has been compiled, it
    is possible to serialize it in a file for example, and later execute
    it with Wasmer with headless mode turned on. Headless Wasmer has no
    compiler, which makes it more portable and faster to load. It's
    ideal for constrained environments.

  • Cross-compilation — Most compilers support cross-compilation. It
    means it possible to pre-compile a WebAssembly module targeting a
    different architecture or platform and serialize it, to then run it
    on the targeted architecture and platform later.

  • Run Wasmer in a JavaScript environment — With the js Cargo
    feature, it is possible to compile a Rust program using Wasmer to
    WebAssembly. In this context, the resulting WebAssembly module will
    expect to run in a JavaScript environment, like a browser, Node.js,
    Deno and so on. In this specific scenario, there is no engines or
    compilers available, it's the one available in the JavaScript
    environment that will be used.

Wasmer ships by default with the Cranelift compiler as its great for
development purposes. However, we strongly encourage to use the LLVM
compiler in production as it performs about 50% faster, achieving
near-native speeds.

Note: if one wants to use multiple compilers at the same time, it's
also possible! One will need to import them directly via each of the
compiler crates.

Read the documentation to learn
more
.


Made with ❤️ by the Wasmer team, for the community


Overview (`lib/backend-api/README.md`)

wasmer-backend-api

GraphQL API client for the Wasmer backend.

Development

This client is built on the cynic crate,
a GraphQL client library that allows tight integration between Rust and
GraphQL types.

It was chosen over other implementations like graphql-client because it
significantly reduces boilerplate and improves the development experience.

The downside is that the underlying GraphQL queries are much less obvious when
looking at the code. This can be remedied with some strategies mentioned below.

Consult the Cynic docs at cynic-rs.dev for more
information.

Backend GraphQL Schema

The GraphQL schema for the backend is stored in ./schema.graphql.

To update the schema, simply download the latest version and replace the local
file.

It can be retrieved from
https://github.com/wasmerio/backend/blob/main/backend/graphql/schema.graphql.

Writing/Updating Queries

You can use the Cynic web UI to easily create the types for new
queries.

Simply upload the local schema from ./schema.graphql and use the UI to build
your desired query.

NOTE: Where possible, do not duplicate types that are already defined,
and instead reuse/extend them where possible.

This is not always sensible though, depending on which nested data you want to
fetch.


Overview (`lib/c-api/README.md`)

`wasmer-c-api` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

This crate exposes a C and a C++ API for the Wasmer runtime. It also fully supports the wasm-c-api common API.

Usage

Once you install Wasmer in your system, the shared object files and the headers are available inside the Wasmer installed path.

text
$WASMER_DIR/
  lib/
    libwasmer.{so,dylib,dll}
  include/
    wasm.h
    wasmer.h
    wasmer.hh

Wasmer binary also ships with wasmer-config
an utility tool that outputs config information needed to compile programs which use Wasmer.

The full C API documentation can be found here.

Here is a simple example to use the C API:

text
/* Detailed source-code truncated for AI context efficiency. */

Building

You can compile Wasmer shared library from source:

text
make build-capi

This will generate the shared library (depending on your system):

  • Windows: target/release/libwasmer_c_api.dll
  • macOS: target/release/libwasmer_runtime_c_api.dylib
  • Linux: target/release/libwasmer_runtime_c_api.so

If you want to generate the library and headers in a friendly format as shown in Usage, you can execute the following in Wasmer root:

bash
make package-capi

This command will generate a package directory, that you can then use easily in the Wasmer C API examples.

Testing

Tests are run using the release build of the library. If you make
changes or compile with non-default features, please ensure you
rebuild in release mode for the tests to see the changes.

To run all the full suite of tests, enter Wasmer root directory
and run the following commands:

sh
$ make test-capi

`wasmer config`

wasmer config output various configuration information needed to compile programs which use Wasmer.

`wasmer config --pkg-config`

It outputs the necessary details for compiling and linking a program to Wasmer,
using the pkg-config format:

bash
$ wasmer config --pkg-config > $PKG_CONFIG_PATH/wasmer.pc

`wasmer config --includedir`

Directory containing Wasmer headers:

bash
$ wasmer config --includedir
/users/myuser/.wasmer/include

`wasmer config --libdir`

Directory containing Wasmer libraries:

bash
$ wasmer config --libdir
/users/myuser/.wasmer/lib

`wasmer config --libs`

Libraries needed to link against Wasmer components:

bash
$ wasmer config --libs
-L/Users/myuser/.wasmer/lib -lwasmer

`wasmer config --cflags`

Headers needed to build against Wasmer components:

bash
$ wasmer config --cflags
-I/Users/myuser/.wasmer/include/wasmer

License

Wasmer is primarily distributed under the terms of the MIT
license
(LICENSE).


Overview (`lib/cache/README.md`)

`wasmer-cache` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

The wasmer-cache crate allows to cache WebAssembly modules (of kind
wasmer::Module) in your system, so that next uses of the module does
imply a compilation time.

Usage

The Cache trait represents a generic cache for storing and loading
compiled WebAssembly modules. The FileSystemCache type implements
Cache to store cache on the file system.

rust
use wasmer::{DeserializeError, Module, SerializeError};
use wasmer_cache::{Cache, FileSystemCache, Hash};

fn store_module(module: &Module, bytes: &[u8]) -> Result<(), SerializeError> {
    // Create a new file system cache.
    let mut fs_cache = FileSystemCache::new("some/directory/goes/here")?;

    // Compute a key for a given WebAssembly binary
    let hash = Hash::generate(bytes);

    // Store a module into the cache given a key
    fs_cache.store(hash, module.clone())?;

    Ok(())
}

Overview (`lib/cli/README.md`)

`wasmer-cli` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

This crate is the Wasmer CLI.

The recommended way to install wasmer is via the wasmer-installer.

However, you can also install wasmer via Cargo (you will need to specify the compilers to use):

bash
cargo install wasmer-cli --features "singlepass,cranelift"

Or by building it inside the codebase:

bash
cargo build --release --features "singlepass,cranelift"

Features

The Wasmer supports the following features:

  • wat (default): support for executing WebAssembly text files.
  • wast(default): support for running wast test files.
  • cache (default): support or automatically caching compiled artifacts.
  • wasi (default): support for WASI.
  • singlepass: support for the Singlepass compiler.
  • cranelift: support for the Cranelift compiler.
  • llvm: support for the LLVM compiler.

CLI commands

Once you have Wasmer installed, you can start executing WebAssembly files easily:

Get the current Wasmer version:

bash
wasmer -V

Execute a WebAssembly file:

bash
wasmer run myfile.wasm

Compile a WebAssembly file:

bash
wasmer compile myfile.wasm -o myfile.wasmu

Run a compiled WebAssembly file (fastest):

bash
wasmer run myfile.wasmu

Overview (`lib/compiler-cranelift/README.md`)

`wasmer-compiler-cranelift` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer-compiler-cranelift)

This crate contains a compiler implementation based on Cranelift.

Usage

rust
use wasmer::{Store, sys::EngineBuilder};
use wasmer_compiler_cranelift::Cranelift;

let compiler = Cranelift::new();
let mut store = Store::new(compiler);

Note: you can find a full working example using Cranelift compiler
here
.

When to use Cranelift

We recommend using this compiler crate only for development
proposes
. For production we recommend using wasmer-compiler-llvm
as it offers a much better runtime speed (50% faster on average).

Acknowledgments

This project borrowed some of the function lowering from
cranelift-wasm.

Please check Wasmer ATTRIBUTIONS to further see licenses and other
attributions of the project.


Overview (`lib/compiler-llvm/README.md`)

`wasmer-compiler-llvm` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/lib/compiler-llvm/LICENSE) [](https://crates.io/crates/wasmer-compiler-llvm)

This crate contains a compiler implementation based on the LLVM Compiler Infrastructure.

Usage

rust
use wasmer::{Store, EngineBuilder};
use wasmer_compiler_llvm::LLVM;

let compiler = LLVM::new();
let mut store = Store::new(compiler);

Note: you can find a full working example using LLVM compiler here.

When to use LLVM

We recommend using LLVM as the default compiler when running WebAssembly
files on any production system, as it offers maximum performance near
to native speeds.

Requirements

The LLVM compiler requires a valid installation of LLVM in your system.
It currently requires LLVM 22.

You can install LLVM easily on your Debian-like system via this command:

bash
wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh
sudo bash /tmp/llvm.sh 22
sudo apt install libpolly-22-dev

Or in macOS:

bash
brew install llvm@22

Or via any of the pre-built binaries that LLVM offers.


Overview (`lib/compiler-singlepass/README.md`)

`wasmer-compiler-singlepass`

This crate contains a compiler implementation based on the Singlepass linear compiler.
Supported targets:

  • x86_64
  • aarch64
  • riscv64 (experimental)

Usage

rust
use wasmer::{Store, sys::EngineBuilder};
use wasmer_compiler_singlepass::Singlepass;

let compiler = Singlepass::new();
let mut store = Store::new(compiler);

Note: you can find a full working example using Singlepass compiler
here
.

When to use Singlepass

Singlepass is designed to emit compiled code at linear time, as such
is not prone to JIT bombs and also offers great compilation
performance orders of magnitude faster than
wasmer-compiler-cranelift and wasmer-compiler-llvm, however
with a bit slower runtime speed.

The fact that singlepass is not prone to JIT bombs and offers a very
predictable compilation speed makes it ideal for blockchains and other
systems where fast and consistent compilation times are very critical.


Overview (`lib/compiler/README.md`)

`wasmer-compiler` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

This crate is the base for Compiler implementations.

It performs the translation from a Wasm module into a basic
ModuleInfo, but leaves the Wasm function bytecode translation to the
compiler implementor.

Here are some of the Compilers provided by Wasmer:

How to create a compiler

To create a compiler, one needs to implement two traits:

  1. CompilerConfig, that configures and creates a new compiler,
  2. Compiler, the compiler itself that will compile a module.
rust
/// The compiler configuration options.
pub trait CompilerConfig {
    /// Gets the custom compiler config
    fn compiler(&self) -> Box<dyn Compiler>;
}

/// An implementation of a compiler from parsed WebAssembly module to compiled native code.
pub trait Compiler {
    /// Compiles a parsed module.
    ///
    /// It returns the [`Compilation`] or a [`CompileError`].
    fn compile_module<'data, 'module>(
        &self,
        target: &Target,
        compile_info: &'module CompileModuleInfo,
        module_translation: &ModuleTranslationState,
        // The list of function bodies
        function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
    ) -> Result<Compilation, CompileError>;
}

Acknowledgments

This project borrowed some of the code structure from the
cranelift-wasm crate, however it's been adapted to not depend on
any specific IR and be abstract of any compiler.

Please check Wasmer ATTRIBUTIONS to further see licenses and other
attributions of the project.


Overview (`lib/config/README.md`)

wasmer-config

(API Docs)

Provides configuration types for Wasmer.

For Developers

Releasing

This repository uses Release Please to automate a lot of the
work around creating releases.

Every time a commit following the Conventional Commit Style is merged
into main, the release-please.yml
workflow will run and update the "Release PR" to reflect the new changes.

For commits that just fix bugs (i.e. the message starts with "fix: "), the
associated crate will receive a changelog entry and a patch version bump.
Similarly, adding a new feature (i.e. "feat:") does a minor version bump and
adding breaking changes (i.e. "fix!:" or "feat!:") will result in a major
version bump.

When the release PR is merged, the updated changelogs and bumped version numbers
will be merged into the main branch, the release-please.yml workflow will
automatically generate GitHub Releases, and CI will publish the crate if
necessary.

TL;DR:

  1. Use Conventional Commit Messages whenever you make a noteworthy change
  2. Merge the release PR when ready to release
  3. Let the automation do everything else

License

This project is licensed under the MIT license (LICENSE or
http://opensource.org/licenses/MIT).

It is recommended to always use cargo crev to verify the
trustworthiness of each of your dependencies, including this one.


Overview (`lib/middlewares/README.md`)

Wasmer Middlewares

The wasmer-middlewares crate is a collection of various useful
middlewares:

  • metering: A middleware for tracking how many operators are
    executed in total and putting a limit on the total number of
    operators executed.

    See the metering
    example

    to get a concrete and complete example.


Overview (`lib/package-sdk/README.md`)

wasmer-sdk

The wasmer-sdk provides convenient wrappers to work with the Wasmer ecosystem,
including functionality for:

  • Building and publishing packages
  • Deploying apps
  • ...

Architecture Support

This crate currently only works on native architectures, and does not support
browser Webassembly yet. Support will likely added in the future.


Overview (`lib/types/README.md`)

`wasmer-types` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

This library provides all the types and traits necessary to use
WebAssembly easily anywhere.

Among other things, it defines the following types:

  • units like Pages or Bytes
  • types and values like I32, I64, F32, F64, ExternRef,
    FuncRef, V128, value conversions, ExternType, FunctionType
    etc.
  • native contains a set of trait and implementations to deal with
    WebAssembly types that have a direct representation on the host,
  • memory_view, an API to read/write memories when bytes are
    interpreted as particular types (i8, i16, i32 etc.)
  • indexes contains all the possible WebAssembly module indexes for
    various types
  • initializers for tables, data etc.
  • features to enable or disable some WebAssembly features inside the
    Wasmer runtime

Acknowledgments

This project borrowed some of the code for the entity structure from cranelift-entity.
We decided to move it here to help on serialization/deserialization.

Please check Wasmer ATTRIBUTIONS to further see licenses and other attributions of the project.


Overview (`lib/vm/README.md`)

`wasmer-vm` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE)

This crate contains the Wasmer VM runtime library, supporting the Wasm ABI used by wasmer.

The Wasmer runtime is modular by design, and provides several
libraries where each of them provides a specific set of features. This
wasmer-vm library contains the low-level foundation for the runtime
itself.

It provides all the APIs wasmer needs to operate,
from the instance, to memory, probestack, signature registry, trap,
table, VMContext, libcalls etc.

It is very unlikely that a user will need to deal with wasmer-vm
directly. The wasmer crate provides types that embed types from
wasmer-vm with a higher-level API.

Acknowledgments

This project borrowed some of the code for the VM structure and trapping from the wasmtime-runtime.

Please check Wasmer ATTRIBUTIONS to further see licenses and other attributions of the project.


Overview (`lib/wai-bindgen-wasmer/README.md`)

wai-bindgen-wasmer

Runtime utility crate for Wasmer host WAI bindings generated by wai-bindgen-gen-wasmer.

This crate was moved from the https://github.com/wasmerio/wai repository.

wai-bindgen-wasmer needs Wasmer as a dependency, which makes it extremely awkward to use if the
crate is not in the same repo.
This is necessary because wai is now used for wasix_http_client bindings, and will also be used
for all WASI and WASIX syscalls in the future.

The medium-term plan is to rewrite wai-bindgen-gen-wasmer to make this create redundant.

See https://github.com/wasmerio/wai/issues/31 .


Overview (`lib/wasi-types/README.md`)

wasmer-wasix-types

This crate contains WASI(X) type definitions used by wasmer-wasix.


Overview (`lib/wasix/README.md`)

`wasmer-wasi` [](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [](https://slack.wasmer.io) [](https://github.com/wasmerio/wasmer/blob/main/LICENSE) [](https://crates.io/crates/wasmer-wasi)

This crate provides the necessary imports to use WASI easily from Wasmer.
WebAssembly System Interface
(WASI for short) is a modular system interface for WebAssembly. WASI
is being standardized in the WebAssembly subgroup.

Very succinctly, from the user perspective, WASI is a set of
WebAssembly module imports under a specific namespace (which
varies based on the WASI version). A program compiled for the
wasm32-wasip1 target will be able to support standard I/O, file I/O,
filesystem manipulation, memory management, time, string, environment
variables, program startup etc.

Wasmer WASI is created with the aim to be fully sandboxed.
We are able to achieve that thanks to our Virtual Filesystem implementation (wasmer-vfs)
and by only allowing secure systemcalls back to the host.

Note: If you encounter any sandboxing issue please open an issue in the wasmer repo https://github.com/wasmerio/wasmer.

This crate provides the necessary API to create the imports to use
WASI easily from the Wasmer runtime, through our ImportObject API.

Supported WASI versions

WASI version Support
wasi_unstable ✅
wasi_snapshot_preview1 ✅

The special Latest version points to wasi_snapshot_preview1.

Learn more about the WASI version
process

(ephemeral, snapshot, old).

Usage

Let's consider the following hello.rs Rust program:

rust
fn main() {
    println!("Hello, {:?}", std::env::args().nth(1));
}

Then, let's compile it to a WebAssembly module with WASI support:

sh
$ rustc --target wasm32-wasip1 hello.rs

Finally, let's execute it with the wasmer CLI:

sh
$ wasmer run hello.wasm Gordon
Hello, Some("Gordon")

… and programmatically with the wasmer and the wasmer-wasi libraries:

rust
use std::io::Read;
use wasmer::{Module, Store};
use wasmer_wasix::{Pipe, WasiEnv};

let wasm_path = "hello.wasm";

// Let's declare the Wasm module with the text representation.
let wasm_bytes = std::fs::read(wasm_path)?;

// Create a Store.
let mut store = Store::default();

println!("Compiling module...");
// Let's compile the Wasm module.
let module = Module::new(&store, wasm_bytes)?;

let (stdout_tx, mut stdout_rx) = Pipe::channel();

// Run the module.
WasiEnv::builder("hello")
     .args(&["Gordon"])
    // .env("KEY", "Value")
    .stdout(Box::new(stdout_tx))
    .run_with_store(module, &mut store)?;

eprintln!("Run complete - reading output");

let mut buf = String::new();
stdout_rx.read_to_string(&mut buf).unwrap();

eprintln!("Output: {buf}");

Check the fully working example using
WASI
.

More resources

This library is about the WASI implementation inside the Wasmer
runtime. It contains documentation about the implementation
itself. However, if you wish to learn more about WASI, here is a list
of links that may help you:

  • wasi-libc, WASI libc
    implementation for WebAssembly programs built on top of WASI system
    calls. It provides a wide array of POSIX-compatible C APIs,
    including support for standard I/O, file I/O, filesystem
    manipulation, memory management, time, string, environment
    variables, program startup, and many other APIs,
  • wasi-sdk, WASI-enabled
    WebAssembly C/C++ toolchain, based on wasi-libc,
  • WASI API
    documentation
    ,
  • WASI C API header
    file
    ,
  • WASI Application Binary Interface
    (ABI)
    ,
    where we learn about _start and _initialize (for reactors) for example.

Overview (`tests/deprecated/README.md`)

Tests: Deprecated

In this folder we will test deprecated APIs to verify that they
still work the way it should, so users of Wasmer are happy while
transitioning to newer APIs.

As time passes and adoption of new APIs rises, tests on this folder
should start tending towards 0.

Therefore, deprecated tests are intended to be deleted on the long
term.


Overview (`tests/integration/README.md`)

Wasmer Integration tests

All Wasmer end to end integration tests live here.
We have different kind of integration tests:

CLI Integration tests

This tests check that the wasmer CLI works as it should when running it
as a Command in a shell, for each of the supported compilers.

Snapshot Tests

A snapshot test suite is located at ./cli/tests/snapshot.rs.

The file contains tests that run various Webassembly files through wasmer run.
The output is stored as snapshots in the repository.

The insta crate is used for snapshots.

Working With Snapshots

  • Install the cargo-insta CLI
    cargo install cargo-insta
  • Update snapshots:
    text
    cd ./cli/
    cargo insta test --review -- snapshot

C Integration tests

This tests verify that Wasmer wasm-c-api tests are passing for each of the
supported compilers.

Rust Integration tests

This tests verify that the wasmer API fulfill the required API that
external users use.


Overview (`tests/lib/README.md`)

Wasmer Test libraries

Here is the place where the test libraries will live.


Overview (`tests/wasmer-argus/README.md`)

wasmer-argus

Automatically test packages from the registry.

Building

If you want to use the local wasmer crate, you shall
build the project with cargo build --package wasmer-argus --features wasmer_lib.

Usage

This binary fetches packages from the graphql endpoint of a registry. By
default, it uses http://registry.wasmer.io/graphql; and the needed
authorization token is retrieved from the environment using the WASMER_TOKEN.
Users can specify the token via CLI with the appropriate flag.

This testsuite is parallelised, and the degree of parallelism available can be
specified both by CLI flag or automatically using
std::thread::available_parallelism.

text
Fetch and test packages from a WebContainer registry

Usage: wasmer-argus [OPTIONS]

Options:
  -r, --registry-url <REGISTRY_URL>  
        The GraphQL endpoint of the registry to test [default: http://registry.wasmer.io/graphql]
  -b, --backend <COMPILER_BACKEND>   
        The backend to test the compilation against [default: singlepass] [possible values: llvm, singlepass, cranelift]
      --run                          
        Whether or not to run packages during tests
  -o, --outdir <OUTDIR>              
        The output directory [default: /home/ecmm/sw/wasmer/wasmer/target/debug/out]
      --auth-token <AUTH_TOKEN>      
        The authorization token needed to see packages [default: <env::WASMER_TOKEN>]
      --jobs <JOBS>                  
        The number of concurrent tests (jobs) to perform [default: 12]
  -h, --help                         Print help
  -V, --version                      Print version

Overview (`tests/wast/README.md`)

WebAssembly testsuite

Here is where all the .wast tests live.


Overview (`lib/wasix/tests/README.md`)

WASIX integration tests

default file system tree

We should see these four directories by default

sh
cd ../../cli
cargo run --features compiler,cranelift -- ../wasix/tests/coreutils.wasm ls

Expected:

text
bin
dev
etc
tmp

using /dev/stderr

This test ensures that the dev character devices are working properly, there should be two lines with blah as tee will
send it both to the console and to the file

sh
cd ../../cli
echo blah | cargo run --features compiler,cranelift -- ../wasix/tests/coreutils.wasm tee /dev/stderr

Expected:

text
blah
blah

atomic_wait and atomic_wake syscalls

When we convert this from syscalls to native language constructs in WASM this test
needs to continue to pass.

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- ../wasix/tests/example-condvar.wasm

Expected:

text
condvar1 thread spawn
condvar1 thread started
condvar1 thread sleep(1sec) start
condvar loop
condvar wait
condvar1 thread sleep(1sec) end
condvar1 thread set condition
condvar1 thread notify
condvar woken
condvar parent done
condvar1 thread exit
all done

cowsay

Piping to cowsay should, well.... display a cow that says something

sh
cd ../../cli
echo blah | cargo run --features compiler,cranelift,debug -- ../wasix/tests/cowsay.wasm

Expected:

text
______
< blah >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
               ||----w |
                ||     ||

polling and event notifications

This test makes sure the event notifications works correctly fd_event - this construct is used
in tokio in order to wake up the main IO thread that is blocked on an poll_oneoff.

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- ../wasix/tests/example-epoll.wasm

Expected:

text
EFD_NONBLOCK:4
success write to efd, write 8 bytes(4) at 1669077621s 935291us
success read from efd, read 8 bytes(4) at 1669077621s 937666us
success write to efd, write 8 bytes(4) at 1669077622s 937881us
success read from efd, read 8 bytes(4) at 1669077622s 938309us
success write to efd, write 8 bytes(4) at 1669077623s 939714us
success read from efd, read 8 bytes(4) at 1669077623s 940002us
success write to efd, write 8 bytes(4) at 1669077624s 941033us
success read from efd, read 8 bytes(4) at 1669077624s 941205us
success write to efd, write 8 bytes(4) at 1669077625s 943658us
success read from efd, read 8 bytes(4) at 1669077625s 943956us

fork and execve

The ability to fork the current process and run a different image but retain the existing open
file handles (which is needed for stdin and stdout redirection)

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --use wasmer/coreutils --enable-threads ../wasix/tests/example
-execve.wasm

Expected:

text
Main program started
execve: echo hi-from-child
hi-from-child
Child(1) exited with 0
execve: echo hi-from-parent
hi-from-parent

longjmp

longjmp is used by C programs that save and restore the stack at specific points - this functionality
is often used for exception handling

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-longjmp.wasm

Expected:

text
(A1)
(B1)
(A2) r=10001
(B2) r=20001
(A3) r=10002
(B3) r=20002
(A4) r=10003

Yet another longjmp implementation

This one is initiated from rust code and thus has the risk of leaking memory but uses different interfaces

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-stack.wasm

Expected:

text
before long jump
after long jump [val=10]
before long jump
after long jump [val=20]

fork

Simple fork example that is a crude multi-threading implementation - used by dash

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-fork.wasm

Expected:

text
Parent has x = 0
Child has x = 2
Child(1) exited with 0

fork and longjmp

Performs a longjmp of a stack that was recorded before the fork - this test ensures that the stacks that have
been recorded are preserved after a fork. The behavior is needed for dash

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-fork-longjmp.wasm

Expected:

text
Parent has x = 0
Child has x = 2
Child(1) exited with 5

multi threading

full multi-threading with shared memory and shared compiled modules

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-multi-threading.wasm

Expected:

text
thread 1 started
thread 2 started
thread 3 started
thread 4 started
thread 5 started
thread 6 started
thread 7 started
thread 8 started
thread 9 started
waiting for threads
thread 1 finished
thread 2 finished
thread 3 finished
thread 4 finished
thread 5 finished
thread 6 finished
thread 7 finished
thread 8 finished
thread 9 finished
all done

pipes

Uses the fd_pipe syscall to create a bidirection pipe with two file descriptors then forks
the process to write and read to this pipe.

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-pipe.wasm

Expected:

text
this text should be printed by the child
this text should be printed by the parent

signals

Tests that signals can be received and processed by WASM applications

sh
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-signal.wasm

Note: This test requires that a signal is sent to the process asynchronously

sh
kill -s SIGINT 16967

Expected:

text
received SIGHUP

sleep

Puts the process to sleep for 50ms

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-sleep.wasm

Expected:

text

Spawning sub-processes

Uses posix_spawn to launch a sub-process and wait on it to exit

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads --use wasmer/coreutils ../wasix/tests/example
-spawn.wasm

Expected:

text
Child pid: 1
hi
Child status 0

TCP client

Connects to 8.8.8.8:53 over TCP to verify TCP clients work

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-tcp-client.wasm

Expected:

text
Successfully connected to server in port 53
Finished.

TCP listener

Waits for a connection after listening on 127.0.0.1:7878

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-tcp-listener.wasm

In order to test this a curl command is needed below asynchronously and then it needs to be killed

sh
curl 127.0.0.1:7878

Expected:

text
Listening on 127.0.0.1:7878
Connection established!

Thread local variables

Tests that thread local variables work correctly

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-thread-local.wasm

Expected:

text
/* Detailed source-code truncated for AI context efficiency. */

vforking

Tests that lightweight forking that does not copy the memory but retains the
open file descriptors works correctly.

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads ../wasix/tests/example-vfork.wasm

Expected:

text
Parent waiting on Child(1)
Child(1) exited with 10

web server

Advanced test case that uses tokio, TCP listeners, asynchronous IO, event notifications, multi-threading
and mapped directories to serve HTTP content.

sh
cd ../../cli
cargo run --features compiler,cranelift,debug -- --enable-threads --volume /prog/deploy/wasmer-web/public:/public ../wasix/tests/web-server.wasm -- --port 8080 --log-level trace

Note: This requires that a curl command be made to the HTTP server asynchronously

sh
john@AlienWorld:/prog/wasix-libc/examples$ curl 127.0.0.1:8080
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="Description" content="The Wasmer Shell is an browser based operating system powered by wasmer.io that integrates that allows the WebAssembly community to assembly and build browser hosted applications.">
    <meta property="og:url" content="https://wasmer.sh" />
    <meta property="og:title" content="wasmer.sh" />
    <meta property="og:description" content="An browser based operating system powered by wasmer.io that integrates that allows the WebAssembly community to assembly and build browser hosted applications" />
    <meta property="og:image" content="https://wasmer.sh/favicon.png" />
    <meta property="og:type" content="website" />
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <link rel="stylesheet" href="xterm.css" />
    <link rel="stylesheet" href="wasmer.css" />
    <link rel="icon" href="/favicon.png">
    <title>wasmer.sh</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <script type="module" defer="defer" src="main.js"></script>
  </head>

  <body>
    <canvas id="frontBuffer"></canvas>
    <div id="terminal"></div>
  </body>
</html>

Expected:

text
/* Detailed source-code truncated for AI context efficiency. */

Overview (`tests/lib/wast/README.md`)

This is the wasmer-wast crate, which contains an implementation of WebAssembly's
"wast" test scripting language, which is used in the
WebAssembly spec testsuite, using wasmer for execution.

Note: this project started as a fork of this crate.


Overview (`tests/wast/wasmer/README.md`)

Custom wast tests

In this directory we have created wast tests for different cases
where we want to test other scenarios than the ones offered
by the standard WebAssembly spectests.

NaN canonicalization: `nan-canonicalization.wast`

This is an extra set of tests that assure that operations with NaNs
are deterministic regardless of the environment/chipset where it executes in.

Call Indirect Spilled Stack: `call-indirect-spilledd-stack.wast`

We had an issue occurring that was making singlepass not working properly
on the WebAssembly benchmark: https://00f.net/2019/10/22/updated-webassembly-benchmark/.

This is a test case to ensure it doesn't reproduce again in the future.

Multiple Traps: `multiple-traps.wast`

This is a test assuring functions that trap can be called multiple times.

Fac: `fac.wast`

This is a simple factorial program.

Check that struct-return on the stack doesn't overflow: `stack-overflow-sret.wast`

Stack space for a structure returning function call should be allocated once up
front, not once in each call.

Divide by Zero: `divide.wast`

This is a simple test to check that a divide by zero is correctly trapped

Atomic Load: `atomic_load.wast`

This is a simple test to check that load an atomic "to far" in memory trigger a OutOfBound trap

Nested Unreachable Blocks: `nested_unreachable_blocks.wast`

This was broken at one point in our LLVM backend. Otherwise, it's nothing specific.


Overview (`lib/c-api/tests/wasm-c-api/README.md`)

WebAssembly C and C++ API

Work in progress! No docs yet.

Design Goals

  • Provide a "black box" API for embedding a Wasm engine in other C/C++ applications.

    • Be completely agnostic to VM specifics.

    • Non-goal: "white box" interoperability with embedder (such as combined GC instead of mere finalisation) -- much more difficult to achieve.

  • Allow creation of bindings for other languages through typical C foreign function interfaces.

    • Support a plain C API.

    • Stick to mostly manual memory management of interface objects.

  • Avoid language features that raise barrier to use.

    • E.g., no exceptions or post-C++11 features in C++ API.

    • E.g., no passing of structs by-value or post-C99 features in C API.

  • Achieve link-time compatibility between different implementations.

    • All implementation-dependent API classes are abstract and can be instantiated through factory methods only.

Interfaces

  • C++ API:

    • See include/wasm.hh for interface.

    • See example/*.cc for example usages.

  • C API:

    • See include/wasm.h for interface.

    • See example/*.c for example usages.

Some random explanations:

  • The VM must be initialised by creating an instance of an engine (wasm::Engine/wasm_engine_t) and is shut down by deleting it. Such an instance may only be created once per process.

  • All runtime objects are tied to a specific store (wasm::Store/wasm_store_t). Multiple stores can be created, but their objects cannot interact. Every store and its objects must only be accessed in a single thread.

  • To exchange module objects between threads, create a shared module (wasm::Shared<Module>/wasm_shared_module_t). Other objects cannot be shared in current Wasm.

  • Vector structures (wasm::vec<X>/wasm_x_vec_t) are lightweight abstractions of a pair of a plain array and its length. The C++ API does not use std::vector because that does not support adopting pre-existing arrays.

  • References point to runtime objects, but may involve internal indirections, which may or may not be cached. Thus, pointer equality on Ref* or subclasses cannot be used to compare identity of the underlying objects (Ref::eq may be added later). However, nullptr/NULL uniquely represents null references.

  • The API already encompasses current proposals like multiple return values and reference types, but not yet threads.

Prototype Implementation

  • This repo contains a prototype implementation based on V8 is in src.

    • Note that this requires adding a module to V8, so it patches V8's build file.
  • The C API is implemented on top of the C++ API.

  • See Makefile for build recipe. Canonical steps to run examples:

    1. make v8-checkout
    2. make v8
    3. make all

Limitations

V8 implementation:

  • Currently requires patching V8 by adding a module.

  • Host functions (Func::make) create a JavaScript function internally, since V8 cannot handle raw C imports yet.

  • As a consequence, does not support multiple results in external calls or host functions.

  • Host functions and host globals are created through auxiliary modules constructed on the fly, to work around limitations in JS API.

  • Shared<Module> is currently implemented via serialisation, since V8 does not currently have direct support for cross-isolate sharing.

Other Implementations

Currently, known implementations of this API are included in

  • V8 natively (both C and C++)
  • Wabt (only C?)
  • Wasmtime (only C?)
  • Wasmer (only C, C++ coming soon)

TODO

Possible API tweaks:

  • Add Ref::eq (or better, a subclass EqRef::eq) for reference equality?

  • Add a way to return error messages from Module::make and Module::validate.

  • Use restrict in C API?

  • Find a way to perform C callbacks through C++ without extra wrapper?

  • Add iterators to vec class?


Overview (`lib/wasix/tests/wasm_tests/README.md`)

WASIX wasm tests

This directory contains integration tests that build small WASM programs and run them directly through wasmer-wasix from Rust. Most fixtures are C or C++ programs compiled with wasixcc / wasix++.

A working installation of wasixcc is required for this suite to work. The harness expects wasixcc and wasix++ to be available on PATH.

How the suite is structured

The wasix-wasm integration test target discovers tests automatically from this
directory. Any subdirectory that contains one of these primary files is treated
as a test fixture:

  • build.sh or other *.sh primary sources
  • Cargo.toml
  • main.c
  • main.cpp
  • *.rs

Discovery precedence within a fixture directory is:

  1. *.sh shell primary sources
  2. Cargo.toml (full Cargo project)
  3. main.c / main.cpp
  4. *.rs (each Rust source is an independent test)

The harness builds each discovered fixture, runs the resulting main module through the WASIX runner,
and registers one test per configuration each of the enabled engines.

Primary source files can contain inline directives that define the runnable configurations,
arguments, runtime environment, stdin, expected output, expected exit status, mapped directories, prefilled files, and file checks.
The supported directives are documented in ../wasm_tests.rs.

If a fixture has more than one .sh file, each shell file is treated as a
primary source, where build.sh is the default shell source name.

Fixtures with an explicit Cargo.toml are built as full Cargo projects. Directives
can be placed in ##Directive: Args comments in the manifest.

The former tests/wasi-fyi shell suite now lives in wasi_fyi/
as Rust primary sources with inline directives.

How building works

Source fixtures are copied into a per-test build directory under wasm_tests/build/.
The harness then builds them as follows:

  • main.c is compiled with CC, or wasixcc if CC is unset.
  • main.cpp is compiled with CXX, or wasix++ if CXX is unset.
  • *.rs is built with cargo wasix build using an ephemeral Cargo.toml generated
    in the build directory.
  • Cargo.toml fixtures are built with cargo wasix build and the single binary
    artifact is copied to main.
  • build.sh and other shell primary sources are executed with bash; the
    harness sets CC=wasixcc, CXX=wasix++, and
    WASIXCC_DISCARD_UNSUPPORTED_FLAGS=yes.

Every build must produce an executable WebAssembly output named main.

If a fixture needs compiler environment overrides, add BuildEnv directives to
the primary source, for example //#BuildEnv: WASIXCC_PIC=1 in C/C++ sources or
##BuildEnv: WASIXCC_PIC=1 in shell sources.

Running the tests

These tests run through the normal wasix integration test target, so standard
Cargo and nextest filtering both work. Before running the suite, make sure
wasixcc is installed and available in your shell environment.
Rust fixtures also require cargo-wasix on PATH (cargo install cargo-wasix).

Single-file Rust fixtures build with two Rust toolchains by default (see the
Toolchains directive): wasix (cargo-wasix), which runs on every engine
except Singlepass — the WASIX toolchain emits exception-handling opcodes
Singlepass does not support — and wasip1 (rustc --target wasm32-wasip1,
nightly when the source uses #![feature(...)]), which runs on every engine.
The wasip1 variants need rustup target add wasm32-wasip1 (plus the same
target on nightly).

We do not publish the WASIX Rust toolchain for every platform yet, so the
wasix variants are only collected on hosts that have one: gnu Linux on x86_64
and aarch64, and macOS on aarch64. They are skipped on musl, which has no
toolchain, and on Windows, which wasixcc does not cover either. The wasip1
variants build everywhere, so single-file Rust fixtures keep running on those
hosts.

On macOS, this suite collects and runs the LLVM variants only because Cranelift
exception-handling support is still incomplete there:


Overview (`lib/wasix/tests/wasm_tests/wasi_fyi/README.md`)

wasi-fyi fixtures

These fixtures were ported from the legacy tests/wasi-fyi shell test suite into the wasmer-wasix Rust integration harness.

Each *.rs file is a primary source discovered by the shared wasm_tests
harness. The source-level directives define per-test inputs and expectations:

  • Args supplies command-line arguments.
  • Env supplies runtime environment variables.
  • StdinFile supplies stdin bytes from a fixture file.
  • ExpectedStdoutFile and ExpectedStderrFile assert exact output.
  • ExpectedExitCode asserts the expected process exit code.

Common runner setup lives in wasi-fyi.config and is included explicitly with
AbstractConfigFile.

The original fixture license is preserved in LICENSE.


Overview (`lib/wasix/tests/wasm_tests/wasi_fyi/test_fs/README.md`)

Test FS

This is a test "file system" used in some of the WASI integration tests.

It's just a bunch of files in a tree.

If you make changes here, please regenerate the tests with make wasitests!

The contents of temp are deleted before each run. If you want to test making or mutating files, do it in that sub directory.


Overview (`lib/wasix/tests/wasm_tests/wasi_wast/test_fs/README.md`)

Test FS

This is a test "file system" used in some of the WASI integration tests.

It's just a bunch of files in a tree.

If you make changes here, update the expected output fixtures in the parent
wasi_wast directory.

The contents of temp are deleted before each run. If you want to test making or mutating files, do it in that sub directory.


Overview (`tests/integration/cli/tests/packages/js/README.md`)

This is a simple Javascript Service Worker server template running with WinterJS.

This starter's full tutorial is available here.

Usage

Modify the logic of your the Javascript worker in the src/index.js file.

You can run the JS Service Worker locally with (check out the Wasmer install guide):

bash
wasmer run . --net

Open http://localhost:8080 with your browser to see the worker working!

Deploy on Wasmer Edge

The easiest way to deploy your Javascript Worker is to use the Wasmer Edge.

Live example: https://wasmer-js-worker-starter.wasmer.app/

bash
wasmer deploy

Overview (`lib/wasix/tests/wasm_tests/wasi_fyi/test_fs/hamlet/README.md`)

Hamlet split in to acts and scenes

From: http://shakespeare.mit.edu/hamlet/full.html


Overview (`lib/wasix/tests/wasm_tests/wasi_wast/test_fs/hamlet/README.md`)

Hamlet split in to acts and scenes

From: http://shakespeare.mit.edu/hamlet/full.html


ARCHITECTURE (`docs/ARCHITECTURE.md`)

Repository Architecture

This document maps the workspace, one crate per concern. The workspace
holds tens of crates; the full listing is the members section of the
root Cargo.toml. The table below covers the paths you
will touch most:

Path Content
lib/api Public wasmer crate. Flavors: sys (native, default), v8, js.
lib/cli CLI crate wasmer-cli. Binaries: wasmer, wasmer-headless.
lib/compiler Compiler framework and traits.
lib/compiler-{singlepass,cranelift,llvm} The three compiler backends.
lib/vm Low-level VM runtime.
lib/wasix The WASIX implementation (syscalls, processes, threads).
lib/journal Snapshot and restore support. See journal.md.
lib/virtual-fs, lib/virtual-net, lib/virtual-io Host abstraction layers.
lib/c-api C API (cdylib named wasmer).
lib/backend-api GraphQL client for the Wasmer registry.
lib/config, lib/package wasmer.toml parsing and webc packaging.
tests/compilers Integration tests (wast.rs, traps.rs, issues.rs, more).
tests/wast/{spec,wasmer} WAST test files. spec is a submodule.

The root crate is a meta-crate.

Submodules

Three submodules: tests/wast/spec, lib/napi, wasmer-test-files.

For initialization and working with the different crates + submodules, see BUILD.md


ATTRIBUTIONS (`docs/ATTRIBUTIONS.md`)

Wasmer Attributions

Wasmer is a community effort and makes use of code from various other
projects ❤️.
Listed below are notable sections of code that are licensed
from other projects and the relevant license of those projects.

These are the projects that were used as inspiration and/or that we are using code from.
Each of the subcrates we have an Acknowledgements section with more details.

Projects:

  • Emscripten: for emtests test sources to ensure compatibility - LICENSE
  • Nebulet: as the base for creating a great Rust WebAssembly runtime - LICENSE
  • WAVM: for their great integration and testing framework - LICENSE
  • wasmtime: for their API and internal documentation, as well as some internal implementations - LICENSE
  • WebAssembly spec: for the spectests implementation

🙏 Please let us know if you believe there is an error or omission in
this list and we will correct.

Licenses

Nebulet

text
MIT License

Copyright (c) 2018

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

WAVM

text
/* Detailed source-code truncated for AI context efficiency. */

Greenwasm

text
/* Detailed source-code truncated for AI context efficiency. */

Wasmtime

text
/* Detailed source-code truncated for AI context efficiency. */

Emscripten

text
/* Detailed source-code truncated for AI context efficiency. */

Zlib

text
version 1.3.1, January 22nd, 2024

  Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Jean-loup Gailly        Mark Adler
  [email protected]          [email protected]

bzip2-1.0.6

text
/* Detailed source-code truncated for AI context efficiency. */

BUILD (`docs/BUILD.md`)

Building Wasmer from Source

Installing Rustup

Wasmer supports building to the latest 3 stable releases, but pins
to one specific one at the time. rustup selects it automatically. See
rust-toolchain.toml for the current pin.
The easiest way to install Rust on your system is via Rustup. To get Rustup on Linux and macOS, you can run the following:

bash
curl https://sh.rustup.rs -sSf | sh

[!NOTE]
To install Rust on Windows, download and run rustup-init.exe, then follow the on-screen instructions.

Installing Additional Dependencies

Linux

Linux is fully supported by Wasmer. WASI(x) is also fully supported. Users
building from source can enable the LLVM backend following the instruction in
the dedicated section below and installing LLVM version 22. To install it,
refer to LLVM's download
page
or
check your distro's package manager.

macOS

macOS is fully supported by Wasmer. WASI(x) is also fully supported. Users
building from source can enable the LLVM backend following the instruction in
the dedicated section below and installing LLVM version 22. To install it on
macOS, you can use homebrew: brew install llvm@22.

Windows

Windows is fully supported by Wasmer. WASI(x) is also fully supported.

  1. Install Visual Studio
  2. Install Rust for Windows
  3. Install Git for Windows. Allow it to add git.exe to your PATH (default settings for the installer are fine).
  4. (optional) Install LLVM 22.1

Building the Wasmer Runtime

Wasmer is built with Cargo, the Rust package manager.

For reproducible builds, set WASMER_REPRODUCIBLE_BUILD=1 in the build
environment. This removes the build timestamp from wasmer --version -v
by omitting the verbose commit-date: line.

First, let's clone Wasmer along with its submodules:

text
git clone --recursive https://github.com/wasmerio/wasmer.git
cd wasmer

In an existing clone, initialize the submodules with
git submodule update --init --recursive.

Wasmer supports different backends at the moment: singlepass, cranelift, LLVM and V8.

Singlepass Compiler

The Singlepass compiler works on Linux, Darwin and Windows systems on amd64
platforms and on Linux and Darwin systems on aarch64 platforms. Currently, it
doesn't work on RISC-V or loongarch64. On system in which it can be used it
is enabled by default.

You can build Wasmer by running this command in the root of the repo:

text
make build-wasmer

Note: you should see singlepass appear in the Enabled Compilers: ... message in the console.

You may disable the Singlepass backend with the ENABLE_SINGLEPASS=0 environment
variable, and force its enabling with ENABLE_SINGLEPASS=1.

Cranelift Compiler

The Cranelift compiler will work if you are on a X86 or ARM machine. On system
in which it can be used it is enabled by default.

You can build Wasmer by running this command in the root of the repo:

text
make build-wasmer

Note: you should see cranelift appear in the Enabled Compilers: ... message in the console.

You may disable the Cranelift backend with the ENABLE_CRANELIFT=0 environment
variable, and force its enabling with ENABLE_CRANELIFT=1.

LLVM Compiler

If you want support for the Wasmer LLVM compiler, then you will also need to:

  • Ensure that LLVM 22 (>=22.1.x) is installed on your system. The backend
    needs LLVM 22 exactly; any other version silently disables it — read the
    Enabled Compilers: banner. The error Didn't find usable system-wide LLVM means LLVM 22 is missing.
  • In case llvm-config-22 is not on PATH, set the correct environment variable
    for LLVM to access: For example, the environment variable for LLVM 22.1.x
    would be: LLVM_SYS_221_PREFIX=/path/to/unpacked/llvm-22.1

And create a Wasmer release

bash
make build-wasmer

Note: you should see this in the console:
Enabled Compilers: llvm

You may disable the LLVM compiler with export ENABLE_LLVM=0.

V8

To enable the backend, you can set the according ENABLE_=1
flag at build time. The build script itself will download the necessary
libraries at build time.

Note, however, that these backends are not supported on all the platforms that
Wasmer can run on.

text
ENABLE_V8=1 make build-wasmer

All Compilers

Once you have LLVM and Rust, you can just run:

bash
make build-wasmer

Note: you should see this in the console:
Enabled Compilers: singlepass cranelift llvm

Iterating During Development

For fast iteration, run make check, or build one crate:

bash
cargo build -p wasmer-cli --features cranelift

make build-wasmer-debug builds a debug binary with tokio-console support.

Read the Enabled Compilers: banner that each make target prints. The
Makefile silently omits backends it cannot detect. V8 is never
autodetected.

The wasix-libc sysroot and Rust toolchain pins for CI live in
.github/ci-constants.env.

[!CAUTION]
Do not build with cargo build --workspace --features .
Workspace-level features do not reach subcrates. The result is a headless
binary that cannot compile Wasm. Use -p wasmer-cli or the Makefile.

Running Your Wasmer Binary

Once you run the make build-wasmer command, you will have a new binary ready to be used!

text
./target/release/wasmer quickjs.wasm

Building Wasmer C-API from Source

Wasmer provides a pre-compiled version for the C-API on its release page.

However, you can also compile the shared library from source:

text
make build-capi

This will generate the shared library (depending on your system):

  • Windows: target/release/libwasmer_c_api.dll
  • macOS: target/release/libwasmer_c_api.dylib
  • Linux: target/release/libwasmer_c_api.so

If you want to generate the library and headers for using them easily, you can execute:

bash
make package-capi

This command will generate a package directory, that you can then use easily in the Wasmer C API examples.

text
package/
  lib/
    libwasmer.so
  include/
    wasm.h
    wasmer.h

[!IMPORTANT]

By default, the Wasmer C API shared library will include all the backends available in the system where is built.
Defaulting to cranelift if available.

You can generate the C-API for a specific compiler and engine with:
make build-capi-{ENGINE}


CONTRIBUTING (`docs/CONTRIBUTING.md`)

How to Contribute to Wasmer

Thank you for your interest in contributing to Wasmer. This document
outlines the expectations for issues and pull requests.

Issues & Feature Requests

Please use the issue template and provide a failing example if possible to
help us recreate the issue.

[!WARNING]
Do not fix a security vulnerability in a public PR. Embargoed work goes
through the private process in SECURITY.md. A public fix
before disclosure exposes users.

Code Style

Sparse "why" comments. Short single-responsibility functions.

Lint and Format

CI rejects lint and format failures. Run before you push:

bash
make lint

The lint target in the Makefile defines exactly what
runs. To apply clippy fixes in bulk:

bash
cargo clippy --all --exclude wasmer-swift --locked --fix --allow-dirty -- -D clippy::all

cargo fmt does not cover lib/wasix/tests/wasm_tests. CI formats those
files with rustfmt --edition 2024 directly.

Pull Requests

For large changes, open a GitHub issue first to ensure we can accept the
change once it is ready.

  • Title format is conventional-commit style with crate or area scopes:
    fix(Singlepass): ..., feat(wasix): ..., feat!: ... for breaking
    changes, chore: ..., deps: ....
  • PRs are squash-merged to main. The PR template has one # Description
    section.
  • Before you submit: make lint, then cargo test in the crates you
    touched, then a build of the CLI.
  • Do not hand-edit CHANGELOG.md or crate versions. Releases generate
    both (see dev/release.md).
  • macOS and musl CI jobs run on a PR only when the PR has the macos or
    musl label. If your change touches platform code, add the label.
  • Do not commit a submodule pointer bump in an unrelated PR.

Common Build Issues

LLVM Dependency

Didn't find usable system-wide LLVM means LLVM 22 is missing. Either
install it or build with ENABLE_LLVM=0. See
Building Wasmer from Source for installation
instructions.


PACKAGING (`docs/PACKAGING.md`)

Wasmer OS distro packaging notes

  • Wasmer is written in Rust. To build Wasmer, where possible, do not
    directly invoke cargo, but use the supplied Makefile

  • For packaging purposes, use the provided wasmer-full-source.tar.gz,
    which includes all required submodules.

  • Wasmer provides several compilers and the Makefile autodetects
    when compilers can be compiled and/or installed. Set the environment
    variables ENABLE_{CRANELIFT,LLVM,SINGLEPASS}=1 to force compiler
    to be build or to fail trying, e.g:

    sh
    $ ENABLE_LLVM=1 make build-wasmer
  • make install respects DESTDIR, but prefix must be configured
    with WASMER_INSTALL_PREFIX. Note that DESTDIR must include
    WASMER_INSTALL_PREFIX, e.g.:

    sh
    export WASMER_INSTALL_PREFIX=/usr
    make
    DESTDIR=/tmp/staging/usr make install
  • In case you must build/install directly with cargo, make sure to
    enable at least one compiler feature, like e.g. --features cranelift,

    • Beware that compiling with cargo build --workspace --features …
      will not enable features on the subcrates in the workspace and
      result in a headless Wasmer binary that can not compile Wasm files
      directly.
  • For reproducible builds, set WASMER_REPRODUCIBLE_BUILD=1 in the
    build environment. This strips the build timestamp from
    wasmer --version -v by omitting the verbose commit-date: line,
    which is useful for distribution packaging.

  • If you split the package into several subpackages:

    • The wasmer-headless CLI contains a subset of the wasmer's functionalities
      and should only be packaged when splitting — it must be built
      explicitly with:

      sh
      $ make build-wasmer-headless-minimal install-wasmer-headless-minimal
    • libwasmer, containing libwasmer.so*,

    • libwasmer-dev, containing the header files and a .pc file,

    • libwasmer-static, containing libwasmer.a.

The Wasmer distro packaging story is still in its infancy, so feedback is very welcome.

Miscellaneous: binfmt_misc

Wasmer can be registered as a binfmt interpreter for wasm binaries.
An example systemd .service is included here.
Please consider statically linking the wasmer binary so that this capability is also available in mount namespaces.


RISCV (`docs/RISCV.md`)

Current state of the RISCV support

Only Cranelift and LLVM compiler are supported.
Singlepass can be done, but no resources are allocated on this task for now.

Both LLVM and Cranelift support are quite new, and so it is expected to have a few things not working well.

LLVM code needs a hack to force the ABI to "lp64d", and some tested with function & float/double values are still not working correctly and have be disable for now.

On Cranelift, SIMD is not supported as the CPU doesn't have official SIMD/Vector extension for now, and no Workaround is in place.

Test have be conducted on actual hardware, with a Vision Five 2 board running Debian. Some previous tests have also be done on a Vison Five 1 running Fedora (with LLVM only).


SECURITY (`docs/SECURITY.md`)

Security Policy

Supported Versions

The table below summarizes which versions are still supported, and which aren't.

Version Supported
0.x ❌
1.x ❌
2.x ❌
3.x ❌
4.x ❌
5.x ❌
6.x ✅
7.x ✅

Reporting a Vulnerability

The Wasmer team and community take security bugs in Wasmer seriously.
We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.

To report a security issue, email [email protected] or
[email protected] and include the word "SECURITY" in the subject line.

The Wasmer team will send a response indicating the next steps in handling your report.
After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.


TEST (`docs/TEST.md`)

Testing

Thanks to the WebAssembly spec tests
we can ensure 100% compatibility with the WebAssembly spec test suite.

Run the full local suite with make test (needs cargo-nextest;
make require-nextest installs it). It automatically detects the
compilers available on your system. Follow the
Building from Source guide to prepare your system with the
requirements for each backend.

The Makefile lists the individual test targets and their
purpose: the WAST spec tests per backend, the CLI, the examples, the
C API, and more.

It is also possible to test specific parts. One crate:

bash
cargo test -p wasmer-wasix --features sys

One test by name filter:

bash
cargo test --release --tests --features cranelift -- cranelift::spec::simd

Skipping Tests

If a test fails only on one backend or platform, add a line to
tests/ignores.txt with a reason (<compiler> <test> # reason). Do not
chase Singlepass failures for SIMD, relaxed SIMD, exception handling, or
wide arithmetic. Singlepass does not support these proposals.

To debug a failing WAST test, see
AGENTS.md.

WASIX Guest-Side Tests

WASIX guest-side tests live in lib/wasix/tests/wasm_tests/. They need
wasixcc and cargo-wasix on PATH. Fixture directives are documented in
lib/wasix/tests/wasm_tests.rs.

CI Coverage Gaps

macOS and musl CI jobs run on a PR only when the PR carries the macos or
musl label (see CONTRIBUTING.md). A PR can pass CI
and still break main on those platforms.


Journal (`docs/journal.md`)

WASM Journal Functionality

Wasmer now supports journals for the state of a WASM process. This gives the ability
to persist changes made to the temporary file system and to save and store snapshots
of the running process.

The journal file is a linear history of events that occurred when the process was
running that if replayed will bring the process made to a discrete and deterministic
state.

Journal files can be concatenated, compacted and filtered to change the discrete state.

These journals are maintained in a consistent and durable way thus ensuring that
failures of the system while the process is running does not corrupt the journal.

Snapshot Triggers

The journal will record state changes to the sandbox built around the WASM process as
it runs however it may be important to certain use-cases to take explicit snapshot
restoration points in the journal at key points that make sense.

When a snapshot is triggered all the running threads of the process are paused and
the state of the WASM memory and thread stacks are recorded into the journal so that
they can be restored.

In order to use the snapshot functionality the WASM process must be compiled with
the asyncify modifications, this can be done using the wasm-opt tool.

Note: If a process does not have the asyncify modifications you can still use
the journal functionality for recording the file system and WASM memory state
however the stacks of the threads will be omitted meaning a restoration will
restart the main thread.

Various triggers are possible that will cause a snapshot to be taken at a specific
point in time, these are as follows:

On Idle

Triggered when all the threads in the process go into an idle state. This trigger
is useful to take snapshots at convenient moments without causing unnecessary overhead.

For processes that have TTY/STDIN input this is particularly useful.

On FirstListen

Triggered when a listen syscall is invoked on a socket. This can be an important
milestone to take a snapshot when one wants to speed up the boot time of a WASM process
up to the moment where it is ready to accept requests.

On FirstStdin

Triggered when the process reads stdin for the first time. This can be useful to
speed up the boot time of a WASM process.

On FirstEnviron

Triggered when the process reads an environment variable for the first time. This can
be useful to speed up the boot time of a CGI WASM process which reads the environment
variables to parse the request that it must execute.

On Timer Interval

Triggered periodically based on a timer (default 10 seconds) which can be specified
using the journal-interval option. This can be useful for asynchronous replication
of a WASM process from one machine to another with a particular lag latency.

On Sigint (Ctrl+C)

Issued if the user sends an interrupt signal (Ctrl + C).

On Sigalrm

Alarm clock signal (used for timers)
(see man alarm)

On Sigtstp

The SIGTSTP signal is sent to a process by its controlling terminal to request it to stop
temporarily. It is commonly initiated by the user pressing Ctrl-Z.

On Sigstop

The SIGSTOP signal instructs the operating system to stop a process for later resumption

On Non Deterministic Call

When a non-deterministic call is made from WASM process to the outside world (i.e. it reaches
out of the sandbox)

Limitations

  • The WASM process that wish to record the state of the threads must have had the asyncify
    post processing step applied to the binary (see wasm-opt).
  • Taking a snapshot can consume large amounts of memory while its processing.
  • Snapshots are not instant and have overhead when generating.
  • The layout of the memory must be known by the runtime in order to take snapshots.

Design

On startup if the restore journal file is specified then the runtime will restore the
state of the WASM process by reading and processing the log entries in the snapshot
journal. This restoration will bring the memory and the thread stacks back to a previous
point in time and then resume all the threads.

When a trigger occurs a new journal will be taken of the WASM process which will
take the following steps:

  1. Pause all threads
  2. Capture the stack of each thread
  3. Write the thread state to the journal
  4. Write the memory (excluding stacks) to the journal
  5. Resume execution.

The implementation is currently able to save and restore the following:

  • WASM Memory
  • Stack memory
  • Call stack
  • Open sockets
  • Open files
  • Terminal text

Journal Capturer Implementations

Log File Journal

Writes the log events to a linear log file on the local file system
as they are received by the trait. Log files can be concatenated
together to make larger log files.

Unsupported Journal

The default implementation does not support snapshots and will error
out if an attempt is made to send it events. Using the unsupported
capturer as a restoration point will restore nothing but will not
error out.

Compacting Journal

Deduplicates memory and stacks to reduce the number of volume of
log events sent to its inner capturer. Compacting the events occurs
in line as the events are generated

Filtered Journal

Filters out a specific set of log events and drops the rest, this
capturer can be useful for restoring to a previous call point but
retaining the memory changes (e.g. WCGI runner).

Improvements

https://codesandbox.io/blog/how-we-scale-our-microvm-infrastructure-using-low-latency-memory-decompression


Migration To 1.0.0 (`docs/migration_to_1.0.0.md`)

Migrating from Wasmer 0.x to Wasmer 1.0.0

Wasmer 1.0.0 is getting ready for a full release and is our primary focus. This document will
describe the differences between Wasmer 0.x and Wasmer 1.0.0 and provide examples
to make migrating to the new API as simple as possible.

Table of Contents

Rationale for changes in 1.0.0

Wasmer 0.x was great but as the Wasm community and standards evolve we felt the need to make Wasmer also follow these
changes.

Wasmer 1.x is what we think a necessary rewrite of a big part of the project to make it more future-proof.

This version introduces many new features and makes using Wasmer more natural. We did a hard work making it as close
to the standard API as possible while always providing good performances, flexibility and stability.

The rewrite of the Wasmer Runtime also comes with a rewrite of the languages integrations to achieve the same goals:
providing a clearer API and improving the feature set.

In this document you will discover the major changes between Wasmer 0.x and Wasmer 1.x by highlighting how to use the
new Rust API.

How to use Wasmer 1.0.0

Installing Wasmer CLI

See wasmer.io for installation instructions.

If you already have wasmer installed, run wasmer self-update.

Install the latest versions of Wasmer with wasmer-nightly or by following the steps described in the
documentation: Getting Started.

Using Wasmer 1.0.0

The CLI interface for Wasmer 1.0.0 is mostly the same as it was in Wasmer 0.x.

One difference is that rather than specifying the compiler with --backend=cranelift,
in Wasmer 1.0.0 we prefer using the name of the backend as a flag directly,
for example: --cranelift.

The top-level crates that users will usually interface with are:

See the examples to find out how to do specific things in Wasmer 1.0.0.

Project Structure

The figure above shows the core Wasmer crates and their dependencies with transitive dependencies deduplicated.

Wasmer 1.0.0 has two core architectural abstractions: engines and compilers.

An engine is a system that processes Wasm with a compiler and prepares it to be executed.

A compiler is a system that translates Wasm into a format that can be understood
more directly by a real computer: machine code.

For example, in the examples you'll see that we are using the JIT engine and the Cranelift compiler. The JIT engine
will generate machine code at runtime, using Cranelift, and then execute it.

For most uses, users will primarily use the wasmer crate directly, perhaps with one of our
provided ABIs such as wasmer-wasi. However, for users that need finer grained control over
the behavior of wasmer, other crates such as wasmer-compiler and wasmer-engine may be used
to implement custom compilers and engines respectively.

Differences

Instantiating modules

With Wasmer 0.x, instantiating a module was a matter of calling wasmer::compiler::compile and then calling
instantiate on the compiled module.

While simple, this did not give you full-control over Wasmer's configuration. For example, choosing another compiler
was not straightforward.

With Wasmer 1.x, we changed this part and made the API look more like how Wasmer works internally to give you more
control:

diff
- let module = compile(&wasm_bytes[..])?; 
+ let engine = JIT::new(Cranelift::default()).engine();
+ let store = Store::new(&engine);
+ let module = Module::new(&store, wasm_bytes)?;
- let instance = module.instantiate(&imports)?;
+ let instance = Instance::new(&module, &import_object)?;

Note that we did not cover how to create the import object here. This is because this part works the same as it used to
with Wasmer 0.x.

To get more information on how instantiation now works, have a look at the dedicated example

Passing host functions

With Wasmer 0.x passing host functions to the guest was primarily done using the func! macro or by directly using
Func::new or DynamicFunc::new.

In Wasmer 1.0 the equivalent of Func::new is Function::new_native /
Function::new_native_with_env and the equivalent of DynamicFunc::new
is Function::new / Function::new_with_env.

Given we have a function like:

rust
fn sum(a: i32, b: i32) -> i32 {
    a + b
}

We want to import this function in the guest module, let's have a look at how it differs between Wasmer 0.x and
Wasmer 1.x:

diff
let import_object = imports! {
    "env" => {
-         "sum" => func!(sum),
+         "sum" => Function::new_native(&store, sum),
    }
}

The above example illustrates how to import what we call "native functions". There were already available in Wasmer
0.x through the func! macro or with Func::new.

There is a second flavor for imported functions: dynamic functions. With Wasmer 0.x you would have created such a
function using DynamicFunc::new, here is how it's done with Wasmer 1.x:

rust
let sum_signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]);
let sum = Function::new(&store, &sum_signature, |args| {
    let result = args[0].unwrap_I32() + args[1].unwrap_i32();
    
    Ok(vec![Value::I32(result)])
});

Both examples address different needs and have their own pros and cons. We encourage you to have a look at the
dedicated example: Exposing host functions.

Note that having this API for functions now looks more like the other entities APIs: globals, memories, tables. Here is
a quick example introducing each of them: Imports & Exports

Accessing the environment as a host function

With Wasmer 0.x each function had its own vm::Ctx. This was your entrypoint to the module internals and allowed
access to the context of the currently running instance.

With Wasmer 1.0.0 this was changed to provide a simpler yet powerful API.

Let's see an example where we want to have access to the module memory. Here is how that changed from 0.x to 1.0.0:

diff
+ #[derive(WasmerEnv, Clone, Default)]
+ struct MyEnv {
+     #[wasmer(export)]
+     memory: LazyInit<Memory>,
+ }
+ let env = MyEnv::default();
+
- let get_at = |ctx: &mut vm::Ctx, ptr: WasmPtr<u8, Array>, len: u32| {
+ let get_at = |env: &MyEnv, ptr: WasmPtr<u8, Array>, len: u32| {
-     let mem_desc = ctx.memory(0);
-     let mem = mem_desc.deref();
+     let mem = env.memory_ref().unwrap();
  
      println!("Memory: {:?}", mem);
  
      let string = ptr.get_utf8_string(mem, len).unwrap();
      println!("string: {}", string);
  };

  let import_object = imports! {
      "env" => {
-         "get_at" => func!(get_at),
+         "get_at" => Function::new_native_with_env(&store, env.clone(), get_at),
      }
  };

- let instance = instantiate(wasm_bytes, &import_object)?;
+ let instance = Instance::new(&wasm_bytes, &import_object)?;

Here we have a module which provides one exported function: get. Each time we call this function it will in turn
call our imported function get_at.

The get_at function is responsible for reading the guest module-s memory through the vm::Ctx.

With Wasmer 1.0.0 (where the vm::Ctx does not exist anymore) we can achieve the same result with something more
natural: we only use imports and exports to read from the memory and write to it.

However in order to provide an easy to use interface, we now have a trait
that can be implemented with a derive macro: WasmerEnv. We must make our
env types implement WasmerEnv and Clone. We mark an internal field
wrapped with LazyInit with #[wasmer(export)] to indicate that the type
should be found in the Wasm exports with the name of the field
("memory"). The derive macro then generates helper functions such as
memory_ref on the type for easy access to these fields.

See the WasmerEnv
docs for more information.

Take a look at the following examples to get more details:

The other thing where vm::Ctx was useful was to pass data from and to host functions. This has also been made simpler
with Wasmer 1.x:

rust
let shared_counter: Arc<RefCell<i32>> = Arc::new(RefCell::new(0));

#[derive(WasmerEnv, Clone)]
struct Env {
    counter: Arc<RefCell<i32>>,
}

fn get_counter(env: &Env) -> i32 {
    *env.counter.borrow()
}

let get_counter_func = Function::new_native_with_env(
    &store, 
    Env { counter: shared_counter.clone() }, 
    get_counter
);

A dedicated example describes how to use this feature: Exposing host functions.

Error handling

Handling errors with Wasmer 0.x was a bit hard, especially, the wasmer_runtime::error::RuntimeError. It was rather
complex: it had many variants that you had to handle when pattern matching results. This has been made way simpler with
Wasmer 1.0.0:

diff
// Retrieve the `get` function from module's exports and then call it
let result = get.call(0, 13);

match result {
-     Err(RuntimeError::InvokeError(InvokeError::TrapCode { .. })) => {
-         // ...
-     }
-     Err(RuntimeError::InvokeError(InvokeError::FailedWithNoError)) => {
-         // ...
-     }
-     Err(RuntimeError::InvokeError(InvokeError::UnknownTrap { .. })) => {
-         // ...
-     }
-     Err(RuntimeError::InvokeError(InvokeError::UnknownTrapCode { .. })) => {
-         // ...
-     }
-     Err(RuntimeError::InvokeError(InvokeError::EarlyTrap(_))) => {
-         // ...
-     }
-     Err(RuntimeError::InvokeError(InvokeError::Breakpoint(_))) => {
-         // ...
-     }
-     Err(RuntimeError::Metering(_)) => {
-         // ...
-     }
-     Err(RuntimeError::InstanceImage(_)) => {
-         // ...
-     }
-     Err(RuntimeError::User(_)) => {
-         // ...
-     }
+     Error(e) => {
+         println!("Error caught from `div_by_zero`: {}", e.message());
+          
+         let frames = e.trace();
+         let frames_len = frames.len();
+         
+         // ...
+     }
    Ok(_) => {
        // ...
    },
}

As you can see here, handling errors is really easy now! You may find the following examples useful to get more familiar
with this topic:

Note that with Wasmer 1.0.0, each function that is part of the API has its own kind of error. For example:

  • Instantiating a module may return InstantiationErrors;
  • Getting exports from the guest module may return ExportErrors;
  • Calling an exported function may return RuntimeErrors;
  • ...

Caching modules

You may be aware Wasmer, since 0.x, allows you to cache compiled module so that further executions of your program
will be faster.

Because caching may bring a significant boost when running Wasm modules we wanted to make it easier to use with
Wasmer 1.0.0.

With Wasmer 0.x you had to handle the whole caching process inside your program's code. With Wasmer 1.0.0
you'll be able to delegate most of the work to Wasmer:

diff
- let artifact = module.cache().unwrap();
- let bytes = artifact.serialize().unwrap();
- 
- let path = "module_cached.so";
- fs::write(path, bytes).unwrap();
+ module.serialize_to_file(path)?;

- let mut file = File::open(path).unwrap();
- let cached_bytes = &mut vec![];
- file.read_to_end(cached_bytes);
- drop(file);
- 
- let cached_artifact = Artifact::deserialize(&cached_bytes).unwrap();
- let cached_module = unsafe { load_cache_with(cached_artifact, &default_compiler()) }.unwrap();
+ let cached_module = unsafe { Module::deserialize_from_file(&store, path) }?;

Migration To 3.0.0 (`docs/migration_to_3.0.0.md`)

Migrating from Wasmer 2.x to Wasmer 3.0.0

This document will describe the differences between Wasmer 2.x and Wasmer 3.0.0
and provide examples to make migrating to the new API as simple as possible.

Table of Contents

Rationale for changes in 3.0.0

This version introduces the following changes to make the Wasmer API more ergonomic and safe:

  1. ImportsObject and the traits Resolver, NamedResolver, etc have been removed and replaced with a single simple type Imports. This reduces the complexity of setting up an Instance. The helper macro imports! can still be used.
  2. The Store will keep track of all memory and functions used, removing old tracking and Weak/Strong pointer usage. Every function and memory that can be defined is associated to a specific Store, and cannot be mixed with another Store
  3. NativeFunc has been renamed to TypedFunction, accordingly the following functions have been renamed:
    • Function::native(…) → Function::typed(…)
    • Function::new_native(…) → Function::new_typed(…)
    • Function::new_native_with_env(…) → Function::new_typed_with_env(…)
      The previous variants still exist in order to support the migration, but they have been deprecated.
  4. WasmerEnv and associated traits and macro have been removed. To use a function environment, you will need to create a FunctionEnv object and pass it along when you construct the function. For convenience, these functions also exist in a variant without the environment for simpler use cases that don't need it. For the variants with the environment, it can be retrieved from the first argument of the function. Because the WasmerEnv and all helpers don't exists anymore, you have to import memory yourself, there isn't any per instance initialisation automatically done anymore. It's especially important in wasi use with WasiEnv. Env can be accessed from a FunctionEnvMut<'_, WasiEnv> using FunctionEnvMut::data() or FunctionEnvMut::data_mut().
  5. The Engines API has been simplified, Instead of the user choosing and setting up an engine explicitly, everything now uses a single engine. All functionalities of the universal, staticlib and dylib engines should be available in this new engine unless explicitly stated as unsupported.
  6. Loupe has been removed. Memory inspection should be done manually

How to use Wasmer 3.0.0

Installing Wasmer CLI

See wasmer.io for installation instructions.

If you already have wasmer installed, run wasmer self-update.

Install the latest versions of Wasmer with wasmer-nightly or by following the
steps described in the documentation: Getting Started.

Using Wasmer 3.0.0

One of the main changes in 3.0.0 is that Store now owns all WebAssembly objects; thus exports like a Memory are merely handles to the actual memory object inside the store. To read/write any such value you will always need a Store reference.

If you define your own function, when the function is called it will hence need a reference to the store in order to access WebAssembly objects. This is achieved by the StoreRef<'_> and StoreMut<'_> types, which borrow from the store and provide access to its data. Furthermore, to prevent borrowing issues you can create new StoreRef and StoreMuts whenever you need to pass one at another function. This is done with the AsStoreRef, AsStoreMut traits.

See the examples to find out how to do specific things in Wasmer 3.0.0.

Project Structure

A lot of types were moved to wasmer-types crate. There are no engine crates anymore; all the logic is included in wasmer-compiler.

Differences

`WasmerEnv` is removed in favor of `FunctionEnv`

WasmerEnv has been removed in Wasmer 3.0 in favor of FunctionEnv, which is now shareable automatically between functions without requiring the environment to be cloneable.

rust
let my_counter = 0_i32;
let env = FunctionEnv::new(&mut store, my_counter);

Note: Any type can be passed as the environment: (Nota bene the passed type T must implement the Any trait, that is, any type which contains a non-'static reference.)

rust
struct Env {
    counter: i32,
}
let env = FunctionEnv::new(&mut store, Env {counter: 0});

Here's how the code depending on WasmerEnv should evolve:

Before

rust
#[derive(wasmer::WasmerEnv, Clone)]
pub struct MyEnv {
    #[wasmer(export)]
    pub memory: wasmer::LazyInit<Memory>,
    #[wasmer(export(name = "__alloc"))]
    pub alloc_guest_memory: LazyInit<NativeFunc<u32, i32>>,

    pub multiply_by: u32,
}

let my_env = MyEnv {
  memory: Default::default(),
  alloc_guest_memory: Default::default(),
  multiply_by: 10,
};

let instance = Instance::new(&module, &imports);

After

rust
pub struct MyEnv {
    pub memory: Option<Memory>,
    pub alloc_guest_memory: Option<TypedFunction<i32, i32>>,
    pub multiply_by: u32,
}

let env = FunctionEnv::new(&mut store, MyEnv {
  memory: None,
  alloc_guest_memory: None,
  multiply_by: 10,
});

let instance = Instance::new(&mut store, &module, &imports)?;
let mut env_mut = env.into_mut(&mut store); // change to a FunctionEnvMut
let (mut data_mut, mut store_mut) = env_mut.data_and_store_mut(); // grab data and a new store_mut
data_mut.memory = Some(instance.exports.get_memory("memory")?.clone());
data_mut.alloc_guest_memory = Some(instance.exports.get_typed_function(&mut store_mut, "__alloc")?);

New `MemoryView` API (preparation for shared memory)

Reading from memory has slightly changed compared to 2.x:

rust
// 2.x
let memory = instance.exports.get_memory("mem")?;
println!("Memory size (pages) {:?}", memory.size());
println!("Memory size (bytes) {:?}", memory.data_size());

let load = instance
    .exports
    .get_native_function::<(), (WasmPtr<u8, Array>, i32)>("load")?;

let (ptr, length) = load.call(&mut store)?;
let str = ptr.get_utf8_string(memory, length as u32).unwrap();
println!("Memory contents: {:?}", str);
rust
// 3.x
let memory = instance.exports.get_memory("mem")?;
let memory_view = memory.view(&store);
println!("Memory size (pages) {:?}", memory_view.size());
println!("Memory size (bytes) {:?}", memory_view.data_size());

let load: TypedFunction<(), (WasmPtr<u8>, i32)> =
    instance.exports.get_typed_function(&mut store, "load")?;

let (ptr, length) = load.call(&mut store)?;
let memory_view = memory.view(&store);
let str = ptr.read_utf8_string(&memory_view, length as u32).unwrap();
println!("Memory contents: {:?}", str);

The reason for this change is that in the future this will enable
safely sharing memory across threads. The same thing goes for reading slices:

rust
// 2.x
let new_str = b"Hello, Wasmer!";
let values = ptr.deref(memory, 0, new_str.len() as u32).unwrap();
for i in 0..new_str.len() {
    values[i].set(new_str[i]);
}
rust
// 3.x
let memory_view = memory.view(&store); // (can be reused)
let new_str = b"Hello, Wasmer!";
let values = ptr.slice(&memory_view, new_str.len() as u32).unwrap();
for i in 0..new_str.len() {
    values.index(i as u64).write(new_str[i]).unwrap();
}

Managing imports

Instantiating a Wasm module is similar to 2.x;

rust
let import_object: Imports = imports! {
    "env" => {
        "host_function" => host_function,
    },
};
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");

You can also build the Imports object manually:

rust
let mut import_object: Imports = Imports::new();
import_object.define("env", "host_function", host_function);
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");

For WASI, don't forget to initialize the WasiEnv (it will import the memory)

rust
let mut wasi_env = WasiState::builder("hello").finalize()?;
let import_object = wasi_env.import_object(&mut store, &module)?;
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
wasi_env.initialize(&mut store, &instance).unwrap();

`ChainableNamedResolver` is removed

Chaining imports with a trait has been deemed too complex for what it does; it's possible to chain (i.e. override) an Imports' contents by using its implementation of std::iter::Extend from the Rust standard library:

rust
let imports1: Imports = todo!();
let mut imports2: Imports = todo!();

imports2.extend(&imports);
// This is equivalent to the following:
// for ((ns, name), ext) in imports1.into_iter() {
//     imports2.define(&ns &name, ext);
// }

Engines

Before

In Wasmer 2.0, you had to explicitly define the Engine you want to use:

rust
let wasm_bytes = wat2wasm(
    "..".as_bytes(),
)?;

let compiler_config = Cranelift::default();
let engine = Universal::new(compiler_config).engine();
let mut store = Store::new(&engine);
let module = Module::new(&store, wasm_bytes)?;
let instance = Instance::new(&module, &imports! {})?;

After

In Wasmer 3.0, there's only one engine. The user can ignore the engine details when using the API:

rust
let wasm_bytes = wat2wasm(
    "..".as_bytes(),
)?;

let compiler = Cranelift::default();
let mut store = Store::new(compiler);
let module = Module::new(&store, wasm_bytes)?;
let instance = Instance::new(&mut store, &module, &imports! {})?;

Advanced configuration

The previous ability to define target and features remains in a new EngineBuilder interface:

rust
let compiler = Cranelift::default();

let mut features = Features::new();
// Enable the multi-value feature.
features.multi_value(true);

let engine = EngineBuilder::new(compiler).set_features(Some(features));
let store = Store::new(engine);

C-API

The WASM C-API hasn't changed. Some wasmer-specific functions have changed, that relate to setting up WASI environments.

  • wasi_env_new function changed input parameters to accommodate the new Store API, it now is:
    c
    struct wasi_env_t *wasi_env_new(wasm_store_t *store, struct wasi_config_t *config);
  • wasi_get_imports function changed input parameters to accommodate the new Store API, it now is:
    c
    bool wasi_get_imports(const wasm_store_t *_store,
                          struct wasi_env_t *wasi_env,
                          const wasm_module_t *module,
                          wasm_extern_vec_t *imports);
  • wasi_env_set_memory was added. It's necessary to set the WasiEnv memory by getting it from Instances memory exports after its initialization. This must be performed in a specific order:
    1. Create WasiEnv
    2. Create Instance
    3. Get Instance Exports
    4. Find Memory from Instance Exports and store it to WasiEnv
      The function's signature is:
    c
    void wasi_env_set_memory(struct wasi_env_t *env, const wasm_memory_t *memory);

Dev Release (`docs/dev/release.md`)

Release Process

The release process of wasmer is mostly automated, including generating the CHANGELOG,
tagging the release and starting the build.yaml action

In the /scripts folder, you will see three files:

  • update-version.py: iterates through all Cargo.toml files and bumps the version number
    according to PREVIOUS_VERSION and NEXT_VERSION
  • publish.py: resolves the dependency order and publishes all crates to crates.io
  • make-release.py: creates a new pull request from the current master branch, generates the
    CHANGELOG, waits until all checks have passed and the release PR is merged, then starts the
    GitHub action to trigger the actual release on GitHub.

In theory, all you need to do to create a new release is to look that master is green, then
run python3 scripts/make-release.py 3.2.0 - in practice the script can sometimes lock up or
break due to unexpected delays for example it takes a couple of seconds between a pull request
being merged and master being updated. Therefore it's best to run each step individually and
make sure that every step finishes properly.

sh
# required before starting
gh login

# Script will create a release PR (release-3.2.0) and loop until the 
# release PR is merged into master (after checks are green)
python3 scripts/make-release.py 3.2.0

# After the release PR is merged, the build.yml workflow should be
# triggered automatically - if it isn't, trigger it manually
git checkout master
git tag v3.2.0 && git push origin v3.2.0
gh workflow run build.yml --ref v3.2.0 --field release=v3.2.0

# After the release is done on GitHub, run the script again 
# to update the release notes
python3 scripts/make-release.py 3.2.0

# Once the release on GitHub is properly done and verified that all
# artifacts exist, checkout the tag and run the publishing to crates.io
git checkout v3.2.0
python3 scripts/publish.py publish

After the GitHub release (first command), the crates need to be
published to crates.io - the order is important because if anything
goes wrong in the first command or a release needs to be amended
because of last-minute fixes, we can still revert the GitHub release,
but publishing on crates.io is final because we can't yank crates
(this has caused a lot of version-renumbering issues in the past).

Issues to watch out for

There are a couple of problems with the scripts that you should watch out for:

  • On the release pull request, the CHANGELOG might be generated incorrectly or with wrong line endings
  • If the script fails, there should be an audible message (implemented using the say command), so that you
    can leave the script running in the background and get notified if anything goes wrong.
  • The script might not trigger the build.yml action, in some cases it has to be run manually
  • Publishing to crates.io might fail because of new crates that have to be published manually.
    • It is important to adjust the SETTINGS in the publish.py script if some crates need default-features
      to be enabled when publishing
    • crates that were never published before need to usually be published for the first time
      by cd lib/crate && cargo publish
  • After publishing new crates, check that the crate ownership is set to github:wasmerio:wasmer-core.
  • The CHANGELOG is generated from the pull request titles since the last release. Sometimes these titles need
    to be fixed up to make any sense for a reader
  • The release notes should just highlight the most important changes for a release, not dump everything.
  • The following files should be released (TODO: more consistent naming schema):
    • wasmer-darwin-arm64.tar.gz
    • wasmer-linux-aarch64.tar.gz
    • wasmer-linux-amd64.tar.gz
    • wasmer-linux-musl-amd64.tar.gz
    • wasmer-windows-amd64.tar.gz
    • wasmer-windows-gnu64.tar.gz
    • wasmer-windows.exe

Videos


En Examples Coredump (`docs/en/examples-coredump.md`)

Using Wasm coredump

The following steps describe how to debug using Wasm coredump in Wasmer:

  1. Compile your WebAssembly with debug info enabled; for example:

    sh
    $ rustc foo.rs --target=wasm32-wasi -C debuginfo=2

    foo.rs

    fn c(v: usize) {
    a(v - 3);

    }

    fn b(v: usize) {
    c(v - 3);

    }

    fn a(v: usize) {
    b(v - 3);

    }

    pub fn main() {
    a(10);

    }

  2. Run with Wasmer and Wasm coredump enabled:

    sh
    $ wasmer --coredump-on-trap=/tmp/coredump foo.wasm
    
    thread 'main' panicked at 'attempt to subtract with overflow', foo.rs:10:7
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    Error: failed to run main module `foo.wasm`
    
    Caused by:
        0: Core dumped at /tmp/coredump
        1: failed to invoke command default
        2: error while executing at wasm backtrace:
                    ...
  3. Use wasmgdb to debug:

    sh
    $ wasmgdb foo.wasm /tmp/coredump
    
    wasmgdb> bt
    ...
    #13     000175 as panic () at library/core/src/panicking.rs
    #12     000010 as a (v=???) at /path/to/foo.rs
    #11     000009 as c (v=???) at /path/to/foo.rs
    #10     000011 as b (v=???) at /path/to/foo.rs
    #9      000010 as a (v=???) at /path/to/foo.rs
    #8      000012 as main () at /path/to/foo.rs
    ...

Schema Generated Jsonschema Types AppConfigV1.Schema.Json (`docs/schema/generated/jsonschema/types/AppConfigV1.schema.json`)

{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "AppConfigV1",
"description": "User-facing app.yaml config file for apps.\n\nNOTE: only used by the backend; Edge itself does not use this format and\nrelies on the internal AppVersionV1Spec representation instead.",
"type": "object",
"properties": {
"app_id": {
"description": "App id assigned by the backend.\n\nThis will get populated once the app has been deployed.\n\nThis id is also used to map to the existing app during deployments.",
"type": [
"string",
"null"
]
},
"capabilities": {
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMapV1"
},
{
"type": "null"
}
]
},
"cli_args": {
"description": "Only applicable for runners that accept CLI arguments.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"debug": {
"description": "Enable debug mode, which will show detailed error pages in the web gateway.",
"type": [
"boolean",
"null"
]
},
"domains": {
"description": "Domains for the app.\n\nThis can include both provider-supplied\nalias domains and custom domains.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"env": {
"description": "Environment variables.",
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"health_checks": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HealthCheckV1"
}
},
"jobs": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/Job"
}
},
"locality": {
"description": "Location-related configuration for the app.",
"anyOf": [
{
"$ref": "#/$defs/Locality"
},
{
"type": "null"
}
]
},
"name": {
"description": "Name of the app.",
"type": [
"string",
"null"
]
},
"owner": {
"description": "Owner of the app.\n\nThis is either a username or a namespace.",
"type": [
"string",
"null"
]
},
"package": {
"description": "The package to execute.",
"$ref": "#/$defs/PackageSource"
},
"redirect": {
"anyOf": [
{
"$ref": "#/$defs/Redirect"
},
{
"type": "null"
}
]
},
"scaling": {
"anyOf": [
{
"$ref": "#/$defs/AppScalingConfigV1"
},
{
"type": "null"
}
]
},
"scheduled_tasks": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppScheduledTask"
}
},
"volumes": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppVolume"
}
}
},
"additionalProperties": true,
"required": [
"package"
],
"$defs": {
"AppConfigCapabilityCdnCacheV1": {
"description": "CDN cache capability settings.",
"type": "object",
"properties": {
"enabled": {
"description": "Enable CDN caching for the app.",
"type": [
"boolean",
"null"
]
}
},
"additionalProperties": true
},
"AppConfigCapabilityInstaBootV1": {
"description": "Enables accelerated instance boot times with startup snapshots.\n\nHow it works:\nThe Edge runtime will create a pre-initialized snapshot of apps that is\nready to serve requests\nYour app will then restore from the generated snapshot, which has the\npotential to significantly speed up cold starts.\n\nTo drive the initialization, multiple http requests can be specified.\nAll the specified requests will be sent to the app before the snapshot is\ncreated, allowing the app to pre-load files, pre initialize caches, ...",
"type": "object",
"properties": {
"max_age": {
"description": "Maximum age of snapshots.\n\nFormat: 5m, 1h, 2d, ...\n\nAfter the specified time new snapshots will be created, and the old\nones discarded.",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"mode": {
"description": "The method to use to generate the instaboot snapshot for the instance.",
"anyOf": [
{
"$ref": "#/$defs/InstabootSnapshotModeV1"
},
{
"type": "null"
}
],
"default": null
},
"requests": {
"description": "HTTP requests to perform during startup snapshot creation.\nApps can perform all the appropriate warmup logic in these requests.\n\nNOTE: if no requests are configured, then a single HTTP\nrequest to '/' will be performed instead.",
"type": "array",
"items": {
"$ref": "#/$defs/HttpRequest"
}
}
}
},
"AppConfigCapabilityMapV1": {
"description": "Restricted version of the internal CapabilityMapV1, with only a select\nsubset of settings.",
"type": "object",
"properties": {
"cdn_cache": {
"description": "CDN cache settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityCdnCacheV1"
},
{
"type": "null"
}
]
},
"instaboot": {
"description": "Enables app bootstrapping with startup snapshots.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityInstaBootV1"
},
{
"type": "null"
}
]
},
"memory": {
"description": "Instance memory settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMemoryV1"
},
{
"type": "null"
}
]
},
"runtime": {
"description": "Runtime settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityRuntimeV1"
},
{
"type": "null"
}
]
},
"ssh": {
"anyOf": [
{
"$ref": "#/$defs/CapabilitySshServerV1"
},
{
"type": "null"
}
]
}
},
"additionalProperties": true
},
"AppConfigCapabilityMemoryV1": {
"description": "Memory capability settings.\n\nNOTE: this is kept separate from the internal CapabilityMemoryV1 struct\nto keep the high-level app.yaml distinct from the internal App entity.",
"type": "object",
"properties": {
"limit": {
"description": "Memory limit for an instance.\n\nFormat: [digit][unit], where unit is Mb/Gb/MiB/GiB,...",
"type": [
"string",
"null"
]
}
}
},
"AppConfigCapabilityRuntimeV1": {
"description": "Runtime capability settings.",
"type": "object",
"properties": {
"async_threads": {
"description": "Whether to enable asynchronous threads/deep sleeping.",
"type": [
"boolean",
"null"
]
},
"engine": {
"description": "Engine to use for an instance, e.g. wasmer_cranelift, wasmer_llvm, etc.",
"type": [
"string",
"null"
]
}
}
},
"AppScalingConfigV1": {
"type": "object",
"properties": {
"mode": {
"anyOf": [
{
"$ref": "#/$defs/AppScalingModeV1"
},
{
"type": "null"
}
]
}
}
},
"AppScalingModeV1": {
"type": "string",
"enum": [
"single_concurrency"
]
},
"AppScheduledTask": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": [
"name"
]
},
"AppVolume": {
"type": "object",
"properties": {
"mount": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"name",
"mount"
]
},
"CapabilitySshServerV1": {
"description": "Configure SSH server credentials and settings.",
"type": "object",
"properties": {
"enabled": {
"description": "Enable an SSH server.",
"type": [
"boolean",
"null"
]
},
"users": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/SshUserV1"
}
}
},
"additionalProperties": true
},
"ExecutableJob": {
"type": "object",
"properties": {
"capabilities": {
"anyOf": [
{
"$ref": "#/$defs/ExecutableJobCompatibilityMapV1"
},
{
"type": "null"
}
]
},
"cli_args": {
"description": "CLI arguments passed to the runner.\nOnly applicable for runners that accept CLI arguments.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"command": {
"description": "The command to run. Defaults to the package's entrypoint.",
"type": [
"string",
"null"
]
},
"env": {
"description": "Environment variables.",
"type": [
"object",
"null"
],
"additionalProperties": {
"type": "string"
}
},
"package": {
"description": "The package that contains the command to run. Defaults to the app config's package.",
"anyOf": [
{
"$ref": "#/$defs/PackageSource"
},
{
"type": "null"
}
]
},
"volumes": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/AppVolume"
}
}
}
},
"ExecutableJobCompatibilityMapV1": {
"type": "object",
"properties": {
"memory": {
"description": "Instance memory settings.",
"anyOf": [
{
"$ref": "#/$defs/AppConfigCapabilityMemoryV1"
},
{
"type": "null"
}
]
}
},
"additionalProperties": true
},
"HealthCheckHttpV1": {
"description": "Health check configuration for http endpoints.",
"type": "object",
"properties": {
"body": {
"description": "Request body as a string.",
"type": [
"string",
"null"
]
},
"expect": {
"anyOf": [
{
"$ref": "#/$defs/HttpRequestExpect"
},
{
"type": "null"
}
]
},
"headers": {
"description": "HTTP headers added to the request.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HttpHeader"
}
},
"healthy_threshold": {
"description": "Number of retries before the health check is considered healthy again.\n\nDefaults to 1.",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
},
"interval": {
"description": "Interval for the health check.\n\nFormat: 1s, 5m, 11h, ...\n\nDefaults to 60s.",
"type": [
"string",
"null"
]
},
"method": {
"description": "HTTP method.\n\nDefaults to GET.",
"type": [
"string",
"null"
]
},
"path": {
"description": "Request path.",
"type": "string"
},
"timeout": {
"description": "Request timeout.\n\nFormat: 1s, 5m, 11h, ...",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"unhealthy_threshold": {
"description": "Number of retries before the health check is considered unhealthy.\n\nDefaults to 1.",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
}
},
"required": [
"path"
]
},
"HealthCheckV1": {
"oneOf": [
{
"type": "object",
"properties": {
"http": {
"$ref": "#/$defs/HealthCheckHttpV1"
}
},
"additionalProperties": false,
"required": [
"http"
]
}
]
},
"HttpHeader": {
"description": "Definition for an HTTP header.",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
},
"required": [
"name",
"value"
]
},
"HttpRequest": {
"description": "Defines an HTTP request.",
"type": "object",
"properties": {
"body": {
"description": "Request body as a string.",
"type": [
"string",
"null"
]
},
"expect": {
"anyOf": [
{
"$ref": "#/$defs/HttpRequestExpect"
},
{
"type": "null"
}
]
},
"headers": {
"description": "HTTP headers added to the request.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/HttpHeader"
}
},
"method": {
"description": "HTTP method.\n\nDefaults to GET.",
"type": [
"string",
"null"
]
},
"path": {
"description": "Request path.",
"type": "string"
},
"timeout": {
"description": "Request timeout.\n\nFormat: 1s, 5m, 11h, ...",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
}
},
"required": [
"path"
]
},
"HttpRequestExpect": {
"description": "Validation checks for an [HttpRequest].",
"type": "object",
"properties": {
"body_includes": {
"description": "Text that must be present in the response body.",
"type": [
"string",
"null"
]
},
"body_regex": {
"description": "Regular expression that must match against the response body.",
"type": [
"string",
"null"
]
},
"status_codes": {
"description": "Expected HTTP status codes.",
"type": [
"array",
"null"
],
"items": {
"type": "integer",
"format": "uint16",
"maximum": 65535,
"minimum": 0
}
}
}
},
"InstabootSnapshotModeV1": {
"description": "How will an instance be bootstrapped?",
"oneOf": [
{
"description": "Start the instance without any snapshot triggers. Once the requests are done,\nuse wasmer_wasix::WasiProcess::snapshot_and_stop to capture a snapshot\nand shut the instance down.",
"type": "string",
"const": "bootstrap"
},
{
"description": "Explicitly enable the given snapshot triggers before starting the instance.\nThe instance's process will have its stop_running_after_checkpoint flag set,\nso the first snapshot will cause the instance to shut down.",
"type": "object",
"properties": {
"triggers": {
"type": "array",
"items": {
"$ref": "#/$defs/SnapshotTrigger"
}
}
},
"additionalProperties": false,
"required": [
"triggers"
]
}
]
},
"Job": {
"description": "Job configuration.",
"type": "object",
"properties": {
"action": {
"$ref": "#/$defs/JobAction"
},
"jitter_percent_max": {
"description": "Maximum percent of "jitter" to introduce between invocations.\n\nValue range: 0-100\n\nJitter is used to spread out jobs over time.\nThe calculation works by multiplying the time between invocations\nby a random amount, and taking the percentage of that random amount.\n\nSee also [Self::jitter_percent_min] to set a minimum jitter.",
"type": [
"integer",
"null"
],
"format": "uint8",
"maximum": 255,
"minimum": 0
},
"jitter_percent_min": {
"description": "Minimum "jitter" to introduce between invocations.\n\nValue range: 0-100\n\nJitter is used to spread out jobs over time.\nThe calculation works by multiplying the time between invocations\nby a random amount, and taking the percentage of that random amount.\n\nIf not specified while jitter_percent_max is, it will default to 10%.\n\nSee also [Self::jitter_percent_max] to set a maximum jitter.",
"type": [
"integer",
"null"
],
"format": "uint8",
"maximum": 255,
"minimum": 0
},
"max_schedule_drift": {
"description": "Don't start job if past the due time by this amount,\ninstead opting to wait for the next instance of it\nto be triggered.",
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"retries": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0
},
"timeout": {
"anyOf": [
{
"$ref": "#/$defs/PrettyDuration"
},
{
"type": "null"
}
]
},
"trigger": {
"$ref": "#/$defs/JobTrigger"
}
},
"additionalProperties": true,
"required": [
"name",
"trigger",
"action"
]
},
"JobAction": {
"type": "object",
"oneOf": [
{
"type": "object",
"properties": {
"fetch": {
"$ref": "#/$defs/HttpRequest"
}
},
"required": [
"fetch"
]
},
{
"type": "object",
"properties": {
"execute": {
"$ref": "#/$defs/ExecutableJob"
}
},
"required": [
"execute"
]
}
]
},
"JobTrigger": {
"type": "string"
},
"Locality": {
"type": "object",
"properties": {
"regions": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"regions"
]
},
"PackageSource": {
"type": "string"
},
"PasswordV1": {
"oneOf": [
{
"description": "Plain text password.",
"type": "object",
"properties": {
"password": {
"type": "string"
},
"type": {
"type": "string",
"const": "plain"
}
},
"required": [
"type",
"password"
]
},
{
"description": "Bcrypt password hash.",
"type": "object",
"properties": {
"hash": {
"type": "string"
},
"type": {
"type": "string",
"const": "bcrypt"
}
},
"required": [
"type",
"hash"
]
}
]
},
"PrettyDuration": {
"type": "string"
},
"Redirect": {
"description": "App redirect configuration.",
"type": "object",
"properties": {
"force_https": {
"description": "Force https by redirecting http requests to https automatically.",
"type": [
"boolean",
"null"
]
}
}
},
"SnapshotTrigger": {
"type": "string"
},
"SshUserV1": {
"type": "object",
"properties": {
"authorized_keys": {
"description": "SSH public keys for this user.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
},
"passwords": {
"description": "Passwords for this user.",
"type": [
"array",
"null"
],
"items": {
"$ref": "#/$defs/PasswordV1"
}
},
"username": {
"description": "The username used for SSH login.",
"type": "string"
}
},
"additionalProperties": true,
"required": [
"username"
]
}
}
}


--- METRICS ---