js-sys: WebAssembly in WebAssembly - 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-sys: WebAssembly in WebAssembly

View full source code or view the compiled example online

Using the `js-sys` crate we can get pretty meta and instantiate `WebAssembly` modules from inside `WebAssembly` modules!

## `src/lib.rs`

    #![allow(unused)]
    fn main() {
    use js_sys::{Function, Object, Reflect, WebAssembly};
    use wasm_bindgen::prelude::*;
    use wasm_bindgen_futures::{spawn_local, JsFuture};

    // lifted from the `console_log` example
    #[wasm_bindgen]
    extern "C" {
        #[wasm_bindgen(js_namespace = console)]
        fn log(a: &str);
    }

    macro_rules! console_log {
        ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
    }

    const WASM: &[u8] = include_bytes!("add.wasm");

    async fn run_async() -> Result<(), JsValue> {
        console_log!("instantiating a new Wasm module directly");

        let a = JsFuture::from(WebAssembly::instantiate_buffer(WASM, &Object::new())).await?;
        let b: WebAssembly::Instance = Reflect::get(&a, &"instance".into())?.dyn_into()?;

        let c = b.exports();

        let add = Reflect::get(c.as_ref(), &"add".into())?
            .dyn_into::<Function>()
            .expect("add export wasn't a function");

        let three = add.call2(&JsValue::undefined(), &1.into(), &2.into())?;
        console_log!("1 + 2 = {:?}", three);
        let mem = Reflect::get(c.as_ref(), &"memory".into())?
            .dyn_into::<WebAssembly::Memory>()
            .expect("memory export wasn't a `WebAssembly.Memory`");
        console_log!("created module has {} pages of memory", mem.grow(0));
        console_log!("giving the module 4 more pages of memory");
        mem.grow(4);
        console_log!("now the module has {} pages of memory", mem.grow(0));

        Ok(())
    }

    #[wasm_bindgen(start)]
    fn run() {
        spawn_local(async {
            run_async().await.unwrap_throw();
        });
    }
    }