/ src / reference / debugging.md
debugging.md
  1  # Debugging Rust-Generated WebAssembly
  2  
  3  This section contains tips for debugging Rust-generated WebAssembly.
  4  
  5  ## Building with Debug Symbols
  6  
  7  > ⚡ When debugging, always make sure you are building with debug symbols!
  8  
  9  If you don't have debug symbols enabled, then the `"name"` custom section won't
 10  be present in the compiled `.wasm` binary, and stack traces will have function
 11  names like `wasm-function[42]` rather than the Rust name of the function, like
 12  `wasm_game_of_life::Universe::live_neighbor_count`.
 13  
 14  When using a "debug" build (aka `wasm-pack build --debug` or `cargo build`)
 15  debug symbols are enabled by default.
 16  
 17  With a "release" build, debug symbols are not enabled by default. To enable
 18  debug symbols, ensure that you `debug = true` in the `[profile.release]` section
 19  of your `Cargo.toml`:
 20  
 21  ```toml
 22  [profile.release]
 23  debug = true
 24  ```
 25  
 26  ## Logging with the `console` APIs
 27  
 28  Logging is one of the most effective tools we have for proving and disproving
 29  hypotheses about why our programs are buggy. On the Web, [the `console.log`
 30  function](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) is the
 31  way to log messages to the browser's developer tools console.
 32  
 33  We can use [the `web-sys` crate][web-sys] to get access to the `console` logging
 34  functions:
 35  
 36  ```rust
 37  extern crate web_sys;
 38  
 39  web_sys::console::log_1(&"Hello, world!".into());
 40  ```
 41  
 42  Alternatively, [the `console.error`
 43  function](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) has
 44  the same signature as `console.log`, but developer tools tend to also capture
 45  and display a stack trace alongside the logged message when `console.error` is
 46  used.
 47  
 48  ### References
 49  
 50  * Using `console.log` with the `web-sys` crate:
 51    * [`web_sys::console::log` takes an array of values to log](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.log.html)
 52    * [`web_sys::console::log_1` logs a single value](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.log_1.html)
 53    * [`web_sys::console::log_2` logs two values](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.log_2.html)
 54    * Etc...
 55  * Using `console.error` with the `web-sys` crate:
 56    * [`web_sys::console::error` takes an array of values to log](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.error.html)
 57    * [`web_sys::console::error_1` logs a single value](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.error_1.html)
 58    * [`web_sys::console::error_2` logs two values](https://rustwasm.github.io/wasm-bindgen/api/web_sys/console/fn.error_2.html)
 59    * Etc...
 60  * [The `console` object on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console)
 61  * [Firefox Developer Tools — Web Console](https://developer.mozilla.org/en-US/docs/Tools/Web_Console)
 62  * [Microsoft Edge Developer Tools — Console](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console)
 63  * [Get Started with the Chrome DevTools Console](https://developers.google.com/web/tools/chrome-devtools/console/get-started)
 64  
 65  ## Logging Panics
 66  
 67  [The `console_error_panic_hook` crate logs unexpected panics to the developer
 68  console via `console.error`.][panic-hook] Rather than getting cryptic,
 69  difficult-to-debug `RuntimeError: unreachable executed` error messages, this
 70  gives you Rust's formatted panic message.
 71  
 72  All you need to do is install the hook by calling
 73  `console_error_panic_hook::set_once()` in an initialization function or common
 74  code path:
 75  
 76  ```rust
 77  #[wasm_bindgen]
 78  pub fn init_panic_hook() {
 79      console_error_panic_hook::set_once();
 80  }
 81  ```
 82  
 83  [panic-hook]: https://github.com/rustwasm/console_error_panic_hook
 84  
 85  ## Using a Debugger
 86  
 87  Unfortunately, the debugging story for WebAssembly is still immature. On most
 88  Unix systems, [DWARF][dwarf] is used to encode the information that a debugger
 89  needs to provide source-level inspection of a running program. There is an
 90  alternative format that encodes similar information on Windows. Currently, there
 91  is no equivalent for WebAssembly. Therefore, debuggers currently provide limited
 92  utility, and we end up stepping through raw WebAssembly instructions emitted by
 93  the compiler, rather than the Rust source text we authored.
 94  
 95  > There is a [sub-charter of the W3C WebAssembly group for
 96  > debugging][debugging-subcharter], so expect this story to improve in the
 97  > future!
 98  
 99  [debugging-subcharter]: https://github.com/WebAssembly/debugging
100  [dwarf]: http://dwarfstd.org/
101  
102  Nonetheless, debuggers are still useful for inspecting the JavaScript that
103  interacts with our WebAssembly, and inspecting raw wasm state.
104  
105  ### References
106  
107  * [Firefox Developer Tools — Debugger](https://developer.mozilla.org/en-US/docs/Tools/Debugger)
108  * [Microsoft Edge Developer Tools — Debugger](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/debugger)
109  * [Get Started with Debugging JavaScript in Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/javascript/)
110  
111  ## Avoid the Need to Debug WebAssembly in the First Place
112  
113  If the bug is specific to interactions with JavaScript or Web APIs, then [write
114  tests with `wasm-bindgen-test`.][wbg-test]
115  
116  If a bug does *not* involve interaction with JavaScript or Web APIs, then try to
117  reproduce it as a normal Rust `#[test]` function, where you can leverage your
118  OS's mature native tooling when debugging. Use testing crates like
119  [`quickcheck`][quickcheck] and its test case shrinkers to mechanically reduce
120  test cases. Ultimately, you will have an easier time finding and fixing bugs if
121  you can isolate them in a smaller test cases that don't require interacting with
122  JavaScript.
123  
124  Note that in order to run native `#[test]`s without compiler and linker errors,
125  you will need to ensure that `"rlib"` is included in the `[lib.crate-type]`
126  array in your `Cargo.toml` file.
127  
128  ```toml
129  [lib]
130  crate-type ["cdylib", "rlib"]
131  ```
132  
133  [quickcheck]: https://crates.io/crates/quickcheck
134  [web-sys]: https://rustwasm.github.io/wasm-bindgen/web-sys/index.html
135  [wbg-test]: https://rustwasm.github.io/wasm-bindgen/wasm-bindgen-test/index.html