wasmer-js
wasmer-js copied to clipboard
WASI RuntimeError occurs when loading .wasm with import other than WASI function
Hello.
In wasmer-js 1.0.2, WASI RuntimeError occurs when loading .wasm with import other than WASI function.
This occurs when there is an (import "module" "external".
test.wasm: test.wasm.zip
(import "module" "external" (func $_ZN11chipbx_core8external17h1c65b4913beb0195E (type $t0)))
(import "wasi_snapshot_preview1" "fd_write" (func $_ZN4wasi13lib_generated22wasi_snapshot_preview18fd_write17hf61715b32291be1dE (type $t8)))
(import "wasi_snapshot_preview1" "environ_get" (func $__imported_wasi_snapshot_preview1_environ_get (type $t4)))
(import "wasi_snapshot_preview1" "environ_sizes_get" (func $__imported_wasi_snapshot_preview1_environ_sizes_get (type $t4)))
(import "wasi_snapshot_preview1" "proc_exit" (func $__imported_wasi_snapshot_preview1_proc_exit (type $t1)))
Error message:
Error: Failed to instantiate WASI: RuntimeError: `
at B.wbg.__wbg_new_342a24ca698edd87 (/home/hiromasa/devel/amd64/chipbx/chipbx-js/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/hiromasa/devel/amd64/chipbx/chipbx-js/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
at file:///home/hiromasa/devel/wasm/test/src/index.mjs:18:12
test.wasm (Rust cargo build --target=wasm32-wasi --release):
fn main() {
println!("internal: hello world!");
unsafe { external(); }
}
#[link(wasm_import_module = "module")]
extern { fn external(); }
JavaScript (node.js):
import { init, WASI } from '@wasmer/wasi';
import * as fs from 'fs';
await init();
let wasi = new WASI({
env: {
},
args: [
],
});
const moduleBytes = fs.readFileSync('src/test.wasm');
const module = await WebAssembly.compile(moduleBytes);
await wasi.instantiate(module, {
'module': {
'external': function() { console.log("external: hello world!") }
}
});
// Run the start function
let exitCode = wasi.start();
let stdout = wasi.getStdoutString();
// This should print "hello world (exit code: 0)"
console.log(`${stdout}(exit code: ${exitCode})`);
I think it was probably the way the imports argument was specified in wasi.instantiate. In wasmer-python, I was able to get imports in the following way. How do I do it in wasmer-js?
Python:
import os
from wasmer import engine, wasi, Store, Module, Instance, Function
from wasmer_compiler_cranelift import Compiler
#
# import function
#
def external():
print("external: hello world!")
# read .wasm file
__dir__ = os.path.dirname(os.path.realpath(__file__))
wasm_bytes = open(__dir__ + '/test.wasm', 'rb').read()
# setup
store = Store(engine.JIT(Compiler))
module = Module(store, wasm_bytes)
# create WASI env
wasi_version = wasi.get_version(module, strict=False)
wasi_env = \
wasi.StateBuilder('test'). \
map_directory('the_host_current_dir', '.'). \
finalize()
import_object = wasi_env.generate_import_object(store, wasi_version)
external_function = Function(store, external)
# register import
import_object.register(
"module",
{
"external": external_function
}
)
# create instance
instance = Instance(module, import_object)
# start
instance.exports._start()
wasmer-python result: success
internal: hello world!
external: hello world!
Can you attach here the wasm file so I can test and do a new release?
It should be supported, so I'm not sure what's happening
Yes. It is attached to the previous post. The .wasm is the link below.
Please let me know if there is any information that is missing. Thank you for your support.
EDIT I think this is more likely https://github.com/wasmerio/wasmer-js/issues/302
I can successfully run the wasm with Safari.
Having the similar issue here.
Error: Failed to instantiate WASI: RuntimeError: `
at B.wbg.__wbg_new_342a24ca698edd87 (Library.esm.min.js:25:11042)
at 0024ee5a:0x7c9d3
at 0024ee5a:0x19d5a
at s.instantiate (Library.esm.min.js:25:6735)
at main (index.js:14:1)
However there's no imported modules with my case.
Here's my .wasm (compiled using WasmSwift), it should just print "42. hello.wasm.zip
The hello.wasm works fine with wasmer
> wasmer hello.wasm
42
I use webpack 5, with buffer polyfill.
"devDependencies": {
"buffer": "^6.0.3",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2"
},
"dependencies": {
"@wasmer/wasi": "^1.0.2"
}
//webpack.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'development',
//...
externals: {
'wasmer_wasi_js_bg.wasm': true
},
resolve: {
fallback: {
buffer: require.resolve('buffer/'),
},
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
}),
]
};
I'm running into this problem too with cura-engine and @wasmer/wasi V1.0.2
Output from the minified version (@wasmer/wasi)
Error: Failed to instantiate WASI: RuntimeError: `
at B.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/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 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
at main (/root/cura-engine/wasmer.js:26:21)
Output from the unminified version (@wasmer/wasi/dist/Library.cjs)
Error: Failed to instantiate WASI: RuntimeError: `
at imports.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:880:19)
at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
at WASI.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:583:24)
at main (/root/cura-engine/wasmer.js:26:21)
Note: the cura-engine WASM binary is quite large but I'm not sure that's what's causing this given the below reproduction. Furthermore, compiling without imported functions works fine with this library.
Minimal Reproduction
WASM Source
#include <stdio.h>
#include <stdint.h>
//Web Assembly V1 data types
typedef int32_t i32;
//Imported callback function
i32 callback(i32 num);
int main()
{
//Print
printf("Before\n");
//Invoke the callback
i32 result = callback(9+9);
//Print
printf("After (Result: %i)\n", result);
return 0;
}
Note: compile with wasicc test.c -o test.wasm -Wl,--allow-undefined. Also, when I inspect the output, I see (import "env" "callback" (func $callback (type $t3))) so I'm pretty sure this is compiling correctly.
Host
//Imports
const {readFile} = require('fs/promises');
const {init, WASI} = require('@wasmer/wasi');
const main = async () =>
{
//Initialize WASI
await init();
//Instantiate the WASI interface
const wasi = new WASI({
args: [],
env: {},
});
//Read the web assembly
const buffer = await readFile('./test.wasm');
//Compile the web assembly
const module = await WebAssembly.compile(new Uint8Array(buffer));
//Instantiate the web assembly
wasi.instantiate(module, {
env: {
//Callback
callback: num =>
{
//Computer result
const result = num + 5;
//Log
console.log(`[Callback] Invoked with ${num}, result: ${result}`);
return result;
}
}
});
//Run the web assembly
wasi.start();
//Get the output
const stdout = wasi.getStdoutString();
//Log
console.log(stdout);
};
main();
Output from the minified version (@wasmer/wasi)
Error: Failed to instantiate WASI: RuntimeError: `
at B.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/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 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.min.js:26:6805)
at main (/root/cura-engine/test-wasmer.js:23:8)
Output from the unminified version (@wasmer/wasi/dist/Library.cjs)
Error: Failed to instantiate WASI: RuntimeError: `
at imports.wbg.__wbg_new_342a24ca698edd87 (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:880:19)
at wasm://wasm/0024ee5a:wasm-function[823]:0x7c9d3
at wasm://wasm/0024ee5a:wasm-function[79]:0x19d5a
at WASI.instantiate (/root/cura-engine/node_modules/@wasmer/wasi/dist/Library.cjs.js:583:24)
at main (/root/cura-engine/test-wasmer.js:23:8)
Workaround
Since this is a showstopper for me, I've resorted to using the experimental native wasi module. However, this doesn't work in the browser and many convenient APIs (eg: the virtual filesystem) aren't available.
Host
//Imports
const {readFile} = require('fs/promises');
const {WASI} = require('wasi');
const main = async () =>
{
//Instantiate the WASI interface
const wasi = new WASI({
args: [],
env: {},
});
//Read the web assembly
const buffer = await readFile('./test.wasm');
//Compile the web assembly
const module = await WebAssembly.compile(new Uint8Array(buffer));
//Instantiate the web assembly
const instance = await WebAssembly.instantiate(module, {
wasi_snapshot_preview1: wasi.wasiImport,
env: {
//Callback
callback: num =>
{
//Computer result
const result = num + 5;
//Log
console.log(`[Callback] Invoked with ${num}, result: ${result}`);
return result;
}
}
});
//Run the web assembly
wasi.start(instance);
};
main();
Note: run with the --experimental-wasi-unstable-preview1 flag.
Output
(node:32388) ExperimentalWarning: WASI is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Before
[Callback] Invoked with 18, result: 23
After (Result: 23)
Note: this is the expected output.
Verified that this issue is fixed with the PR upgrading to Wasmer 3.0 wasmerio/wasmer#299 (we also added a test case to make sure it remains fixed in future releases).
We'll publish a new version soon
~I have a .wasm file generated by the wasi sdk v16 via rust which makes use of wasi_snapshot_preview1 methods. Looking forward to a new release. In the meantime, I'll do a local build of @wasmer/wasi from main.~ Ignore this, I wasn't using the library properly. Things are working fine for me the current release.