WASM

Web Assembly

References

Reference documentation:

Tech Foundation

WebAssembly (abbreviated Wasm) 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.

WAPM = Web Assembly Package Manager (like NPM on Node.JS)

Wasmer is an open-source runtime for executing WebAssembly compiled code on the Server.

WASI = Web Assembly System Interface -> This is to run WASM directly on operating system -> this is a growing sector

WASM initially was created to run on browser, on the JVM infra, so no other special VM was needed on Brower. As an analogy, Docker was created to offer Sanbox environment above operating system, enabling to run application in protected environment. If we see the browser as an operating system, WASM is offering Sanboxing solution on it, enabling to run application on isolation mode on browser without any interference.

Foundations:

  • WebAssembly is a compile-targeted language for running bytecode on the web.

  • Relative to Javascript, WebAssembly offers predictable performance. It is not inherently faster than Javascript, but it can be faster than JavaScript in the correct use case. Such as computationally intensive tasks, like nested loops or handling large amounts of data. Therefore, WebAssembly is a compliment to JavaScript, and not a replacement.

  • WebAssembly is extremely portable. WebAssembly runs on: all major web browsers, V8 runtimes like Node.js, and independent Wasm runtimes like Wasmtime, Lucet, and Wasmer.

  • WebAssembly has Linear Memory, in other words, one big expandable array. And in the context of Javascript, synchronously accessible by Javascript and Wasm.

  • WebAssembly can export functions and constants, And in the context of Javascript, synchronously accessible by Javascript and Wasm.

  • WebAssembly, in its current MVP, only handles integers and floats. However, tools and libraries exist to make passing high-level data types convenient.

wasm-pack: This helps compile the code to WebAssembly, as well as produce the right packaging for npm, https://hacks.mozilla.org/2018/04/hello-wasm-pack/

wasm-pack uses wasm-bindgen, another tool, to provide a bridge between the types of JavaScript and Rust. It allows JavaScript to call a Rust API with a string, or a Rust function to catch a JavaScript exception. wasm-bindgen on that WebAssembly, generates a JavaScript file that wraps up that WebAssembly file into a module npm can understand.

WASM Language is described on https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#introduction①. WASM defines an abstract syntax for specifying execution rules. (incuding syntax for encode, decode, validate and execute and instruction set. WebAssembly is a virtual instruction set architecture (virtual ISA). This document is concerned with the core ISA layer of WebAssembly. It defines the instruction set, binary encoding, validation, and execution semantics, as well as a textual representation. It does not, however, define how WebAssembly programs can interact with a specific environment they execute in, nor how they are invoked from such an environment.

WASM abstract syntax result in 2 grammars oriented encoding output

  • Binary Format -> Take the abstract syntax and produce a dense linear encoding (grammar based approach with hex -> the ouput is the encoded format, plus the grammar to decode it)

  • Text Format -> idem, it takes the abstract syntax and render it, using S-expressions encoding to give output

Then the embeder environments (so a Web Browser or a WASI running on a machine) will then use API to interact with the low level Assembly encoded code to execute the function. But when a user, via a JS wrapper function call a WASM function, this is the WASM stack that is used in his sandboxes environemnt that is executed.

As a developer of an app, you code in Rust a logic that you compile with rust wasm-pack module and have a wasm compiled version. Then you import that wasm code in a js that will execute on the browser of a user https://www.w3.org/TR/2019/REC-wasm-js-api-1-20191205/ . This is this JS API layer that will enable a JS to interact with the wasm (stack based low level assembly code) to execute in his sandbox env on the the mem of the browser. This is a tweek that use the browser JS VM environment to execute that JS wrapper WASM code.

WebAssembly semantics are defined in terms of an abstract store, representing the state of the WebAssembly abstract machine. WebAssembly operations take a store and return an updated store. Elements of the WebAssembly store may be identified with JavaScript values.

Install WASM (WASM Runtime)

// Install the Wasmer Standalone runtime
$ sudo curl https://get.wasmer.io -sSfL | sh

// Then close terminal and open a new one and test if
$ wasmer -V
>> wasmer 1.0.1
$ wapm -V
>> wapm-cli 0.5.0

Run WASM Module

// Once the Wasmer CLI is installed, you can run Wasm modules from the command line!

// For the test we will take an existing WASM package
// https://wapm.io/package/quickjs#
$ wapm install quickjs

// Test QJS
$ qjs

Install WASM from RUST env

There are two main use cases for Rust and WebAssembly:

  • Build an entire application — an entire web app based in Rust.

  • Build a part of an application — using Rust in an existing JavaScript frontend.

Procedure on : https://wasmbyexample.dev/examples/hello-world/hello-world.rust.en-us.html

// Have RUST installed (pre-requ)
// Install the crate wasm-pack tks to cargo to have that module available in Rust
$ cargo install wasm-pack

// Create project directory
$ mkdir projectHelloWorld
$ cd projectHelloWorld
// Initialite the Rust project material with Cargo
$ cargo init
//Modify the cargo.toml to implement wasm-pack
// update the rust source to integrate wasm-pack
use wasm_bindgen::prelude::*;
// let's compile our crate using wasm-pack, into a wasm module.
// The wasm-pack tool has support for a lot of different output types, especially for bundlers like Webpack or Rollup. But, since we want an ES6 module in our case, we use the web target below:
// To execute in the project folder
$ wasm-pack build --target web

Procedure 2: For developpping a npm package with a module in WASM inside of it (compile a Rust project to wasm and use it in an existing web app.): https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm

Summary:

  • First develop in Rust a logic

  • Then you create a npm package including js wrapper enabling to include WASM code, thanks to "wasm-pack" tool (a Rust Lib installed with Cargo)

  • Then you create a NPM Web site (using webpack), importing the npm package created here above.

  • You launch locally that web server and your browser connect to it and it will exectue WASM Code encapsulated with a Javascript UI

// Pre-requ: Have installed: Rust, node
// Create a new rust lib project
$ cargo new --lib hello-wasm
// update the code into src/lib.rs, add the following
// Add wasm-bindgen to communicate between rust and javascript
use wasm_bindgen::prelude::*;
// Update the Cargo.toml file (to include dependencies and lib)

// Build the wasm package from the rust project
$ wasm-pack build
//!!! if you have an error saying that "no prebuilt wasm-opt binaries are available for this platform: Unrecognized target!"
// Follow this https://github.com/rustwasm/wasm-pack/issues/965


// Add the following to the Cargo.toml file
[package.metadata.wasm-pack.profile.release]
wasm-opt = false

// Make the npm package using Wasm module available to other javscript packages
$ $ cd pkg
$ sudo npm link

// We now have an npm package, written in Rust, but compiled to WebAssembly. It's ready for use from JavaScript, and doesn't require the user to have Rust installed; the code included was the WebAssembly code, not the Rust source.

// Build the Web Site (npm) that use the npm package (containing WebAssembly), using webpack npm for web side
$ cd ../..
$ mkdir site
$ cd site
$ npm link hello-wasm
// the last command copy the npm package created in the sub directory nodes-modules (of the website here)
//Then create the web site and link in HTML, the JS wrapper of WASM
// Create package.json
// Create the webpack.config.js (so the config file of the Webpack service Web)
// Create index.html
// Create the index.js    

// Then run the node.js build Web Server (on /site)

$ npm install
$ npm run serve

// You can browse on http://localhost:8080

Last updated