diff --git a/technology/dev/WebAssembly.md b/technology/dev/WebAssembly.md new file mode 100644 index 0000000..b9a8192 --- /dev/null +++ b/technology/dev/WebAssembly.md @@ -0,0 +1,178 @@ +--- +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.