将类型传达给wasm-bindgen

在将Rust / JS类型相互转换时谈论的最后一个方面是如何实际传达这些信息. 该#[wasm_bindgen]宏正在运行Rust代码的语法 (未解析) 结构,然后负责生成信息wasm-bindgenCLI工具稍后会读取.

为实现这一目标,采取了一种略微不同寻常的方法. 有关Rust代码结构的静态信息通过JSON (当前) 序列化到wasm可执行文件的自定义部分. 其他信息,例如类型实际上是什么,遗憾的是直到后来在编译器中才知道由于关联类型投影和typedef之类的事情. 事实证明,我们想要传达"丰富"类型FnMut(String, Foo, &JsValue)到了wasm-bindgenCLI,处理这一切非常棘手!

要解决这个问题了#[wasm_bindgen]宏生成可执行功能其中"描述了进口或出口的类型签名". 这些可执行函数是什么的WasmDescribe特质是关于:


# #![allow(unused_variables)]
#fn main() {
pub trait WasmDescribe {
    fn describe();
}
#}

虽然看似简单,但这个特性实际上非常重要. 当你写,这样的导出:


# #![allow(unused_variables)]
#fn main() {
#[wasm_bindgen]
fn greet(a: &str) {
    // ...
}
#}

除了我们上面谈到的垫片,JS生成宏生成类似的东西:

#[no_mangle]
pub extern fn __wbindgen_describe_greet() {
    <Fn(&str)>::describe();
}

或者换句话说,它会生成调用describe功能. 这样做了__wbindgen_describe_greetshim是导入/导出的类型布局的编程描述. 然后执行这些操作wasm-bindgen跑!这些执行依赖于调用的导入__wbindgen_describe通过一个u32到主机,当多次调用时给出一个Vec<u32>有效. 这个Vec<u32>然后可以被重新分解成一个enum Descriptor它完全描述了一种类型.

总而言之,这有点迂回,但根本不会对生成的代码或运行时产生任何影响. 所有这些描述符函数都从发出的wasm文件中删除.