-
Notifications
You must be signed in to change notification settings - Fork 114
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
Example running using Node.js as a host #649
Comments
There isn't one presently. I'm certainly open to a contribution adding one.
I haven't tested it but it should be. At the moment, Javy modules don't have any non-WASI function imports. |
I am happy to contribute once I have something working. |
@jeffcharles I created an example https://github.com/asprouse/javy-nodejs-example It is based on the sample code from this repo's readme I am having an issue with reading the input from stdin. I get the following:
I think the issue is with |
Is there any output printed to the stderr or stdout files when you see the unreachable Wasm trap? If there is, that could indicate what the error in JavaScript was. We usually use Wasmtime and it definitely outputs error messages that we emit from inside the Wasm. You should be able to just run something like Another approach if there is not output in the stderr or stdout files and you don't want to use Wasmtime, is you could try inserting calls to |
Thanks for the advice! I updated the code in The only thing left is to get the dynamic linking working. Once that is in place what is the best way to contribute? A PR with an update to the readme with a link to my repo or we could create a |
I'm happy you got your code working 😄!
I was thinking just including a snippet of what you have in |
Ok sounds good I will prepare a PR. My next issue is with using the dynamic linking feature ( Now I get the error:
This error is thrown when running wasi.start(). When adding a
When I run the same code but without using
Am I missing something to get this working? Thanks again for your continued support. |
Could you try not providing the WASI imports when instantiating the Something like const provider = await WebAssembly.compile(
await readFile(new URL("./provider.wasm", import.meta.url)),
);
const wasiImports = wasi.getImportObject();
const providerInstance = await WebAssembly.instantiate(provider, wasiImports);
const instance = await WebAssembly.instantiate(wasm, {
javy_quickjs_provider_v1: providerInstance.exports,
}); The dynamic module should be sending its bytecode to the provider instance which is what imports the WASI functions. Not 100% sure that will work but worth a try. |
I was able to get this to work by overriding the const providerInstance = await WebAssembly.instantiate(
providerModule,
wasi.getImportObject(),
);
const instance = await WebAssembly.instantiate(embeddedModule, {
javy_quickjs_provider_v1: providerInstance.exports,
});
const {_start} = instance.exports;
// Hack to add the memory export from the provider module
Object.defineProperty(instance, "exports", {
get() {
return {
_start,
memory: providerInstance.exports.memory,
};
},
}); This feels hacky, is it a limitation in node's api that you cannot specify the |
I haven't had a chance to experiment with Node's WASI APIs so I don't have an answer off-hand. Hypothetically we could have the dynamically linked module re-export the memory from the provider. This file uses Walrus to write the module. It looks like it's the use of |
An alternative, and potentially the right thing to do in this case, is to use the
Here's a diff of the changes: diff --git a/host.mjs b/host.mjs
index 4004737..ca64be6 100644
--- a/host.mjs
+++ b/host.mjs
@@ -61,16 +61,22 @@ async function run(wasmFilePath, input) {
const {_start} = instance.exports;
// Hack to add the memory export from the provider module
- Object.defineProperty(instance, "exports", {
- get() {
- return {
- _start,
- memory: providerInstance.exports.memory,
- };
- },
- });
+ // Object.defineProperty(instance, "exports", {
+ // get() {
+ // return {
+ // _start,
+ // memory: providerInstance.exports.memory,
+ // };
+ // },
+ // });
- wasi.start(instance);
+ wasi.initialize(providerInstance);
+ _start();
+
+ // Don't invoke through Wasi given that the dynamically linked module
+ // doesn't make use of any WASI APIs.
+ // wasi.start(instance);
const [out, err] = await Promise.all([
readOutput(stdoutFilePath), |
Ok that works and is much cleaner. I have made the change here: @saulecabrera @jeffcharles What do you think of the current state of the example? Thanks again for all your help 😄 ! |
In general it looks good to me. I'd suggest updating the example to use Feel free to open a PR and we'd be happy to review in more detail! |
I'll go ahead and close this one as #661 was merged; feel free to reopen if there's anything missing. |
Background
I am looking for a way to run user generated javascript securely in a Node.js host (not Node.js code in QuickJS). We have considered
node:vm
based solutions like https://github.com/laverdet/isolated-vm but most of these libraries are not maintained and warn against running untrusted user code. Ideally I want to generate a WASM module with multiple exports, one for each user defined function.Question
Is there a basic example of how to run a Javy generated module in a Node.js host? Is this possible with node's built-in WASI support?
The text was updated successfully, but these errors were encountered: