Rust and the Web Platform

Hugo Zapata

Concepts

WASM (WebAssembly) Low level bytecode format
asm.js low level strict JavaScript subset
emscriptem Compile from C,C++ or any language compatible with LLVM to JavaScript .
C++ => LLVM =>  JavaScript
  var buffer = new ArrayBuffer(32768); // JavaScript
  var HEAPF32 = new Float32Array(buffer);
  function main() {
    var a = 0, b = 0;
    do {
      a = (8 + (b << 2)) | 0;
      HEAPF32[a >> 2] = +HEAPF32[a >> 2] + 1.0;
      b = (b + 1) | 0;
    } while ((b | 0) < 5000);
  }

asm.js is still JavaScript

Still has some performance benefits (depending on the engine):

A JavaScript engine can immediately recognize asm.js code at compile-time and immediately compile it to assembly language, with no need to ever run the code through an interpreter.

http://asmjs.org/faq.html

WebAssembly is not JavaScript

(module
  (func $i (import "imports" "imported_func") (param i32))
  (func (export "exported_func")
    i32.const 42
    call $i
  )
)

Text representation (.wat) of a function that receives a reference to a JavaScript function and calls it with the value 42

https://developer.mozilla.org/en-US/docs/WebAssembly/Text_format_to_wasm#A_first_look_at_the_text_format

( The final format is binary  .wasm )

Using the compiled WebAssembly code from JavaScript

fetch('simple.wasm').then(response =>
  response.arrayBuffer()
).then(bytes =>
  WebAssembly.instantiate(bytes, importObject)
).then(results => {
  results.instance.exports.my_cool_method();
});

Steps:

  1. Fetch the code
  2. Convert to a byte array
  3. Use WebAssembly.instantiate API
  4. Call the public method

Rust properties

Safety and Control

  • Compile time validation of (data) race conditions and other memory problems.
  • By default variables are immutable.
  • Modern syntax
  • standard library
  • Unsafe mode
  • No garbage collection
    • Rust uses 'lifetimes' to keep track of usage scope and object destruction
fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

This code won't compile

error[E0384]: re-assignment of immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("The value of x is: {}", x);
4 |     x = 6;
  |     ^^^^^ re-assignment of immutable variable

Compiling from Rust to WebAssembly

It's easy to compile directly from the rust compile to .wasm ( Since a few weeks ago )

rustup update
rustup target add wasm32-unknown-unknown --toolchain nightly
rustc +nightly --target wasm32-unknown-unknown
     -O --crate-type=cdylib add.rs -o add.big.wasm

Announcement of a new compilation target for WASM: (wasm32-unknown-unknown)

Example

#[no_mangle]
pub fn add_one(x: i32) -> i32 {
    x + 1
}

Rust

(module
  (type (;0;) (func (param i32) (result i32)))
  (type (;1;) (func))
  (func (;0;) (type 0) (param i32) (result i32)
    get_local 0
    i32.const 1
    i32.add)
  (func (;1;) (type 1))
  (table (;0;) 0 anyfunc)
  (memory (;0;) 17)
  (export "memory" (memory 0))
  (export "add_one" (func 0))
  (export "rust_eh_personality" (func 1))
  (data (i32.const 4) "\10\00\10\00"))

Readable WebAssembly

https://www.hellorust.com/demos/add/index.html

deck

By hugo zapata

deck

  • 266