# wasm-glue **Get println! & panics to work in WebAssembly** WebAssembly is cool and all, but Rust `println!`'s don't work out of the box, and when it crashes you're left with that unhelpful "unreachable" error in the stack trace instead of it telling you what actually went wrong. `wasm-glue` is glue code to hook up your stdout and stderr. 👉 [Live Example](https://demille.github.io/wasm-glue/example/)
## Usage Most basic usage, call `wasm_glue::hook()` once, near the start of whatever you are doing: ```rust extern crate wasm_glue; #[no_mangle] pub fn run_webassembly() { // hook stdout and stderr up once, before printing anything wasm_glue::hook(); println!("hello console!"); println!("I'm gunna crash:"); None::>.unwrap(); } ``` **Coordinating JavaScript:** You'll need 3 imported JavaScript functions for this to work: `print`, `eprint`, and `trace`: ```rust extern { fn print(ptr: *const c_char); // for stdout fn eprint(ptr: *const c_char); // for stderr fn trace(ptr: *const c_char); // specifically for panics } ``` A basic implementation of these functions would look like this: ```js // keep a WebAssembly memory reference for `readString` let memory; // read a null terminated c string at a wasm memory buffer index function readString(ptr) { const view = new Uint8Array(memory.buffer); let end = ptr; while (view[end]) ++end; const buf = new Uint8Array(view.subarray(ptr, end)); return (new TextDecoder()).decode(buf); } // `wasm_glue::hook()` requires all three const imports = { env: { print(ptr) { console.log(readString(ptr)); }, eprint(ptr) { console.warn(readString(ptr)); }, trace(ptr) { throw new Error(readString(ptr)); }, }, }; // ... WebAssembly.instantiate(buffer, imports).then((result) => { const exports = result.instance.exports; // update memory reference for readString() memory = exports.memory; exports.run_webassembly(); // ... }) ``` :boom: Boom! Fully working `println!`'s and helpful panics. See a complete example of this in the `/example` folder. _**Extra Credit:**_ demangle your stack traces. You can copy the [implementation here][demangle] to demangle the `.stack` property of the error you generate inside your `trace` function. Helps make debugging a little more readable. [demangle]: https://github.com/DeMille/wasm-ffi/blob/master/src/demangle.js
## What's happening? `wasm-glue` uses somewhat obscure std library functions: - `std::io::set_print()` - `std::io::set_panic()` - `std::panic::set_hook()` Check `lib.rs` to see what's going on.
## Options `wasm_glue::hook()` calls all 3 of those magic functions. But you can pick and choose if you'd rather. You can also set stdout / stderr to unbuffered instead of line buffered (the default). • **::set_stdout()** • **::set_stdout_unbuffered()** • **::set_stderr()** • **::set_stderr_unbuffered()** • **::set_panic_hook()** Alternatively, you can just use the macros for `print!` / `eprint`: ```rust #[macro_use] extern crate wasm_glue; ```
## License MIT