Synchronous Instantiation - The wasm-bindgen Guide (original) (raw)
- Introduction
- 1. Examples
- 1.1. Hello, World!
- 1.2. Using console.log
- 1.3. Small Wasm files
- 1.4. Without a Bundler
- 1.5. Synchronous Instantiation
- 1.6. Importing functions from JS
- 1.7. Working with char
- 1.8. js-sys: WebAssembly in WebAssembly
- 1.9. web-sys: DOM hello world
- 1.10. web-sys: Closures
- 1.11. web-sys: performance.now
- 1.12. web-sys: using fetch
- 1.13. web-sys: Weather report
- 1.14. web-sys: canvas hello world
- 1.15. web-sys: canvas Julia set
- 1.16. web-sys: WebAudio
- 1.17. web-sys: WebGL
- 1.18. web-sys: WebSockets
- 1.19. web-sys: WebRTC DataChannel
- 1.20. web-sys: requestAnimationFrame
- 1.21. web-sys: A Simple Paint Program
- 1.22. web-sys: Wasm in Web Worker
- 1.23. Parallel Raytracing
- 1.24. Wasm Audio Worklet
- 1.25. web-sys: A TODO MVC App
- 2. Reference
- 2.1. Deployment
- 2.2. JS snippets
- 2.3. Static JS Objects
- 2.4. Passing Rust Closures to JS
- 2.5. Receiving JS Closures in Rust
- 2.6. Promises and Futures
- 2.7. Iterating over JS Values
- 2.8. Arbitrary Data with Serde
- 2.9. Accessing Properties of Untyped JS Values
- 2.10. Working with Duck-Typed Interfaces
- 2.11. Command Line Interface
- 2.12. Optimizing for Size
- 2.13. Supported Rust Targets
- 2.14. Supported Browsers
- 2.15. Support for Weak References
- 2.16. Support for Reference Types
- 2.17. Supported Types
- 2.18. #[wasm_bindgen] Attributes
- 2.18.1. On JavaScript Imports
- 2.18.1.1. catch
- 2.18.1.2. constructor
- 2.18.1.3. extends
- 2.18.1.4. getter and setter
- 2.18.1.5. final
- 2.18.1.6. indexing_getter, indexing_setter, and indexing_deleter
- 2.18.1.7. js_class = "Blah"
- 2.18.1.8. js_name
- 2.18.1.9. js_namespace
- 2.18.1.10. method
- 2.18.1.11. module = "blah"
- 2.18.1.12. raw_module = "blah"
- 2.18.1.13. no_deref
- 2.18.1.14. static_method_of = Blah
- 2.18.1.15. structural
- 2.18.1.16. typescript_type
- 2.18.1.17. variadic
- 2.18.1.18. vendor_prefix
- 2.18.1.1. catch
- 2.18.2. On Rust Exports
- 2.18.2.1. constructor
- 2.18.2.2. js_name = Blah
- 2.18.2.3. js_class = Blah
- 2.18.2.4. readonly
- 2.18.2.5. skip
- 2.18.2.6. skip_jsdoc
- 2.18.2.7. start
- 2.18.2.8. main
- 2.18.2.9. typescript_custom_section
- 2.18.2.10. getter and setter
- 2.18.2.11. inspectable
- 2.18.2.12. skip_typescript
- 2.18.2.13. getter_with_clone
- 2.18.2.14. unchecked_return_type and unchecked_param_type
- 2.18.2.15. return_description and param_description
- 2.18.2.1. constructor
- 3. web-sys
- 4. Testing with wasm-bindgen-test
- 5. Contributing to wasm-bindgen
- 5.2. Internal Design
- 5.3. js-sys
- 5.4. web-sys
- 5.5. Publishing
- 5.6. Team
This documentation isno longer maintained at this domain, and is now maintained at wasm-bindgen.github.io instead.
The `wasm-bindgen` Guide
This example shows how to synchronously initialize a WebAssembly module as opposed to asynchronously. In most cases, the default way of asynchronously initializing a module will suffice. However, there might be use cases where you'd like to lazy load a module on demand and synchronously compile and instantiate it. Note that this only works off the main thread and since compilation and instantiation of large modules can be expensive you should only use this method if it's absolutely required in your use case. Otherwise you should use the default method.
For this deployment strategy bundlers like Webpack are not required. For more information on deployment see the dedicated documentation.
First let's take a look at our tiny lib:
# #![allow(unused_variables)]
#fn main() {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(value: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
log(&format!("Hello, {}!", name));
}
#}Next, let's have a look at the index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
/**
* First off we spawn a Web Worker. That's where our lib will be used. Note that
* we set the `type` to `module` to enable support for ES modules.
*/
const worker = new Worker("/worker.js", { type: "module" });
/**
* Here we listen for messages from the worker.
*/
worker.onmessage = ({ data }) => {
const { type } = data;
switch (type) {
case "FETCH_WASM": {
/**
* The worker wants to fetch the bytes for the module and for that we can use the `fetch` API.
* Then we convert the response into an `ArrayBuffer` and transfer the bytes back to the worker.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
* @see https://developer.mozilla.org/en-US/docs/Glossary/Transferable_objects
*/
fetch("/pkg/synchronous_instantiation_bg.wasm")
.then((response) => response.arrayBuffer())
.then((bytes) => {
worker.postMessage(bytes, [bytes]);
});
break;
}
default: {
break;
}
}
};
</script>
</body>
</html>
Otherwise the rest of the magic happens in worker.js:
import * as wasm from "./pkg/synchronous_instantiation.js";
self.onmessage = ({ data: bytes }) => {
/**
* When we receive the bytes as an `ArrayBuffer` we can use that to
* synchronously initialize the module as opposed to asynchronously
* via the default export. The synchronous method internally uses
* `new WebAssembly.Module()` and `new WebAssembly.Instance()`.
*/
wasm.initSync({ module: bytes });
/**
* Once initialized we can call our exported `greet()` functions.
*/
wasm.greet("Dominic");
};
/**
* Once the Web Worker was spawned we ask the main thread to fetch the bytes
* for the WebAssembly module. Once fetched it will send the bytes back via
* a `postMessage` (see above).
*/
self.postMessage({ type: "FETCH_WASM" });
And that's it! Be sure to read up on the deployment options to see what it means to deploy without a bundler.