Skip to content

medz/wasd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

208 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

WASD

pub package Dart SDK License GitHub Stars

A pure Dart WebAssembly runtime for Dart and Flutter ecosystems.

WASD provides Dart-native WebAssembly execution with a pure Dart core runtime layer, so you can embed and run Wasm modules directly from Dart code without relying on a native runtime dependency in the core library.

Overview

WASD is a Dart package for:

  • Decoding and validating WebAssembly binaries
  • Compiling and instantiating modules from bytes or streams
  • Instantiating modules with host imports
  • Executing exported functions from Dart
  • Running WASI Preview1 workloads
  • Inspecting module imports/exports/custom sections

Why WASD

  • Pure Dart core runtime, aligned with Dart/Flutter embedding workflows
  • Public API that mirrors WebAssembly-style operations (compile, instantiate, validate)
  • Explicit host integration via import maps and typed wrappers
  • Built-in WASI Preview1 host surface through WASI
  • Regression-oriented tests and conformance tooling in-repo

Installation

dart pub add wasd

Or add manually in pubspec.yaml:

dependencies:
  wasd: ^0.2.0

Quick Start

Run included examples:

dart run example/wasm_cli.dart
dart run example/wasm_cli.dart 3 9

The Flutter DOOM example has its own guide in example/doom/README.md.

Minimal module invocation:

import 'dart:typed_data';
import 'package:wasd/wasd.dart';

Future<void> main() async {
  final Uint8List wasmBytes = loadYourModuleBytes();
  final runtime = await WebAssembly.instantiate(wasmBytes.buffer);
  final addExport = runtime.instance.exports['add'];
  if (addExport is! FunctionImportExportValue) {
    throw StateError('Expected `add` export to be a function.');
  }

  final result = (addExport.ref([20, 22]) as num).toInt();
  print(result); // 42
}

Uint8List loadYourModuleBytes() => throw UnimplementedError();

Host Function Imports

Provide host callbacks with Imports and ImportExportKind.function:

import 'dart:typed_data';
import 'package:wasd/wasd.dart';

Future<void> main() async {
  final wasmBytes = loadYourModuleBytes();
  final imports = <String, ModuleImports>{
    'env': {
      'plus': ImportExportKind.function((args) {
        final a = args[0] as int;
        final b = args[1] as int;
        return a + b;
      }),
    },
  };

  final runtime = await WebAssembly.instantiate(wasmBytes.buffer, imports);
  final usePlus = runtime.instance.exports['use_plus'];
  if (usePlus is! FunctionImportExportValue) {
    throw StateError('Expected `use_plus` export to be a function.');
  }

  print(usePlus.ref([4, 5])); // 9
}

Uint8List loadYourModuleBytes() => throw UnimplementedError();

WASI Preview1

Use WASI and call _start through wasi.start(instance).

import 'package:wasd/wasd.dart';

Future<void> main() async {
  final wasmBytes = loadWasiModuleBytes();
  final wasi = WASI(
    args: const ['demo'],
    env: const {'FOO': 'bar'},
  );

  final runtime = await WebAssembly.instantiate(wasmBytes.buffer, wasi.imports);
  final exitCode = wasi.start(runtime.instance);

  print('exitCode=$exitCode');
}

Uint8List loadWasiModuleBytes() => throw UnimplementedError();

Module Metadata

import 'dart:typed_data';
import 'package:wasd/wasd.dart';

Future<void> main() async {
  final wasmBytes = loadYourModuleBytes();
  final module = await WebAssembly.compile(wasmBytes.buffer);
  final imports = Module.imports(module);
  final exports = Module.exports(module);

  print('imports=${imports.length} exports=${exports.length}');
}

Uint8List loadYourModuleBytes() => throw UnimplementedError();

Verification

dart analyze
dart test test/wasi_test.dart test/wasm_test.dart

Compatibility Snapshot

WebAssembly Implementation Version

Item Version Status
Core Wasm module binary 0x01 0x00 0x00 0x00 Supported

WASI Version

WASI Version Status
Preview 1 Supported
Preview 2 Not implemented
Preview 3 Not implemented

Limitations

  • Some proposal/component forms are intentionally guarded and may return UnsupportedError until implemented.
  • JS runtime behavior is environment-dependent: Node.js uses node:wasi; browsers provide a minimal wasi_snapshot_preview1 shim for command-style flows (proc_exit, args_*, environ_*, random_get, fd_read, fd_write, fd_fdstat_get, fd_filestat_get, fd_prestat_*, fd_close, clock_time_get) and virtual filesystem basics (fd_seek, path_open, path_filestat_get), with explicit ENOSYS stubs for unsupported calls (for example path_unlink_file, proc_raise, sock_*).
  • Native preview1 host support intentionally tracks the same minimal surface as the browser shim: command-style flows plus virtual filesystem basics (fd_seek, path_open, path_filestat_get), while unsupported preview1 syscalls stay as explicit ENOSYS stubs.

Contributions for missing features and edge-case regressions are welcome.

Contributing

Contributions are welcome through pull requests and issues.

  • Follow existing lint/style rules (dart format ., dart analyze)
  • Add focused regression tests for behavior changes
  • Keep changes scoped and reproducible with command output

License

WASD is licensed under the MIT License. See LICENSE.

About

πŸ’₯ A pure Dart implementation of a WASM runtime.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors