1

I'm not able to get emscripten wasm to work within react.

  • Create a fresh app with create-react-app

  • installed react-app-rewired 2.1.6 and wasm-loader 1.3.0

  • added config-override.js with

    const path = require("path");
    
    module.exports = function override(config, env) {
      const wasmExtensionRegExp = /\.wasm$/;
    
      config.resolve.extensions.push(".wasm");
    
      config.module.rules.forEach((rule) => {
        (rule.oneOf || []).forEach((oneOf) => {
          if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) {
            // make file-loader ignore WASM files
            oneOf.exclude.push(wasmExtensionRegExp);
          }
        });
      });
    
      // add a dedicated loader for WASM
      config.module.rules.push({
        test: wasmExtensionRegExp,
        include: path.resolve(__dirname, "src"),
        use: [{ loader: require.resolve("wasm-loader"), options: {} }],
        type: "javascript/auto",
      });
    
      return config;
    };
    

Compiled the c code with:

emcc src\emsample.c -s WASM=1 -o deploy\www\emsample.js -s "EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap']" -s EXPORTED_FUNCTIONS="['_sayHi', '_myFunction', '_daysInWeek', '_int_sqrt', '_main']" -s MODULARIZE -s EXPORT_NAME=EmSample -s 

Copied wasm and js file to /src folder

Next i wanted to make use of the wasm and added to App.js:

[...]
import EmSample from "./emsample";

EmSample({
  global: {},
  env: {
    memoryBase: 0,
    tableBase: 0,
    memory: new WebAssembly.Memory({ initial: 256 }),
    table: new WebAssembly.Table({ initial: 0, element: "anyfunc" }),
  },
}).then((instance) => {
  // What is with the weird exports._Z4facti function?
  // This is how the function name is encoded by the C++ to wasm compiler
  const sayHi = instance.exports._myFunction;

  console.log(sayHi());
});
[...]

Which gives the error:

Uncaught (in promise) TypeError: WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function

If I change import statement to

//Remark: add /*eslint-disable*/ to emsample.js to avoid problems with eslint
import EmSample from "./emsample.js";

gives the error:

Uncaught (in promise) RuntimeError: abort(CompileError: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 44 4f @+0) at Error

I played around with lot of different emcc settings without success.

Using the same wasm file within a simple HTML page works well

<!DOCTYPE html>
<title>Emscripten + npm example</title>
Open the console to see the output from the wasm module.
<script type="module">
  import EmSample from "./emsample.js";

  EmSample().then(function (mymod) {
    console.log(mymod._sayHi());
    const mySqrt = mymod.cwrap("int_sqrt", "number", ["number"]);
    console.log(mySqrt(64));
    console.log(mySqrt(7));
    console.log(mySqrt(8));
    console.log(mymod._myFunction());
    console.log(mymod._daysInWeek());
  });
</script>

What I'm missing to make it work in a react application?

mcd
  • 101
  • 1
  • 7

0 Answers0