JS snippets - The `wasm-bindgen` Guide

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# JS Snippets

Often when developing a crate you want to run on the web you'll want to include some JS code here and there. While `js-sys` and `web-sys` cover many needs they don't cover everything, so `wasm-bindgen` supports the ability to write JS code next to your Rust code and have it included in the final output artifact.

To include a local JS file, you'll use the `#[wasm_bindgen(module)]` macro:

    #![allow(unused)]
    fn main() {
    #[wasm_bindgen(module = "/js/foo.js")]
    extern "C" {
        fn add(a: u32, b: u32) -> u32;
    }
    }

This declaration indicates that all the functions contained in the `extern` block are imported from the file `/js/foo.js`, where the root is relative to the crate root (where `Cargo.toml` is located).

The `/js/foo.js` file will make its way to the final output when `wasm-bindgen` executes, so you can use the `module` annotation in a library without having to worry users of your library!

The JS file itself must be written with ES module syntax:

    export function add(a, b) {
        return a + b;
    }

A full design of this feature can be found in RFC 6 as well if you're interested!

### Using `inline_js`

In addition to `module = "..."` if you're a macro author you also have the ability to use the `inline_js` attribute:

    #![allow(unused)]
    fn main() {
    #[wasm_bindgen(inline_js = "export function add(a, b) { return a + b; }")]
    extern "C" {
        fn add(a: u32, b: u32) -> u32;
    }
    }

Using `inline_js` indicates that the JS module is specified inline in the attribute itself, and no files are loaded from the filesystem. They have the same limitations and caveats as when using `module`, but can sometimes be easier to generate for macros themselves. It's not recommended for hand-written code to make use of `inline_js` but instead to leverage `module` where possible.

### Caveats

While quite useful local JS snippets currently suffer from a few caveats which are important to be aware of. Many of these are temporary though!

- Currently `import` statements are not supported in the JS file. This is a restriction we may lift in the future once we settle on a good way to support this. For now, though, js snippets must be standalone modules and can't import from anything else.

- Only `--target web` and the default bundler output mode are supported. To support `--target nodejs` we'd need to translate ES module syntax to CommonJS (this is planned to be done, just hasn't been done yet). Additionally to support `--target no-modules` we'd have to similarly translate from ES modules to something else.

- Paths in `module = "..."` must currently start with `/`, or be rooted at the crate root. It is intended to eventually support relative paths like `./` and `../`, but it's currently believed that this requires more support in the Rust `proc_macro` crate.

As above, more detail about caveats can be found in RFC 6.