bytecodealliance / jco

JavaScript toolchain for working with WebAssembly Components
https://bytecodealliance.github.io/jco/
Apache License 2.0
642 stars 64 forks source link

How to use WASI functionality w/ `jco`? #457

Closed danbugs closed 5 months ago

danbugs commented 5 months ago

I created a simple JS module, like:

export function greet(name) {
    console.log(`Hello, ${name}!`);
}

It implements the following WIT:

package component:hello-world-guest-wit;

world example {
    include wasi:cli/imports@0.2.0;
    export greet: func(name: string);
}

To get wasi:cli/imports@0.2.0 I just copied the entire deps folder here: https://github.com/bytecodealliance/wasmtime/tree/main/crates/wasi/wit/deps .

Then, I componentize the JS module partnered w/ the WIT file, like: jco componentize greet.js --wit .\wit\ --world-name example --out greet.wasm.

To test this all out, I implemented a custom host, like:

wasmtime::component::bindgen!({
    path: "../wit",
    world: "example",
});

struct State {
    wasi: wasmtime_wasi::WasiCtx,
    table: wasmtime_wasi::ResourceTable,
}

impl wasmtime_wasi::WasiView for State {
    fn ctx(&mut self) -> &mut wasmtime_wasi::WasiCtx {
        &mut self.wasi
    }

    fn table(&mut self) -> &mut wasmtime_wasi::ResourceTable {
        &mut self.table
    }
}

fn main() {
    let mut config = wasmtime::Config::default();
    config.wasm_component_model(true);

    let engine = wasmtime::Engine::new(&config).unwrap();
    let mut linker = wasmtime::component::Linker::<State>::new(&engine);
    wasmtime_wasi::add_to_linker_sync(&mut linker).unwrap();

    let wasi = wasmtime_wasi::WasiCtxBuilder::new()
        .inherit_stdout()
        .build();

    let mut store = wasmtime::Store::new(&engine, State { wasi, table: wasmtime_wasi::ResourceTable::new() });
    let component = wasmtime::component::Component::from_file(&engine, "../greet.wasm").unwrap();

    let (instance, _) = Example::instantiate(&mut store, &component, &linker).unwrap();

    instance.call_greet(&mut store, "World").unwrap();
}

Running this, I expected to see "Hello, World!" printed to the console, but, instead, I get absolutely nothing.

danbugs commented 5 months ago

I think there was a mismatch between the versions of jco and componentize-js. After running:

And re-running the example, I get the expected console.log! Closing the issue :)