wasmerio / wasmer-js

Monorepo for Javascript WebAssembly packages by Wasmer

Home Page:https://wasmerio.github.io/wasmer-js/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

wasmer-js import issue in nodejs v16.15.1

mhykes opened this issue · comments

Issue:
When I pass imports to wasi.instantiate() and have a module that tries to import those imports, I get an error and my module won't load. This isn't related to the chrome browser issue since this is 100% server side. I've only tested this in nodejs v16.15.1 so far, but I'd be very surprised of this was related to the version of nodejs.

Example:
Create a nodejs project with npm init.
Run npm i @wasmer/wasi wabt
Save the code below as index.js

Expected: I can run node index.js and get back

==RESULTS==
{ nopResult: { resultCode: 0 }, minResult: { resultCode: 0 } }
==DONE==

Actual: I run node index.js and get back

ERROR: minimal import test
 Error: Failed to instantiate WASI: RuntimeError: `
    at B.wbg.__wbg_new_342a24ca698edd87 (/home/***/webassembly/wasmer/wasmInJs/minimal/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:11276)
    at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
    at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
    at s.instantiate (/home/***/webassembly/wasmer/wasmInJs/minimal/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
    at startWasiTask (/home/***/webassembly/wasmer/wasmInJs/minimal/index.js:64:35)
    at async run (/home/***/webassembly/wasmer/wasmInJs/minimal/index.js:75:17)
SUCCESS: nop
==RESULTS==
{ nopResult: { resultCode: 0 }, minResult: undefined }
==DONE==

NodeJs File: index.js

const fs = require("fs")
const { init, WASI } = require("@wasmer/wasi");
const { exit } = require("process");
const wabtFactory = require("wabt");

async function run() {

  // Load the WASI library
  await init();

  // Construct wabt
  const wabt = await wabtFactory();


  // A minimal wat that does nothing
  //  also import from wasi_unstable so it is recognized as wasi
  const nopWat = `(module 
    (import "wasi_unstable" "fd_write" (func (param i32 i32 i32 i32) (result i32)))
    (memory (export "memory") 0 32)
    (func $run )
    (export "_start" (func $run)))`;

  // A minimal wat with a custom import
  //  also import from wasi_unstable so it is recognized as wasi
  const minWat = `(module 
    (import "console" "echo" (func $echo (param $char i32)))
    (import "wasi_unstable" "fd_write" (func (param i32 i32 i32 i32) (result i32)))
    (memory (export "memory") 0 32)
    (func $run )
    (export "_start" (func $run)))`;

  // Convert the wat to wasm bytes
  const nopWasmModule = wabt.parseWat('nop.wat', nopWat);
  const minWasmModule = wabt.parseWat('min.wat', minWat);
  const nop = nopWasmModule.toBinary({});
  const min = minWasmModule.toBinary({});

  // Instantiate WASI
  let wasi = new WASI({
    args: [],
    env: {}
  })

  // Async function to run our Wasm module/instance
  const startWasiTask =
    async options => {

      // Get the buffer from options
      const { buffer } = options;

      // Format the wasm bytes
      let wasmBytes = new Uint8Array(buffer);

      // Compile the WebAssembly file into a module
      const module = await WebAssembly.compile(wasmBytes);

      // Build imports object to pass to the module
      const importsProvided = {
        'console': {
          'echo': echo
        }
      }

      // Instantiate the module
      const instance = await wasi.instantiate(module, importsProvided);

      // Start the WASI instance
      const resultCode = wasi.start();

      return {resultCode};
    }

  // Run the minimal import test
  let minResult;
  try {
    minResult = await startWasiTask(min);
    console.log('SUCCESS: minimal import test');
  } catch(err) {
    console.log('ERROR: minimal import test\n', err);
  }

  // Run the nop
  let nopResult;
  try {
    nopResult = await startWasiTask(nop);
    console.log('SUCCESS: nop');
  } catch(err) {
    console.log('ERROR: nop\n', err);
  }

  return {nopResult, minResult};
}

run().then((result)=>{
  console.log('==RESULTS==');
  console.log(result);
  console.log('==DONE==');
}).catch((err)=>{
  console.log(err);
})


// Implement "console"."echo": [I32] -> []
function echo(i) {
  console.log(`${i}`);
}

Can someone at least confirm this issue so I know it isn't just something with my setup?

I tried stepping through it in the vscode debugger, but the errors seem to happen inside some bytecode / minified code. I can't quite follow what is going on.

Yes, this is an issue in wasmer-js. We worked half in #299 and when it's shipped it will be fully fixed!

The PR #299 is now fixed and this issue should be resolved by now.
We've published the version 1.1.0 in NPM with the fix.

Closing the issue! (let me know if it persists)