调试 Rust 生成的 WebAssembly
本节包含调试 Rust 生成的 WebAssembly 的技巧。
使用调试符号构建
⚡ 调试时,请务必使用调试符号构建!
如果未启用调试符号,则编译后的 .wasm 二进制文件中将不会存在 "name" 自定义部分,并且堆栈跟踪将显示类似 wasm-function[42] 的函数名称,而不是 Rust 函数的名称,例如 wasm_game_of_life::Universe::live_neighbor_count。
使用 "debug" 构建(即 wasm-pack build --debug 或 cargo build)时,默认情况下会启用调试符号。
使用 "release" 构建时,默认情况下不会启用调试符号。要启用调试符号,请确保在 Cargo.toml 文件的 [profile.release] 部分中将 debug 设置为 true。
[profile.release]
debug = true
使用 console API 进行日志记录
日志记录是我们用来证明和反驳程序出现错误的假设的最有效工具之一。在 Web 上,console.log 函数 是将消息记录到浏览器开发者工具控制台的方法。
我们可以使用 web-sys 箱子 来访问 console 日志记录函数。
# #![allow(unused_variables)] #fn main() { extern crate web_sys; web_sys::console::log_1(&"Hello, world!".into()); #}
或者,console.error 函数 与 console.log 具有相同的签名,但开发者工具往往还会在使用 console.error 时捕获并显示堆栈跟踪以及记录的消息。
参考
- 使用 web-sys 箱子的 console.log
- 使用 web-sys 箱子的 console.error
- MDN 上的 console 对象
- Firefox 开发者工具 - Web 控制台
- Microsoft Edge 开发者工具 - 控制台
- 开始使用 Chrome DevTools 控制台
记录恐慌
console_error_panic_hook 箱子通过 console.error 将意外恐慌记录到开发者控制台。 这可以提供 Rust 的格式化恐慌消息,而不是获得难以理解的 RuntimeError: unreachable executed 错误消息。
您只需在初始化函数或通用代码路径中调用 console_error_panic_hook::set_once() 来安装钩子。
# #![allow(unused_variables)] #fn main() { #[wasm_bindgen] pub fn init_panic_hook() { console_error_panic_hook::set_once(); } #}
使用调试器
不幸的是,WebAssembly 的调试故事仍然不成熟。在大多数 Unix 系统上,DWARF 用于对调试器需要提供运行程序的源代码级检查的信息进行编码。Windows 上存在一种用于对类似信息进行编码的替代格式。目前,WebAssembly 没有等效的格式。因此,调试器目前提供的功能有限,我们最终会逐步执行编译器发出的原始 WebAssembly 指令,而不是我们编写的 Rust 源代码。
W3C WebAssembly 小组有一个用于调试的 子章程,因此预计这种情况在未来会得到改善!
尽管如此,调试器仍然可以用于检查与我们的 WebAssembly 交互的 JavaScript,以及检查原始 wasm 状态。
参考
避免需要调试 WebAssembly
如果错误是特定于与 JavaScript 或 Web API 的交互,那么 使用 wasm-bindgen-test 编写测试。
如果错误不涉及与 JavaScript 或 Web API 的交互,那么尝试将其作为普通的 Rust #[test] 函数重现,这样您就可以在调试时利用操作系统的成熟本机工具。使用 quickcheck 等测试箱及其测试用例缩减器来机械地减少测试用例。最终,如果您能够在不需要与 JavaScript 交互的更小的测试用例中隔离错误,那么您将更容易找到和修复错误。
请注意,为了在没有编译器和链接器错误的情况下运行本机 #[test],您需要确保在 Cargo.toml 文件的 [lib.crate-type] 数组中包含 "rlib"。
[lib]
crate-type ["cdylib", "rlib"]