如何使用 wasm-bindgen 调用作为模块的 JavaScript 函数?

Ech*_*lan 6 rust webassembly wasm-bindgen

我正在尝试使用 Rust 中的 Web3 JavaScript 库,但我陷入了困境。该库的标准用法始于:

// In Node.js use: const Web3 = require('web3');

let web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");
Run Code Online (Sandbox Code Playgroud)

您应该导入的模块是一个构造函数,它还有一些其他属性。我的 Rust 代码应该绑定这个 API,如下所示:

#[wasm_bindgen(module = "web3")]
extern "C" {
    type Web3;

    #[wasm_bindgen(constructor)]
    fn new(_: &Provider) -> Web3;

    type Provider;

    static givenProvider: Provider;
}
Run Code Online (Sandbox Code Playgroud)

最终输出import { Web3, givenProvider } from 'web3';并尝试运行new Web3(...)失败。它应该执行诸如import * as Web3 from 'web3';运行new Web3(...)和引用之类的操作Web3.givenProvider

我怎样才能让 wasm-bindgen 输出这样的代码?

Ech*_*lan 4

编辑:原来的答案是错误的。你可以使用 导入类似定义的东西wasm-bindgen,它们合法的 ES6。或者至少 ES6 模块中提供了相同的概念。他们称之为默认导出/导入。这有点尴尬,但是导入它们的方法是使用js_name = "default". 就像这样:

#[wasm_bindgen(module = "web3")]
extern "C" {
    #[wasm_bindgen(js_name = "default")]
    type Web3;

    #[wasm_bindgen(constructor, js_class = "default")]
    fn new(_: &Provider) -> Web3;

    #[wasm_bindgen(static_method_of = Web3, getter, js_class = "default")]
    fn givenProvider() -> Provider;

    type Provider;
}
Run Code Online (Sandbox Code Playgroud)

您需要js_class方法上的参数,它不记得Web3s js_nameis default


旧的错误答案

你无法wasm-bindgen生成这样的代码的原因是它不是合法的 ES6。ECMAScript 模块对所有内容都使用命名导出。Web3 实际上是一个 CommonJS 模块,并且它们确实支持单个匿名导出。

它几乎可以工作的原因是因为我使用的是 webpack,而 webpack 允许您使用 ES6 语法导入 CommonJS 模块,即使语义略有不同。

解决方案是制作一个小垫片,从 ES6 模块导出 CommonJS 模块:

export let Web3 = require('web3');
Run Code Online (Sandbox Code Playgroud)

然后这个绑定将起作用:

#[wasm_bindgen(module = "/src/web3-wrapper.js")]
extern "C" {
    type Web3;

    #[wasm_bindgen(constructor)]
    fn new(_: &Provider) -> Web3;

    #[wasm_bindgen(static_method_of = Web3, getter)]
    fn givenProvider() -> Provider;

    type Provider;
}
Run Code Online (Sandbox Code Playgroud)