This commit is contained in:
JMARyA 2024-03-27 11:51:40 +01:00
parent 26d0ad54f6
commit a497c60af9
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263

View file

@ -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 <you@example.com>"]
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
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<title>hello-wasm example</title>
</head>
<body>
<script type="module">
import init, { greet } from "./pkg/hello_wasm.js";
init().then(() => {
greet("WebAssembly");
});
</script>
</body>
</html>
```
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.