Deno 向けの WASM を作って公開しようとしたけど、上手くいかなかったので、暫定対応と合わせてメモ。
何が起きたのか
そもそも、wasm-bindgen の Deno 向けの生成をすると、
WASM を以下のようなコードで読み込もうとする。
1
| const wasmModule = new WebAssembly.Module(Deno.readFileSync(wasmFile));
|
ローカルに置いてある WASM を読み込むことを前提になっている。
これ故に、例えば github で公開しても動作できない。
さらに、ネットワークから .wasm を取得するとき、WebAssembly の mime type の指定もある。
application/wasm
でサーバーが返さないと、エラーになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const file = new URL(import.meta.url).pathname; const wasmFile = file.substring( 0, file.lastIndexOf(Deno.build.os === "windows" ? "\\" : "/") + 1 ) + "wasm_test_bg.wasm"; const wasmModule = new WebAssembly.Module(Deno.readFileSync(wasmFile)); const wasmInstance = new WebAssembly.Instance(wasmModule, imports); const wasm = wasmInstance.exports;
const url = new URL(import.meta.url); const splitedUrl = url.href.split("/"); splitedUrl.pop(); const dir = splitedUrl.join("/");
const { instance, module } = await WebAssembly.instantiateStreaming( fetch(`${dir}/wasm_test_bg.wasm`) ); const wasm = instance.exports;
|
実行すると、次のようなエラー。
1 2 3 4
| import {myAdd} from "https://raw.githubusercontent.com/Octo8080X/deno-wasm-test/main/pkg-a/wasm_test.js" Download https: Uncaught TypeError: Invalid WebAssembly content type. at deno:extensions/fetch/26_fetch.js:498:17
|
こんなエラーになってしまう。
mime type
は、application/wasm
じゃないとエラーになる。
暫定対応
暫定で、wasm を fetch で取得してバイナリをインスタンス化すると、mime type が対応していなくても大丈夫。
1 2 3 4 5 6 7 8 9 10 11 12 13
| const url = new URL(import.meta.url);
const permit = { name: "net", host: url.host }; await Deno.permissions.request(permit);
const splitedUrl = url.href.split("/"); splitedUrl.pop(); const dir = splitedUrl.join("/"); const response = await fetch(`${dir}/wasm_test_bg.wasm`); const buffer = await response.arrayBuffer(); const wasmInstance = await WebAssembly.instantiate(buffer, imports); const wasm = wasmInstance.instance.exports;
|
ただし、大きな欠陥があって、–allow-net が必要。
実行時のオプションで、host を渡すのは面倒なので、Deno.permissions.request
を使って対話的に処理させる。
読み込む側のコードは、次のようになる。
use_wasm.ts1 2
| import {myAdd} from "https://raw.githubusercontent.com/Octo8080X/deno-wasm-test/main/pkg-n/wasm_test.js" console.log(myAdd(4, 2))
|
実行すると、以下のようになる。
1 2 3 4 5 6 7 8 9 10
| $ deno run d.ts Download https://raw.githubusercontent.com/Octo8080X/deno-wasm-test/main/pkg-n/wasm_test.js Check file:///usr/src/app/d.ts ⚠️ ️Deno requests network access to "raw.githubusercontent.com". Allow? [y/n (y = yes allow, n = no deny)] y 6
$ deno run --allow-net d.ts 6
|
Deno.permissions.request
の便利さを再確認できた。
何も解決してない
実は、Deno Manual - WebAssembly supportに対応策は、書いてある。
Uint8Array に分解して、どうやらぶちまけるといいらしい。
今度はこれにチャレンジする。
ではでは。