Importing WASM files into Electron main process
Mia Lopez
I'm building an Electron app that needs to use Web-Assembly (WASM), however I'm hitting an issue with Fetch throwing a TypeError: Only absolute URLs are supported when importing my WASM file.
Also, perhaps this raises the broader question as to whether the Electron main process or the renderer process should be used to run the WASM ? It does seem to work in the render process.
Here's the complete error:
TypeError: Only absolute URLs are supported at parseURL (/Users/devuser/development/electron-api-demos/node_modules/node-fetch/dist/index.cjs:897:8) at new Request (/Users/devuser/development/electron-api-demos/node_modules/node-fetch/dist/index.cjs:922:17) at /Users/devuser/development/electron-api-demos/node_modules/node-fetch/dist/index.cjs:1175:19 at new Promise (<anonymous>) at fetch (/Users/devuser/development/electron-api-demos/node_modules/node-fetch/dist/index.cjs:1173:9) at IpcMainImpl.<anonymous> (/Users/cbourne/development/electron-api-demos/main-process/communication/async-msg.js:20:36) at IpcMainImpl.emit (events.js:223:5) at WebContents.<anonymous> (electron/js2c/browser_init.js:4093:15) at WebContents.emit (events.js:223:5)And here's the main-process code I'm testing with:
const {ipcMain} = require('electron')
require('/Users/devuser/development/electron-api-demos/script/wasm_exec.js')
const fetch = require("node-fetch");
ipcMain.on('asynchronous-message', (event, arg) => { if (!WebAssembly.instantiateStreaming) { // polyfill WebAssembly.instantiateStreaming = async (resp, importObject) => { const source = await (await resp).arrayBuffer(); return await WebAssembly.instantiate(source, importObject); }; } const go = new Go(); let mod, inst; WebAssembly.instantiateStreaming(fetch("test.wasm"), go.importObject).then((result) => { mod = result.module; inst = result.instance; document.getElementById("runButton").disabled = false; }).catch((err) => { console.error(err); }); async function run() { console.clear(); await go.run(inst); inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance } event.sender.send('asynchronous-reply', 'pong')
}) 3 Answers
The problem is not WASM at all, but the request that is supposed to get the binary. Your fetch comes from node-fetch; the main process runs in Node.js and as such, does not have a base address like a normal page. Either provide a full file:/// absolute URL to fetch, or, more easily, use fs.readFileSync:
const fs = require('fs');
WebAssembly.instantiate(fs.readFileSync("text.wasm")); I can only answer part of your question.
WASM should probably not be run in the Main process. Even though WASM will run in an independent thread, you should reduce the load on the Main process to the maximum extent possible. When the Main process is blocked, even something like minimizing your app will not occur until it becomes unblocked.
For more info, this is a good article:
Have you tried changing fetch("test.wasm") to fetch("./test.wasm") or hardcoding a direct path to local file at least for dev purposes?