nodejs / node

Node.js JavaScript runtime ✨🐢🚀✨
https://nodejs.org
Other
105.86k stars 28.75k forks source link

WASI stdio (stdin, stdout) API not very useful #52614

Open Timmmm opened 3 months ago

Timmmm commented 3 months ago

What is the problem this feature will solve?

Currently the WASI API only lets you give file descriptors for stdin, stdout and stderr. That's not very useful. In most cases I want to interact with these streams which doesn't seem possible - at least not without a ton of platform specific work - with just file descriptors.

What is the feature you are proposing to solve the problem?

You should be able to pass ReadableStream and WritableStream instead. You can do this when spawning subprocesses.

What alternatives have you considered?

Slightly ludicrously, spawning a new child process that just starts the WASI module and does nothing else seems to be the most reasonable workaround currently, though I haven't tried it.

RedYetiDev commented 3 months ago

Hi! Thanks for the feature request! Could you possible provide more context?

It'd be really helpful if you could give us a comparison of the current features vs the proposed ones.

Thank you!

benjamingr commented 3 months ago

@nodejs/wasi

Timmmm commented 3 months ago

@RedYetiDev sure!

Currently the Node API for WASI is:

image

In other words when you start a WASI module, the only option for its stdin/out/err are to give real native file handles. This is quite weird and also inconvenient.

It's weird because WASI's environment is fully controlled by Node. When it writes to stdin it isn't executing native code that requires a file handle, it's calling some WASM interface function that Node provides. I presume this design is something to do with the big warning about WASI's filesystem access not being sandboxed at all at the moment. Presumably they've done the very simplest thing - just pass through WASI filesystem calls to the OS. So I think this is probably intended to be temporary anyway.

It's inconvenient because you can't interact with stdin/out/err except via a file descriptor. The only way to do this through Node is by making a file on disk which is not what you would usually want. My use case is a VSCode LSP server; stdio is used for communication.

Another option would be the pipe() C function, but unfortunately it does not seem to be exposed by Node.

The API should look more like the API for creating a child process, where you can tell it to "pipe" the streams and then retrieve a stream.Readable/Writable for each.

Hope that makes sense! The workaround I am considering is just to fork() node, and run a module which only starts my WASI program. I think fork() lets you pipe the stdio streams, but I haven't actually tried it yet.

RedYetiDev commented 3 months ago

Thanks! That makes more sense. I'm not on the WASI team, but the context will help them when they review this.

Thanks again for your contribution to the community!

mhdawson commented 3 months ago

@Timmmm you might want to check out - https://github.com/nodejs/uvwasi/issues/255. I'm not sure how much preview 1 functionality wil be extended in that context so you might want to see if the preview 2 functionality provided via jco is something you want to use instead.