WebAssembly中的令牌无效或意外

时间:2018-12-23 02:20:49

标签: webassembly rust-rocket

我试图用Rocket运行WebAssembly程序(用Rust编写,https://rustwasm.github.io/book/game-of-life/hello-world.html中的示例程序)。 WebAssembly是使用wasm-pack和wasm_bindgen编译的。 wasm二进制文件在Rocket中表示为content::JavaScript<Vec<u8>>,似乎这是一个“有效”的解决方案。二进制文件已“正确”获取,但是Chrome会显示Uncaught SyntaxError:无效或意外的令牌。这是由于表示为content::JavaScript<Vec<u8>>导致在获取期间发生错误(尽管发送字节与wasm文件中的字节匹配)还是在其他位置存在错误?

我希望有人能解释我为什么生成的二进制文件中出现SyntaxError。

2 个答案:

答案 0 :(得分:0)

好吧,现在我想我知道出了什么问题: 从wasm-pack生成的js文件尝试将WebAssembly加载为模块。该模块需要具有Javascript哑剧,否则它将失败(这就是为什么我尝试将wasm文件作为content::JavaScript<Vec<u8>>发送),但是显然不支持将wasm作为modul加载(如果我错了,请纠正我),因此当然,它将在二进制文件中找到无效的令牌,因为它尝试将其解释为纯JavaScript。我现在实际使用的是来自Rocket witch的Option<NamedFile>类型的application/wasm哑剧。
我需要稍微更改生成的js文件:WebAssembly用WebAssembly.instatiateStreaming(fetch(...), importObjects)初始化,然后应删除模块导入。 importObjects也有些棘手,因为将strigns传递给WebAssembly有点不方便。对于可以从WebAssembly调用的警报功能,importObjects如下所示:
let importObjects = {'./wasm_test': { __wbg_alert_3d9cbee15c16469e: __wbg_alert_3d9cbee15c16469e }};
名称来自wasm二进制文件:(import "./wasm_test" "__wbg_alert_3d9cbee15c16469e" (func $__wbg_alert_3d9cbee15c16469e (type $t0)))
函数__wbg_alert_3d9cbee15c16469e由wasm-pack生成。最后要更改的是最初通过import语句导入的对象。我现在有一个变量,其内容来自obj.instance.exports,该内容在WebAssembly.instatiateStreaming(fetch(...), importObjects).then(obj => { wasm = obj.instance.exports; })的then语句中设置
进行了这些更改后,它为我工作(向WebAssembly发送和从WebAssembly读取字符串)

答案 1 :(得分:0)

关注Ben的回答。 .wasm文件以application/javascript哑剧发送,因此浏览器试图将其作为javascript执行。要与application/wasm哑剧一起发送,请确保您的回复类型为Option<rocket::response::NamedFile>

这是一个例子:

#[get("/pkg/<file..>")]
fn get_pkg(file : PathBuf) -> Option<rocket::response::NamedFile> {
   NamedFile::open(Path::new("client/pkg/").join(file)).ok()
}

关于第二个问题-事实证明,而不是手动编辑wasm-pack build生成的javascript,您实际上可以要求wasm-pack生成可以在浏览器中运行并加载wasm的javascript。简单地做 wasm-pack build --target web

剩下要做的就是在您这一边添加以下内容:

<script type="module">
  import init from './pkg/client.js'; //client.js is the file generated by wasm
  async function run() {
    await init();
  }
  run();
</script>