#panics #glue #hook #trace

nightly wasm-glue

使 println! 和 panics 在 WebAssembly 中工作

1 个不稳定版本

使用旧的 Rust 2015

0.1.0 2018 年 3 月 8 日

#688 in WebAssembly


encrusted 中使用

MIT 许可证

9KB
129

wasm-glue

使 println! 和 panics 在 WebAssembly 中工作

WebAssembly 很酷,但是 Rust 的 println! 不会自动工作,当它崩溃时,你会在堆栈跟踪中看到一个无用的 "unreachable" 错误,而不是告诉你实际上发生了什么。

wasm-glue 是连接你的 stdout 和 stderr 的粘合代码。

👉 在线示例


使用方法

最基本的使用方法,在你所做事情的开始附近调用一次 wasm_glue::hook()

extern crate wasm_glue;

#[no_mangle]
pub fn run_webassembly() {
    // hook stdout and stderr up once, before printing anything
    wasm_glue::hook();

    println!("hello console!");
    println!("I'm gunna crash:");

    None::<Option<u32>>.unwrap();
}

协调 JavaScript: 你需要 3 个导入的 JavaScript 函数来实现这一点: printeprinttrace

extern {
    fn print(ptr: *const c_char);  // for stdout
    fn eprint(ptr: *const c_char); // for stderr
    fn trace(ptr: *const c_char);  // specifically for panics
}

这些函数的基本实现可能看起来像这样

// keep a WebAssembly memory reference for `readString`
let memory;

// read a null terminated c string at a wasm memory buffer index
function readString(ptr) {
  const view = new Uint8Array(memory.buffer);

  let end = ptr;
  while (view[end]) ++end;

  const buf = new Uint8Array(view.subarray(ptr, end));
  return (new TextDecoder()).decode(buf);
}

// `wasm_glue::hook()` requires all three
const imports = {
  env: {
    print(ptr) {
      console.log(readString(ptr));
    },

    eprint(ptr) {
      console.warn(readString(ptr));
    },

    trace(ptr) {
      throw new Error(readString(ptr));
    },
  },
};

// ...

WebAssembly.instantiate(buffer, imports).then((result) => {
    const exports = result.instance.exports;

    // update memory reference for readString()
    memory = exports.memory;
    exports.run_webassembly();

    // ...
})

💥 Boom!完全工作的 println! 和有用的 panics。

/example 文件夹中查看完整的示例。

加分项: 解析你的堆栈跟踪。
你可以复制这里的 实现 来解析你的 .stack 错误属性,这将使调试更易于阅读。


发生了什么?

wasm-glue 使用了一些较为神秘的 std 库函数

  • std::io::set_print()
  • std::io::set_panic()
  • std::panic::set_hook()

查看 lib.rs 来了解发生了什么。


选项

wasm_glue::hook() 调用了所有 3 个魔法函数。但你可以选择使用其中的一个。你还可以将 stdout / stderr 设置为无缓冲而不是行缓冲(默认设置)。

::set_stdout()
::set_stdout_unbuffered()
::set_stderr()
::set_stderr_unbuffered()
::set_panic_hook()

或者,你可以直接使用 print! / eprint 的宏

#[macro_use]
extern crate wasm_glue;

许可证

MIT

无运行时依赖