Неверный или неожиданный токен в WebAssembly

Я пытаюсь запустить программу WebAssembly (написанную на Rust, пример программы из https://rustwasm.github.io/book/game-of-life/hello-world.html) с Rocket. WebAssembly компилируется с помощью wasm-pack и использует wasm_bindgen. Двоичный файл wasm представлен в виде content::JavaScript<Vec<u8>> в Rocket, и кажется, что это "рабочее" решение. Двоичный файл выбирается "правильно", однако Chrome печатает Uncaught SyntaxError: Invalid или неожиданный токен. Это из-за представления как content::JavaScript<Vec<u8>> что во время выборки произошла ошибка (хотя байты отправки совпадают с байтами в файле wasm) или ошибка в другом месте?

Я надеюсь, что кто-то может объяснить мне, почему в сгенерированном двоичном файле есть ошибка SyntaxError.

1 ответ

Хорошо, теперь я думаю, что знаю, что пошло не так: файл js, сгенерированный из пакета wasm, пытается загрузить WebAssembly как модуль. Модуль должен иметь MIME Javascript, иначе он потерпит неудачу (поэтому я попытался отправить файл wasm как content::JavaScript<Vec<u8>>), но, очевидно, загрузка wasm как модуля не поддерживается (поправьте меня, если я ошибаюсь), поэтому, конечно, он найдет недопустимый токен в двоичном файле, потому что он пытается интерпретировать его как простой javascript. Что я на самом деле использую сейчас Option<NamedFile> типа от Ракетной ведьмы есть application/wasm мим.
Мне нужно было немного изменить сгенерированный файл js: WebAssembly инициализируется с WebAssembly.instatiateStreaming(fetch(...), importObjects), импорт модуля должен быть удален. importObjects тоже было немного сложно, потому что передача стрингов в 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. Последнее, что нужно изменить, - это объект, который был изначально импортирован через import заявление. У меня теперь есть переменная, которая имеет содержимое из obj.instance.exports который установлен в тогдашнем утверждении от WebAssembly.instatiateStreaming(fetch(...), importObjects).then(obj => { wasm = obj.instance.exports; })
С этими изменениями у меня получилось (отправка и чтение строк в / из WebAssembly)

Продолжая ответ Бена. В.wasm файл отправляется с application/javascriptmime, таким образом, браузер пытается выполнить его как javascript. отправить его сapplication/wasm mime убедитесь, что ваш ответ имеет тип 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()
}

Что касается второй проблемы - получается, а не вручную редактировать javascript, сгенерированный wasm-pack build вы действительно можете спросить wasm-packчтобы сгенерировать javascript, который можно запустить в браузере и загрузить ваш wasm. просто делай 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>
Другие вопросы по тегам