调试

在我们编写更多代码之前,我们需要一些在出现问题时使用的调试工具。

为Panic启用日志记录

我们的 wasm-pack-template 附带了 console_error_panic_hook crate 是一个可选的默认开启的依赖项,可以在 wasm-game-of-life/src/utils.rs 中看到已配置了。 我们需要做的就是在初始化函数或常用代码路径中安装 hooks。 我们可以在 wasm-game-of-life/src/lib.rs 中的,Universe::new 构造函数里面调用它:

  1. pub fn new() -> Universe {
  2. utils::set_panic_hook();
  3. // ...
  4. }

加入日志到游戏中

运用 console.log 函数,是由 web-sys 添加一些记录日志,记录 Universe::tick 函数的每个 Cell

首先,在 wasm-game-of-life/Cargo.toml 添加 web-sys 依赖项,并启用它的 “console” 功能:

  1. [dependencies.web-sys]
  2. version = "0.3"
  3. features = [
  4. "console",
  5. ]

为了代码更优雅,我们将把 console.log 函数包装成 println! 形式的宏:

  1. extern crate web_sys;
  2. // 一个 macro(宏) 提供 `println!(..)`-形式 语法,给到 `console.log` 日志功能.
  3. macro_rules! log {
  4. ( $( $t:tt )* ) => {
  5. web_sys::console::log_1(&format!( $( $t )* ).into());
  6. }
  7. }

现在,我们可以在 Rust 代码中,调用 log,开始 console.log 的信息记录。 例如,要记录每个单元(cell)的状态,实时邻居计数,以及下一个状态,我们可以修改 wasm-game-of-life/src/lib.rs 像这样:

  1. diff --git a/src/lib.rs b/src/lib.rs
  2. index f757641..a30e107 100755
  3. --- a/src/lib.rs
  4. +++ b/src/lib.rs
  5. @@ -123,6 +122,14 @@ impl Universe {
  6. let cell = self.cells[idx];
  7. let live_neighbors = self.live_neighbor_count(row, col);
  8. + log!(
  9. + "cell[{}, {}] is initially {:?} and has {} live neighbors",
  10. + row,
  11. + col,
  12. + cell,
  13. + live_neighbors
  14. + );
  15. +
  16. let next_cell = match (cell, live_neighbors) {
  17. // Rule 1: Any live cell with fewer than two live neighbours
  18. // dies, as if caused by underpopulation.
  19. @@ -140,6 +147,8 @@ impl Universe {
  20. (otherwise, _) => otherwise,
  21. };
  22. + log!(" it becomes {:?}", next_cell);
  23. +
  24. next[idx] = next_cell;
  25. }
  26. }

在每个 Tick 之间用调试器暂停

例如,我们可用调试器,在我们的 renderLoop 函数每次迭代时,暂停。 只需要在 universe.tick() 之上放置一个 JavaScript 的 debugger;声明

  1. const renderLoop = () => {
  2. debugger;
  3. universe.tick();
  4. drawGrid();
  5. drawCells();
  6. requestAnimationFrame(renderLoop);
  7. };

这为我们提供了一个方便的检查点,用于检查记录的消息,并将当前呈现的帧与前一帧进行比较。

debugging

练习

  • 将日志记录添加到 tick 函数中,该函数记录每个单元格的行和列,这些单元格将状态从 live 转换为 dead,反之亦然。
  • 声明一个 panic!()Universe::new 方法里面。在 Web 浏览器的 JavaScript 调试器中,检查恐慌的回溯。要做到禁用调试符号,只用不带 console_error_panic_hook 可选依赖项,重新构建就好了,并再次检查堆栈跟踪。可以吗?