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 a JsThreadLocal 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 see how 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)]
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)]
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;
}
}

Optional statics

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)]
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.

Static strings

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)]
fn main() {
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(thread_local_v2, static_string)]
    static STRING: JsString = "a string literal";
}
}