From 67ce98f6cea8a4e0de9d9d5e1d51928e919c6fc3 Mon Sep 17 00:00:00 2001 From: Dan Wilhelm Date: Sat, 12 Jan 2019 21:51:18 -0800 Subject: [PATCH] docs: Add deep dive tutorial of src/utils.rs Issue #346 --- .../template-deep-dive/src-utils-rs.md | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/docs/src/tutorial/template-deep-dive/src-utils-rs.md b/docs/src/tutorial/template-deep-dive/src-utils-rs.md index ea0c3c09b..062dcabfd 100644 --- a/docs/src/tutorial/template-deep-dive/src-utils-rs.md +++ b/docs/src/tutorial/template-deep-dive/src-utils-rs.md @@ -1,3 +1,66 @@ # src/utils.rs -🚧 COMING SOON 🚧 +The purpose of `utils.rs` is to define the `utils` module, which contains a single function `set_panic_hook`. This function becomes part of the `utils` module in `lib.rs`, as described in the last section. + +If the `console_error_panic_hook` feature is not enabled, then `set_panic_hook` is defined to be an inlined empty function. So, there is no run-time performance or code-size penalty incurred by its use. + +We will discuss: +1. [Defining `set_panic_hook`](#a1-defining-set_panic_hook) +2. [Why `console_error_panic_hook`?](#a2-why-console_error_panic_hook) + + +--- + +## 1. Defining `set_panic_hook` + +``` +use cfg_if::cfg_if; +``` + +As described in the `src/lib.rs` tutorial, this allows us to write `cfg_if!` instead of `cfg_if::cfg_if!`. + +``` +cfg_if! { + if #[cfg(feature = "console_error_panic_hook")] { + extern crate console_error_panic_hook; + pub use self::console_error_panic_hook::set_once as set_panic_hook; + } else { + #[inline] + pub fn set_panic_hook() {} + } +} +``` + +As described in the `src/lib.rs` tutorial, the macro `cfg_if!` evaluates the `if` statement during compile time. This is possible because it is testing whether `"console_error_panic_hook"` is defined in the `[features]` section of `Cargo.toml` (among other ways), which is available during compile time. + +The entire macro block will either be replaced with the statements in the `if` block or with those in the `else` block. These two cases are now described in turn: + +``` +extern crate console_error_panic_hook; +pub use self::console_error_panic_hook::set_once as set_panic_hook; +``` + +Due to the `use` statement, the function `self::console_error_panic_hook::set_once` can now be accessed more conveniently as `set_panic_hook`. Due to `pub`, this function will be publicly accessible outside of the `utils` module as `utils::set_panic_hook`. + +``` +#[inline] +pub fn set_panic_hook() {} +``` + +An inline function replaces the function call with the contents of the function during compile time. Here, `set_panic_hook` is defined to be an empty inline function. This allows the use of `set_panic_hook` with no run-time or code-size performance penalty if the feature is not enabled. + +## 2. Why `console_error_panic_hook`? + +The crate `console_error_panic_hook` enhances error messages within the web browser. This allows you to easily debug WebAssembly code. + +Let's compare error messages before and after enabling the feature: + +**Before:** `"RuntimeError: Unreachable executed"` + +**After:** `"panicked at 'index out of bounds: the len is 3 but the index is 4', libcore/slice/mod.rs:2046:10"` + +The crate provides a panic hook for WebAssembly that logs panics to the developer console via the JavaScript `console.error` function. + +To use this feature, call `utils::set_panic_hook()` when your code first runs. The function may be called multiple times if needed. + +For more details, see the [`console_error_panic_hook` repository](https://github.com/rustwasm/console_error_panic_hook). \ No newline at end of file