调试 Rust 生成的 WebAssembly
本节包含调试 Rust 生成的 WebAssembly 的技巧。
使用调试符号构建
⚡ 调试时,请确保始终使用调试符号构建!
如果你没有启用调试符号,那么编译后的 .wasm
二进制文件中将不会出现 "name"
自定义部分,并且堆栈跟踪将显示类似 wasm-function[42]
的函数名称,而不是函数的 Rust 名称,例如 wasm_game_of_life::Universe::live_neighbor_count
。
使用“调试”构建(即 wasm-pack build --debug
或 cargo build
)时,默认情况下会启用调试符号。
对于“发布”构建,默认情况下不会启用调试符号。要启用调试符号,请确保在 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]
而不出现编译器和链接器错误,你需要确保 "rlib"
包含在 Cargo.toml
文件的 [lib.crate-type]
数组中。
[lib]
crate-type ["cdylib", "rlib"]