Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import node.js's WASI imports in Asyncify #9

Closed
Pl8tinium opened this issue Dec 9, 2023 · 9 comments
Closed

Import node.js's WASI imports in Asyncify #9

Pl8tinium opened this issue Dec 9, 2023 · 9 comments

Comments

@Pl8tinium
Copy link

Hi,

TLDR: Would it be possible to import the default node.js WASI.wasiImport for wasi_snapshot_preview1?

My goal is to run execute golang code that is compiled to WASI in node.js.

For that I used the tinygo compiler and as I compile to WASI am required to provide the import wasi_snapshot_preview1. Usually, without Asyncify, that works fine for me. I just take the default implementation from node.js's WASI.

const { WASI } = require("wasi");
const wasi = new WASI();

WebAssembly.instantiate(wasm, {
            wasi_snapshot_preview1: wasi.wasiImport,
            env: {
                  ...

This does not seem to work in the implementation of Asyncify.

        const wasmInstance = new Asyncify.Instance(wasmModule, {
            wasi_snapshot_preview1: wasi.wasiImport,
            env: {
                      ...

In this concrete example i get

Module loading failed: TypeError: WebAssembly.Instance(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function at new Instance (c:\Users\...\asyncify.mjs:171:5)

Which is probably because of how the imports are wrapped and handled inside of asyncify. Therefore I thought I should directly try it in the asyncify.mjs file like so:

export class Instance extends WebAssembly.Instance {
  constructor(module, imports) {
    let state = new Asyncify();
    let a = { env: state.wrapImports(imports).env, wasi_snapshot_preview1: wasi.wasiImport }
    console.log(a)
    super(module, a);
    state.init(this, imports);
  }
...
}

This yieds the following error:

'TypeError: Cannot read properties of undefine…\wasi.js:14:30', message: 'Cannot read properties of undefined (reading 'memory')'}

My issue might be somewhat related to [this issue].(#8)

As mentioned in the other issue, it might be that my problem needs to be fixed on the tinygo side. Im not entirely sure though.

Expected Behavior

I would be able to import the default wasi implementation of node.js.

Actual Behavior

I cant import the default wasi implementation of node.js.

Steps to Reproduce the Problem

see examples above

Specifications

  • Version: 1.2.0
  • Platform: Windows/ WSL2
@RReverser
Copy link
Collaborator

Module loading failed: TypeError: WebAssembly.Instance(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function at new Instance (c:\Users...\asyncify.mjs:171:5)

What is wasm in your example?

This yieds the following error:

'TypeError: Cannot read properties of undefine…\wasi.js:14:30', message: 'Cannot read properties of undefined (reading 'memory')'}

It's really hard to tell what's going on without error stacktrace, but it sounds like some side is expecting memory to be either imported or exported. At least from Asyncify side, it expects that there is a memory export in the Wasm module - is there one?

Also, I see you're manually wrapping imports, but are you wrapping exports as well?

@Pl8tinium
Copy link
Author

Okay, i think ive made a mistake in the first example, i put everything together and now i do get the same memory error on both solutions.

...Cannot read properties of undefined (reading 'memory')'}

Nevertheless left it in my fork where i demonstrate my issue. Should now be relatively straight forward to understand what my issue is.

https://github.com/Pl8tinium/asyncify/blob/master/example/node_golang/setup.md

@Pl8tinium
Copy link
Author

i think its the "responsibility" of the WebAssembly.Instance class to export memory (WebAssembly.Memory), which in theory should happen as you just inherit from it, though this doesnt seem to be the case. But not sure if my assumptions here are going into the right direction..

@Pl8tinium
Copy link
Author

"but are you wrapping exports as well" is this necessary? without using asyncify i just had to provide the imports

@RReverser
Copy link
Collaborator

"but are you wrapping exports as well" is this necessary

Yes, otherwise your exports won't become Promises, and will return too early.

@Pl8tinium
Copy link
Author

mmh im a bit clueless, is what you mean by wrapping exports to put them into a separate file and export them instead?

https://github.com/Pl8tinium/asyncify/blob/master/example/node_golang/imports.mjs

Or do you mean that to invoke the function i need to screw the exports back on the original WASI object?

import pkg from 'asyncify-wasm';
const Asyncify = pkg;
import { WASI }  from "wasi";
const wasi = new WASI();
...

const wasmInstance = new Asyncify.Instance(wasmModule, {
  wasi_snapshot_preview1: wasi.wasiImport,
...


wasi.exports = wasmInstance.exports;
console.log(wasi.exports.MyAsyncFunction())

As far as i understand it asyncify now needs explicit mentions of the async functions(WebAssembly/binaryen#2322). Thats what this "wrapping exports" is for, right?

And at the end i still got my memory issue, which i was not successful to solve. The "wrapping exports" should not be related to this issue, right?

@Pl8tinium
Copy link
Author

@RReverser do you have an idea on what i could try or look into next?

@RReverser
Copy link
Collaborator

Sorry, no, I'm afraid I don't have time to dig in into a 3rd-party project. I can fix a bug if it turns out to be one in this library, but I'll heave to leave further investigation to you.

@Pl8tinium
Copy link
Author

i found out my issues:

  • only use node version 16 (or lower?)

  • never use a debugger when running wasm code inside of js

everything works now as expected

ty, for your quick responses!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants