• Stars
    star
    165
  • Rank 228,906 (Top 5 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 3 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A minimalist Rust WebAssembly project template

MiniWASM - A minimalist Rust WebAssembly project template

This is a minimal Rust-powered WebAssembly application template. It was designed to showcase what must be done to get Rust-powered WebAssembly going with only a small amount of code, while still providing useful tools, such as integration with console.log.

How to build?

The easiest way is to install Docker on your system and run the docker-shell.sh script. This script builds a Docker image containing Rust, the wasm32-unknown-unknown target, and a couple of dependencies for optimizing the generated .wasm files.

After building the Docker image the script then launches a container with that image, giving you a shell with a proper build environment. Alternatively you can just install Rust and the wasm32 target on your host machine, and also install binaryen and wabt.

Either way, after opening a shell with a build environment, you can just run the build.sh script. This builds the miniwasm.wasm file and runs it through the optimizer to reduce the file size.

Now that you have the compiled WebAssembly file you can run the serve.sh script. This runs a web server in the current working directory (thanks to Python). You can then go to http://localhost:8000/ to view the application. Open the console to see the log messages that the WebAssembly produces.

Why not wasm-bindgen or wasm-pack?

Wasm-bindgen is awesome, so use it when you can. I myself am working on projects that have more strict performance requirements, and wasm-bindgen's translation layer often gets in the way of performance when I need to pass data back and forth between Rust and JavaScript. Therefore I created MiniWASM as a template to quickly prototype new experiments for my algorithms.

Another reason why you might want to use MiniWASM as a starting point is that you want to build something small and don't want to depend on wasm-pack's NPM packages.

Compatibility

This application template should be compatible with all modern browsers. However, it has only been tested with Chrome 88 and Safari 14. It will probably work fine in Firefox too though.

Technical details

This project consists of two components:

  1. A Rust file serving as the entry point for the WebAssembly application.
  2. An HTML file with embedded JavaScript code to bootstrap the WebAssembly application.

The Rust WebAssembly application

The Rust WebAssembly application is a single-file crate that performs a few functions:

  1. It sets up wee_alloc as the memory allocator.

  2. It has a bridge to send log messages to JavaScript. This is done by importing some proxy functions (one for console.log and one for console.error) and calling them with the address and length of a &str.

    The JavaScript implementation of these functions then looks into the WebAssembly application's WebAssembly.Memory instance and extracts the characters, converting the raw bytes back into a JavaScript-representation before handing them off to the JavaScript console functions.

  3. It defines a struct that holds the application's global state and stores this in a cell in thread local storage.

  4. It defines functions that act as a bridge between the WebAssembly module's external interface and the application struct.

  5. It has a bootstrapping function that sets up a new panic handler so that we can see panics in the JavaScript console.

JavaScript bootstrapping code

Instantiating a WebAssembly module is easy. We just have to fetch the .wasm file and pass its contents into WebAssembly.instantiate.

To get logging to work we need to do a little bit more though. When instantiating the WebAssembly module we provide an import descriptor that exposes console.log and console.error. We can't expose those functions directly though, because WebAssembly's calling convention only allows us to use primitive types as arguments and return values. Therefore we wrap the logging functions with a function that takes the location of a string slice and extracts the bytes from the WebAssembly application's Memory instance. These bytes are converted into a JavaScript string and then handed off to the logging function.

License

Copyright 2021 Emil Loer.

This project is licensed under the MIT license. A copy of the license can be found in the project repository.

More Repositories

1

pygrunn-2012-synth

Example generator based synthesizer, built for my PyGrunn 2012 talk
Python
57
star
2

js303

A fully functional TB-303 clone written in JavaScript using the Web Audio API
JavaScript
50
star
3

gitbot

An IRC bot that listens to GitHub webhooks
Ruby
24
star
4

node-http-digest

HTTP Digest authentication for node.js web servers
JavaScript
16
star
5

jquery-ui-dial

A rotating dial jQuery UI widget.
JavaScript
9
star
6

rustsam

Rust reimplementation of the C64 Software Automatic Mouth speech synthesizer
Rust
7
star
7

nedna

node.js streaming mp3 server
JavaScript
5
star
8

rygments

The fastest Ruby wrapper for the Pygments syntax highlighter.
C
5
star
9

fabutil

Fabric output beautification and deployment power tools
Python
5
star
10

JazzTrainer

Piano chord and scale trainer for jazz musicians
4
star
11

zx0-rs

A ZX0 compressor implementation for Rust
Rust
3
star
12

psg-rs

Fast and precise AY-3-8910 and YM2149 sound chip emulation for Rust
Rust
3
star
13

blueair-py

Unofficial Blueair Python client
Python
3
star
14

turbosass

Sass framework for ninjas
Ruby
3
star
15

pyminify

Script to automate javascript minification using Closure and ScriptDiet
JavaScript
2
star
16

SYOI-stratego

Git demonstratie voor SYOI12
Ruby
2
star
17

pijthon

Pijthon - it's like Python but without the noise
Python
2
star
18

mnml

Minimalistic general purpose markup language
JavaScript
2
star
19

mnml-python

Python Mnml Parser
Python
1
star
20

pygrunn-guis

Example applications from my PyGrunn GUI Toolkits talk
Python
1
star
21

turbogrid

The fastest way to add sortable tables to a Rails 3 app.
Ruby
1
star
22

mnml-spec

The official Mnml specification
1
star
23

pygrunn-tracer

Python Ray Tracer, example for my talk at the PyGrunn Conference of 2013
Python
1
star
24

pygrunn-lisp

Example Lisp interpreter in Python 3
Python
1
star
25

requencer

Ruby audio sequencer/mixer gem
C
1
star
26

slidize

Themeable Kramdown to HTML5 slide generator
JavaScript
1
star
27

pygrunn-2015-rpython-audio

Example code for my PyGrunn 2015 talk about audio rendering using RPython
C++
1
star
28

mnml-pygments-lexer

Pygments Lexer for Mnml
Python
1
star
29

vim-mnml

Vim support for Mnml
Vim Script
1
star