0
votes

I was recently using webpack to load the webassembly module, but I found that the current mechanism does not seem to allow me to load two or more identical webassembly modules

My webassembly is generated using the rust toolchain, so it will also generate a js file at the same time, so I dynamically load the generated js file.

My appeal is that I can import multiple instances that do not affect each other through multiple import(). A simple demo is as follow:

const js = import (/ * webpackChunkName: "view_sketch_wasm" * / "../pkg/hello_wasm.js");
js.then (js => {
  js.add_index ();
  js.add_index ();
  let id = js.get_index ();
  console.log ('id:', id);
  let id2 = js.get_index ();
  console.log ('id:', id2);
  const js2 = import (/ * webpackChunkName: "view_wasm_2" * / "../pkg/hello_wasm.js"); // hello_wasm2 also not useful
  js2.then (js => {
    js.add_index ();
    js.add_index ();
    let id = js.get_index ();
    console.log ('js2 id:', id);
    let id2 = js.get_index ();
    console.log ('js2 id:', id2);
  });
});

I hope that js and js2 will not affect each other. They use two WebAssembly instances, each with its own memory. But in fact they used the same WebAssembly instance (even though I copied hello_wasm.js and changed its name). I also looked at the generated code, mainly because the cache was used when wasm was loaded:

wasmModules.forEach (function (wasmModuleId) {
/ ****** / var installedWasmModuleData = installedWasmModules [wasmModuleId];
/ ****** /
/ ****** / // a Promise means "currently loading" or "already loaded".
/ ****** / if (installedWasmModuleData)
/ ****** / promises.push (installedWasmModuleData);
/ ****** / else {
/ ****** / var importObject = wasmImportObjects [wasmModuleId] ();
/ ****** / var req = fetch (__ webpack_require __. p + "" + {"2": "795c98e4258ee4a1e670"} [wasmModuleId] + ".module.wasm");
/ ****** / var promise;
/ ****** / if (importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/ ****** / promise = Promise.all ([WebAssembly.compileStreaming (req), importObject]). then (function (items) {
/ ****** / return WebAssembly.instantiate (items [0], items [1]);
/ ****** /});
/ ****** /} else if (typeof WebAssembly.instantiateStreaming === 'function') {
/ ****** / promise = WebAssembly.instantiateStreaming (req, importObject);
/ ****** /} else {
/ ****** / var bytesPromise = req.then (function (x) {return x.arrayBuffer ();});
/ ****** / promise = bytesPromise.then (function (bytes) {
/ ****** / return WebAssembly.instantiate (bytes, importObject);
/ ****** /});
/ ****** /}
/ ****** / promises.push (installedWasmModules [wasmModuleId] = promise.then (function (res) {
/ ****** / return __webpack_require __. w [wasmModuleId] = (res.instance 
 res) .exports;
/ ****** /}));
/ ****** /}

In addition, even if I modify this part of the code, the mechanism of webpack_require will have a cache, which prevents me from using two separate instances.

Considering that the loading mechanism here is complicated, and I should not modify the compiled code of webpack. I don't know how to do yet.

I also prepared a demo source code: https://github.com/aircloud/hello-wasm2

In summary, my appeal is that I can have multiple instances of webassembly for a wasm file. How can I do this with the current mechanism of webpack?

Thank you!

1

1 Answers

0
votes

If I understood your question correctly. I think the conflict will arises because of multiple references to the same webassembly.

Are you using LLVM compiler? Emscripten is the backend for WebAssembly and LLVM. Emscripten is a source-to-source compiler that runs as a back end to the WebAssembly & LLVM compiler.

Historically, Emscripten only supported one instance per browser context, which is a limitation WebAssembly inherited. More recently Emscripten has added support for multiple instances but not sure if your compiler has gained that feature yet.

I would recommend iframes as workaround. That will keep everything in separate contexts and should work fine.