A Taste Of WASM

The Browser as a Virtual Machine

@m4d_z
alwaysdata

Back In History

  • 2001: Prototype, Scriptaculo·us, Mootools
  • 2005: jQuery
  • 2010: SPA / Backbone
  • 2012: Angular
  • 2015: virtual-dom, React, Vue.js
  • 2018: PWA
  • now: How is your RAM today? Good? 🤮

We are developping
(Progressive Web) Apps!

We need:

  • Secured Environment
  • Faster Execution
  • Shared Domains Logics

Webassembly: Origins

An Experiment: ASM.js

  • Low-level Subset of JavaScript
  • Very Optimized
  • Complex to write by-hand

Need to Compile!

Emscripten

  • Toolchain
  • Compile from C/C++
  • Use LLVM

What if we could compile
all our apps’ logics?

WebAssembly is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.

WASM Binary Format

0200 20 00
0202 42 00
0204 51
0205 04 7e
0207 42 01
020A 05
020B 20 00
020D 20 00
0210 42 01
0211 7d
0212 10 00
0214 7e
0217 0b

Is this a… language?

WASM Text Format

get_local 0
i64.const 0
i64.eq
if i64
    i64.const 1
else
    get_local 0
    get_local 0
    i64.const 1
    i64.sub
    call 0
    i64.mul
end

🍀 static types

  • 2 Integers
  • 2 Floats

Problem:
I need more than numbers!

Rust Do it!

WASM Rust Hello World, Web version

pub fn greet(name: &str) {
    alert(&format!("Hello {}!", name));
}

Why Rust?

  • C++, thanks, but I only have one brain
  • No data-race by design
  • Static types
  • Iterators
  • Excellent Memory Management
  • Community 😍
  • Toolchain (Rustup, Cargo, Rustc…)
  • And much more… 👍

Build The Web

WASM Modules

  • Works like a black box
  • Declares Types and Functions
  • Exposes an API

The Security Model

  • Sandboxed Environment per Module
  • Deterministic Execution
  • Control-Flow Integrity
  • Type Signature check for Indirect Calls
  • Memory Safety

Browser-side: Instantiate

let importObject = {
    imports: {
        alert: window.alert
    }
}

WebAssembly
    .instantiateStreaming(fetch('my-module.wasm'), importObject)
    .then(mod => mod.instance.exports.greet('Hello World'))

Remember:
I need more than numbers!

I need Strings
💩 UTF-8

A number could be…
a memory pointer!

Linear Memory

const pointer = 0

const LM = new WebAssembly.Memory({ initial: 1 })
const sharedMem = new Uint8Array(LM.buffer)

const str = "Hello World"

[].forEach.call(
  btoa(str),
  (char, idx) => sharedMem[pointer + idx] = char.charCodeAt(0)
)
// Uint8Array(65536) [ 83, 71, 86, 115, 98, 71, 56, 103, 86, 50, … ]

wasm-pack

📦✨ your favorite rust -> wasm workflow tool!

Easy to use

$ cd my-module
$ wasm-pack build --target web --release

Ready to publish

$ tree
├── bridge.js
├── Cargo.toml
├── pkg
│   ├── my-module_bg.d.ts
│   ├── my-module_bg.wasm
│   ├── my-module.d.ts
│   ├── my-module.js
│   ├── package.json
│   └── snippets
│       └── my-module-91b01578bc1ce6c0
│           └── bridge.js
└── src
    └── lib.rs

wasm-bindgen

Facilitating high-level interactions between wasm modules and JavaScript.

  • High-level library
  • Exposes:
    • Web sys (DOM, window, document, fetch, canvas…)
    • JS sys (passing values, types, boxing…)
    • Promises
  • Generate TypeScript bindings
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn alert(s: &str);
}

#[wasm_bindgen(module = "/bindings.js")]
extern "C" {
    fn updateState(state: &JsValue);
}

pub fn greet(name: &str) {
    alert(&format!("Hello {}!", name));

    let state = State { name }
    updateState(JsValue::from_serde(&state).unwrap());
}

Embind

Embind is used to bind C++ functions and classes to JavaScript, so that the compiled code can be used in a natural way by JavaScript.

Rule Them All

WebAssembly isn’t only for the Web

WASM outside of the browser

  • fast low-level modules for interpretors
  • native sandbox for all languages
  • write once, run everywhere

Running on the Server: The System Interface

  • System Calls Abstraction
  • Runtime emulating JS glue code / browser
  • Security

Portability

  • One compile target
  • Easy to distribute
  • Modular set of Standard Interfaces

Security

  • Sandboxed: code can’t access the OS
  • Deterministic access
  • Modules isolation

Glue them: WASM Standard Interfaces

  • Build native modules easily
  • Sandbox native code
  • Share codebase

Passing values from WASM to JS
is easy but tedious

Passing values from WASM
to anything else
is way more complex

  • Offers Intermediate Representation
  • Each language implement Interface Types
  • WASM engine uses IR for data exchange
$ wasmer run cowsay.wasm Hello World!
 ________________
< Hello World! >
 ----------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
               ||----w |
                ||     ||

The Future of FaaS

$ curl --location --request POST 'https://[::]/api/executables' \
--header 'Content-Type: application/octet-stream' \
--header 'SSVM_Description: say hello' \
--data-binary 'pkg/hello_lib_bg.wasm'
$ curl --location --request POST 'https://[::]/api/run/123/say' \
--header 'Content-Type: text/plain' \
--data-raw 'World'

Hello World!

Production Ready

Production-Proof

Coming from JS? Try AssemblyScript.

AssemblyScript compiles a strict variant of TypeScript to WebAssembly using Binaryen.

export function fib(n: i32): i32 {
  var a = 0, b = 1
  if (n > 0) {
    while (--n) {
      let t = a + b
      a = b
      b = t
    }
    return b
  }
  return a
}

Coming from OS language?
Check LLVM support.

  • C / C++
  • Rust
  • C#
  • GO + TinyGO + syscall/js
  • Java

Comming Soon

  • Multi-threading
  • JS Modules exchange/Garbage Collector
  • Portability/Runtime/IoT

Open Standard
→ Build The Ecosystem

Know The Web!

  • HTML/DOM → Interfaces
  • CSS → Layouts/Style
  • JS → UI Thread
  • WASM → Background Processes
m4dz's avatar
m4dz

Paranoïd Web Dino · Tech Evangelist

alwaysdata logo
https://www.alwaysdata.com

Questions?

Illustrations

m4dz, CC BY-SA 4.0

Interleaf images

Courtesy of Unsplash and Pexels contributors

Icons

  • Layout icons are from Entypo+
  • Content icons are from FontAwesome

Fonts

  • Cover Title: Sinzano
  • Titles: Argentoratum
  • Body: Mohave
  • Code: Fira Code

Tools

Powered by Reveal.js

Source code available at
https://git.madslab.net/talks