Static JS Objects - 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
The `wasm-bindgen` Guide
Use of static to Access JS Objects
JavaScript modules will often export arbitrary static objects for use with their provided interfaces. These objects can be accessed from Rust by declaring a named static
in the extern
block with an#[wasm_bindgen(thread_local_v2)]
attribute. wasm-bindgen
will bind aJsThreadLocal
for these objects, which can be cloned into a JsValue
.
These values are cached in a thread-local and are meant to bind static values or objects only. For getters which can change their return value or throw seehow to import getters.
For example, given the following JavaScript:
let COLORS = {
red: 'rgb(255, 0, 0)',
green: 'rgb(0, 255, 0)',
blue: 'rgb(0, 0, 255)',
};
static
can aid in the access of this object from Rust:
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(thread_local_v2)]
static COLORS: JsValue;
}
fn get_colors() -> JsValue {
COLORS.with(JsValue::clone)
}
#}
Since COLORS
is effectively a JavaScript namespace, we can use the same mechanism to refer directly to namespaces exported from JavaScript modules, and even to exported classes:
let namespace = {
// Members of namespace...
};
class SomeType {
// Definition of SomeType...
};
export { SomeType, namespace };
The binding for this module:
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen(module = "/js/some-rollup.js")]
extern "C" {
// Likewise with the namespace--this refers to the object directly.
#[wasm_bindgen(thread_local_v2, js_name = namespace)]
static NAMESPACE: JsValue;
// Refer to SomeType's class
#[wasm_bindgen(thread_local_v2, js_name = SomeType)]
static SOME_TYPE: JsValue;
// Other bindings for SomeType
type SomeType;
#[wasm_bindgen(constructor)]
fn new() -> SomeType;
}
#}
If you expect the JavaScript value you're trying to access to not always be available you can use Option<T>
to handle this:
# #![allow(unused_variables)]
#fn main() {
extern "C" {
type Crypto;
#[wasm_bindgen(thread_local_v2, js_name = crypto)]
static CRYPTO: Option<Crypto>;
}
#}
If crypto
is not declared or nullish (null
or undefined
) in JavaScript, it will simply return None
in Rust. This will also account for namespaces: it will return Some(T)
only if all parts are declared and not nullish.
Strings can be imported to avoid going through TextDecoder/Encoder
when requiring just a JsString
. This can be useful when dealing with environments where TextDecoder/Encoder
is not available, like in audio worklets.
# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(thread_local_v2, static_string)]
static STRING: JsString = "a string literal";
}
#}