--- obj: concept mime: application/wasm extension: wasm website: https://webassembly.org rev: 2024-03-26 --- # WebAssembly WebAssembly, often abbreviated as Wasm, is an open standard and binary instruction format designed for a stack-based virtual machine. It aims to execute code efficiently across various platforms, including web browsers. WebAssembly is a portable binary instruction format that serves as a compilation target for high-level programming languages like C, C++, and [Rust](programming/languages/Rust.md). It enables these languages to be executed in web browsers at near-native speeds, bridging the performance gap between web applications and native applications. ## Features of WebAssembly ### 1. **Efficiency** - WebAssembly binaries are designed to be compact and fast to load, enabling efficient transmission over the network. - It leverages Just-In-Time (JIT) compilation techniques for optimal runtime performance. ### 2. **Safety** - WebAssembly runs in a sandboxed environment within the browser, providing a high level of security. - It uses a memory-safe, sandboxed execution model to prevent malicious code from compromising the host environment. ### 3. **Compatibility** - WebAssembly is designed to be platform-independent, allowing code to run consistently across different architectures and operating systems. - It integrates seamlessly with existing web technologies like JavaScript, enabling interoperability with web applications. ### 4. **Versatility** - WebAssembly can be used for a variety of use cases beyond web development, including server-side applications, game engines, and multimedia processing. ## How WebAssembly Works WebAssembly code is typically generated by compiling source code written in languages like C, C++, or [Rust](programming/languages/Rust.md) using specific compilers such as Emscripten or the [Rust](programming/languages/Rust.md) compiler with the `wasm32-unknown-unknown` target. Once compiled, the WebAssembly code can be executed within a web browser using the JavaScript-based WebAssembly runtime. Alternatively, it can be run outside the browser using standalone WebAssembly runtimes or integrated into existing software systems. ## Use Cases of WebAssembly WebAssembly has various applications across different domains: - **Web Development**: Enhancing web applications with high-performance computations, multimedia processing, and gaming. - **Server-Side Applications**: Running compute-intensive tasks efficiently on the server. - **Game Development**: Building cross-platform games with near-native performance. - **Multimedia Processing**: Processing and manipulating multimedia content such as images, audio, and video in the browser. - **Blockchain**: Executing smart contracts and decentralized applications (DApps) on blockchain platforms. ## Usage with [Rust](programming/languages/Rust.md) ### Requirements You need [Rust](programming/languages/Rust.md) installed and the following for creating the WebAssembly: ```sh cargo install wasm-pack ``` ### Creating the project Create a new library: ```sh cargo new --lib hello-wasm ``` Sample `src/lib.rs`: ```rust use wasm_bindgen::prelude::*; #[wasm_bindgen] extern { pub fn alert(s: &str); } #[wasm_bindgen] pub fn greet(name: &str) { alert(&format!("Hello, {}!", name)); } ``` wasm-pack uses wasm-bindgen, another tool, to provide a bridge between the types of JavaScript and [Rust](programming/languages/Rust.md). It allows JavaScript to call a [Rust](programming/languages/Rust.md) API with a string, or a [Rust](programming/languages/Rust.md) function to catch a JavaScript exception. ### Calling external functions in JavaScript from [Rust](programming/languages/Rust.md) ```rust #[wasm_bindgen] extern { pub fn alert(s: &str); } ``` As you might suspect, this is the alert function provided by JavaScript. Whenever you want to call JavaScript functions, you can add them to this file, and wasm-bindgen takes care of setting everything up for you. Not everything is supported yet, but we're working on it. ### Producing [Rust](programming/languages/Rust.md) functions that JavaScript can call ```rust #[wasm_bindgen] pub fn greet(name: &str) { alert(&format!("Hello, {}!", name)); } ``` Once again, we see the `#[wasm_bindgen]` attribute. In this case, it's not modifying an `extern` block, but a `fn`; this means that we want this [Rust](programming/languages/Rust.md) function to be able to be called by JavaScript. It's the opposite of `extern`: these aren't the functions we need, but rather the functions we're giving out to the world. This function is named `greet`, and takes one argument, a string (written `&str`), `name`. It then calls the `alert` function we asked for in the `extern` block above. ### Compiling our code to WebAssembly To compile our code correctly, we first need to configure it with `Cargo.toml`. Open this file, and change its contents to look like this: ```toml [package] name = "hello-wasm" version = "0.1.0" authors = ["Your Name "] description = "A sample project with wasm-pack" license = "MIT/Apache-2.0" repository = "https://github.com/yourgithubusername/hello-wasm" edition = "2018" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2" ``` The big part to add is the `[package]`. The `[lib]` part tells [Rust](programming/languages/Rust.md) to build a `cdylib` version of our package. The last section is the `[dependencies]` section. Here's where we tell [Cargo](../applications/development/cargo.md) what version of `wasm-bindgen` we want to depend on. ### Building the package Now that we've got everything set up, let's build the package. We'll be using the generated code in a native ES module and in Node.js. For this purpose, we'll use the `--target` argument in `wasm-pack build` to specify what kind of WebAssembly and JavaScript is generated. ```sh wasm-pack build --target web ``` This does a number of things (and they take a lot of time, especially the first time you run `wasm-pack`). In short, `wasm-pack build`: - Compiles your [Rust](programming/languages/Rust.md) code to WebAssembly. - Runs `wasm-bindgen` on that WebAssembly, generating a JavaScript file that wraps up that WebAssembly file into a module the browser can understand. - Creates a `pkg` directory and moves that JavaScript file and your WebAssembly code into it. - Reads your `Cargo.toml` and produces an equivalent `package.json`. - Copies your `README.md` (if you have one) into the package. ### Using the package on the web Now that we've got a compiled Wasm module, let's run it in the browser. Let's start by creating a file named `index.html` in the root of the project, so we end up with the following project structure: ``` ├── Cargo.lock ├── Cargo.toml ├── index.html <-- new index.html file ├── pkg │ ├── hello_wasm.d.ts │ ├── hello_wasm.js │ ├── hello_wasm_bg.wasm │ ├── hello_wasm_bg.wasm.d.ts │ └── package.json ├── src │ └── lib.rs └── target ├── CACHEDIR.TAG ├── release └── wasm32-unknown-unknown ``` Put the following content in the `index.html` file: ```html hello-wasm example ``` The script in this file will import the JavaScript glue code, initialize the Wasm module, and call the `greet` function we wrote in [Rust](programming/languages/Rust.md). Serve the root directory of the project with a local web server, (e.g. `python3 -m http.server`). > Note: Make sure to use an up-to-date web server that supports the `application/wasm` [MIME](../files/MIME.md) type. Older web servers might not support it yet. Load `index.html` from the web server. An alert box appears on the screen, with `Hello, WebAssembly!` in it. We've successfully called from JavaScript into [Rust](programming/languages/Rust.md), and from [Rust](programming/languages/Rust.md) into JavaScript.