這是使用 Rust 和 WebAssembly 的未公開文件,已公開的文件請參閱 Rust 和 WebAssembly 主要文件網站。此處記載的功能可能不適用於 Rust 和 WebAssembly 工具已發布的版本中。

除錯

在寫出更多程式碼之前,當程式出錯時,我們會需要一些除錯工具放在手邊。請花點時間查看 列出可供除錯 Rust 產生的 WebAssembly 的工具和作法的參考頁面

為 Panic 啟用日誌記錄

若我們的程式發生 Panic,我們希望具資訊性的錯誤訊息出現在開發人員主控台中。

我們的 wasm-pack-template 附帶一個在預設情況下已啟用且相依於 console_error_panic_hook crate 的選用相依項,其設定在 wasm-game-of-life/src/utils.rs 中。我們只需要在初始化函式或常見程式碼路徑中安裝這個 hook 即可。我們可以在 wasm-game-of-life/src/lib.rs 中的 Universe::new 建構函式內呼叫。


# #![allow(unused_variables)]
#fn main() {
pub fn new() -> Universe {
    utils::set_panic_hook();

    // ...
}
#}

為我們的生命遊戲加入日誌記錄

讓我們 使用 web-sys crate 中的 console.log 函式,為 Universe::tick 函式中的每個單元格加入一些日誌記錄

首先,將 web-sys 加為相依項,並在 wasm-game-of-life/Cargo.toml 中啟用其 "console" 功能

[dependencies.web-sys]
version = "0.3"
features = [
  "console",
]

有關程式人體工學,我們將把 console.log 函式包裝到 println! 類型的巨集中


# #![allow(unused_variables)]
#fn main() {
extern crate web_sys;

// A macro to provide `println!(..)`-style syntax for `console.log` logging.
macro_rules! log {
    ( $( $t:tt )* ) => {
        web_sys::console::log_1(&format!( $( $t )* ).into());
    }
}
#}

現在,我們可以透過在 Rust 程式碼中插入對 log 的呼叫來開始記錄訊息到主控台,例如,修改 wasm-game-of-life/src/lib.rs 以下載記錄每個單元的狀態、鄰居存活計數,以及下一個狀態

diff --git a/src/lib.rs b/src/lib.rs
index f757641..a30e107 100755
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -123,6 +122,14 @@ impl Universe {
                 let cell = self.cells[idx];
                 let live_neighbors = self.live_neighbor_count(row, col);

+                log!(
+                    "cell[{}, {}] is initially {:?} and has {} live neighbors",
+                    row,
+                    col,
+                    cell,
+                    live_neighbors
+                );
+
                 let next_cell = match (cell, live_neighbors) {
                     // Rule 1: Any live cell with fewer than two live neighbours
                     // dies, as if caused by underpopulation.
@@ -140,6 +147,8 @@ impl Universe {
                     (otherwise, _) => otherwise,
                 };

+                log!("    it becomes {:?}", next_cell);
+
                 next[idx] = next_cell;
             }
         }

使用偵錯器暫停在每一刻點

瀏覽器的逐步偵錯功能有助於檢查 Rust 產生的 WebAssembly 所互動的 JavaScript

例如,我們可以使用偵錯器在 renderLoop 函式的每個反覆運算上暫停,請將 一個 JavaScript debugger; 陳述式 放在呼叫 universe.tick() 的上方

const renderLoop = () => {
  debugger;
  universe.tick();

  drawGrid();
  drawCells();

  requestAnimationFrame(renderLoop);
};

這為我們提供了一個用來檢查記錄的訊息的檢查點,並將目前呈現的畫面與前一個畫面做比較

Screenshot of debugging the Game of Life

練習

  • 加入記錄到 tick 函式,用來記錄每個單元從存活轉換到死亡或反之的列和欄

  • Universe::new 方法中引入一個 panic!(),在你的網頁瀏覽器的 JavaScript 偵錯器中檢查 panic 的回溯,停用偵錯符號,在沒有選用的相依項目 console_error_panic_hook 下重新建立,然後再次檢查堆疊追蹤,它沒有這麼有用不是嗎?