WebAssembly 和 WASI 到底是什么?这篇不讲概念,而是真的把 Rust 编译成 .wasm,检查它的导入导出,从 JS 调用,往它的线性内存里写字节,再让它通过 WASI 打印一行字,最后看宿主不提供能力时会怎样。
w1.wasm 大小 585 字节(包含 3 个函数) 导出: ["memory:memory","add:function","checked_div:function","fib:function"] 导入: [] add(2, 3) = 5 返回类型 number fib(50) = 12586269025n 返回类型 bigint (i64 在 JS 里是 BigInt) add(2147483647, 1) = -2147483648 (i32 回绕:wasm 整数加法不检查溢出) checked_div(1, 0) → RuntimeError: unreachable 陷入 trap 之后实例还能用:add(1, 1) = 2
本机的 brew rustc 没有 wasm32 的预编译标准库,所以用 -Z build-std=core(RUSTC_BOOTSTRAP=1)从源码构建 core,链接器用 Zig 里自带的 wasm-ld(通过 pip 安装的 ziglang 提供,只装在实验用的虚拟环境里)。因此这里是 no_std 的模块,不是带 std 的 wasm32-wasip1 程序。panic 的行为见panic!、unwrap 与 expect。
buf_ptr() = 1048576 (线性内存里的偏移);内存大小 1114112 字节 = 17 页(每页 64 KiB) JS 写入 10 字节后 sum(10) = 1004 JS 里算 = 1004 upper(10) 在 Rust 里就地改写后,JS 读到: HELLO WASM
裸指针的概念见原始指针解引用。
导入: ["wasi_snapshot_preview1.fd_write","wasi_snapshot_preview1.proc_exit"] 导出: ["memory","_start"] hello from Rust compiled to WASI wasi.start 返回(退出码) 0 宿主不提供 WASI 导入时实例化: TypeError: WebAssembly.Instance(): Import #0 "wasi_snapshot_preview1": module is not an object or function (node:64239) ExperimentalWarning: WASI is an experimental feature and might change at any time (Use `node --trace-warnings ...` to show where the warning was created)