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

Add 'fileDescriptors' option to allow file I/O to be used in the browser #59

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

kevinbarabash
Copy link

This option is only used by wasi-browser.ts. It doesn't really make sense for node/deno/bun since those runtimes have native support for WASI.

I'm having issues running the tests so I haven't bothered trying to enable fileAccess for the browser tests.

I have done some manual testing to verify that things are working as expected. I have a plugin with the following F# cord:

[<UnmanagedCallersOnly(EntryPoint = "greet")>]
let Greet () : int32 =
    printfn "Greet called"

    let contents = File.ReadAllText("./input.txt")
    printfn "contents = %s" contents
    
    let input = Pdk.GetInputString()
    printfn $"input = {input}"
    let data = JsonSerializer.Deserialize<Data> input
    
    printfn $"greeting = {data.greeting}, name = {data.name}"
    
    let result = $"{data.greeting}, {data.name}!"
    Pdk.SetOutput(result)
    0

The JavaScript host code looks like this (note, this requires input.txt to exist in the directory being served):

import createPlugin from '@extism/extism';
import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim";

const input = await fetch(`/input.txt`);
const inputBuffer = await input.arrayBuffer();

const url = new URL(`${location.protocol}/${location.host}/Plugin/bin/Debug/net8.0/wasi-wasm/AppBundle/Plugin.wasm`);
const options = { 
    useWasi: true, 
    enableWasiOutput: true,
    fileDescriptors: [
        new PreopenDirectory(".", {
            "input.txt": new File(inputBuffer),
        }),
    ]
};
const plugin = await createPlugin(url, options);

const input = JSON.stringify({ greeting: "hello", name: "world" });
const out = await plugin.call("greet", input);
console.log(out.text());

The output in the browser console looks like this:

Greet called
contents = This is a text file
input = {"greeting":"hello","name":"world"}
greeting = hello, name = world
hello, world!

@@ -1,3 +1,4 @@
import { Fd } from '@bjorn3/browser_wasi_shim';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll want to find a way for each polyfill to expose their own platform-specific Wasi options, vs. making all of the polyfills aware of @bjorn3/browser_wasi_shim. For example, node and deno's WASI implementations don't allow for arbitrary fds to be passed in, & rely on "preopens" instead.

(It might make sense to let users pass in their own instance that conforms to a {close(), initialize(WebAssembly.Instance), importObject()} interface?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing in an a WASI instance seems like the way to go. I'll update this PR this weekend.

Do you know what's up with the tests? I tried running the tests on CI without any code changes in escalier-lang#2 and am seeing the same failure in that PR as in this PR.

Copy link
Contributor

@chrisdickinson chrisdickinson Apr 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah – there was a node:worker_threads regression on upstream Deno; it sounds like they've got a fix for it in canary, though.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get to it this weekend. Next weekend is a long weekend so I'll have more time.

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

Successfully merging this pull request may close these issues.

2 participants