wasmerio / wasmer-js

Monorepo for Javascript WebAssembly packages by Wasmer
https://wasmerio.github.io/wasmer-js/
MIT License
916 stars 81 forks source link

Allow custom imports #369

Open FranklinWaller opened 9 months ago

FranklinWaller commented 9 months ago

Our runtime is half based on WASI with a few custom functions that are specific for blockchains. We use Wasmer-js for the SDK (And Wasmer-rust for the node). In previous versions of Wasmer-js we could specify extra custom imports (through passing WebAssembly.instantiate(module, customImports);). However in the latest Wasmer-js it doesn't seem like we can pass in custom imports anymore. Is this something that will eventually? We are looking to upgrade due the WASIX support.

linear[bot] commented 9 months ago

SDK-39 Allow custom imports

Michael-F-Bryan commented 9 months ago

This is a limitation of the current wasmer_wasix::WasiEnvBuilder API. We need to update it so you can provide your own custom imports, then add them to the imports object here.

Once that is in place, it should be possible to thread the imports through the wasmer_wasix::runners::WasiRunner, and then add an adapter to the @wasmer/sdk package which lets you use JavaScript functions as the imports.

Michael-F-Bryan commented 8 months ago

It turns out custom imports aren't compatible with the way we do multi-threading.

A big part of the @wasmer/sdk API is how we'll execute WebAssembly modules on a background thread (Web Worker) and give users an Instance handle they can use to communicate with the actual instance (reading stdout/stderr, writing to stdin, waiting for it to exit, etc.). This causes issues with custom imports because the JavaScript values you pass in are tied to the JavaScript VM and can't be accessed from other threads.

I've worked around this in the past by setting up the API so values are passed between threads via postMessage() (see the Scheduler abstraction), but that's just not possible in this scenario because @wasmer/sdk doesn't have control over how the wasmer::Imports object is passed to workers.

Another approach I took in #337 was to create a proxy object which would implement virtual_fs::FileSystem by sending messages to a listener running on the FileSystemDirectoryHandle's original thread.

https://github.com/wasmerio/wasmer-js/blob/ecbb8e64a96026bf28190c1456a2bde6c688d1dd/src/fs/actors.rs#L44-L66

However, this approach won't work for custom imports because sending messages is an async operation and functions passed to wasmer::Imports need to be synchronous. It also runs into problems when dealing with imports like WebAssembly.Memory or externref because you need the actual WebAssembly.Memory value when instantiating - a proxy or copy isn't good enough.

Unfortunately, I think we'll need to close this issue because it doesn't appear possible within the constraints of our current architecture.

FranklinWaller commented 8 months ago

That's ok, thank you for taking a look @Michael-F-Bryan Maybe with https://github.com/wasmerio/wasmer-js/issues/370 we can do something similiar and less rely on custom imports and more on something that is also part of WASI(X)

theduke commented 4 months ago

Re-opening because this is still a valid feature request.

mfcekirdek commented 4 months ago

I also need this feature for my use case