js-sdk icon indicating copy to clipboard operation
js-sdk copied to clipboard

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

Open k4b7 opened this issue 1 year ago • 0 comments

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!

k4b7 avatar Mar 25 '24 02:03 k4b7