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

Unable to run JS wasm compiled by jco #26

Open
logaan opened this issue Sep 17, 2024 · 2 comments
Open

Unable to run JS wasm compiled by jco #26

logaan opened this issue Sep 17, 2024 · 2 comments

Comments

@logaan
Copy link

logaan commented Sep 17, 2024

I'm having some difficulty running js code compiled to wasm using jco in wepl. I've tried to boil this down to a minimal example.

repltest.js

export function test() {
    return "ok";
}

repltest.wit

package local:repltest;

world repltest {
  export test: func() -> string;
}

make-test

#!/usr/bin/env bash

npx jco componentize repltest.js --wit repltest.wit -o repltest.wasm

wepl repltest.wasm

When I run make-test it appears to correctly create a wasm file. The imports include a bunch of wasi interfaces. The exports are the one function that we expect to see. Unfortunately calling that function complains of an unimplemented import:

./make-test 
OK Successfully written repltest.wasm.
World: root:component/root
> .imports
wasi:io/[email protected]: {
    [method]pollable.block: func(self: handle<...>)
    poll: func(in: list<handle<...>>) -> list<u32>
}
wasi:io/[email protected]: {
    [method]input-stream.read: func(self: handle<...>, len: u64) -> result<list<u8>, stream-error>
    [method]input-stream.subscribe: func(self: handle<...>) -> handle<...>
    [method]output-stream.check-write: func(self: handle<...>) -> result<u64, stream-error>
    [method]output-stream.write: func(self: handle<...>, contents: list<u8>) -> result<_, stream-error>
    [method]output-stream.blocking-write-and-flush: func(self: handle<...>, contents: list<u8>) -> result<_, stream-error>
    [method]output-stream.blocking-flush: func(self: handle<...>) -> result<_, stream-error>
    [method]output-stream.subscribe: func(self: handle<...>) -> handle<...>
}
wasi:cli/[email protected]: {
    get-stdin: func() -> handle<...>
}
wasi:cli/[email protected]: {
    get-stdout: func() -> handle<...>
}
wasi:cli/[email protected]: {
    get-stderr: func() -> handle<...>
}
wasi:cli/[email protected]: {
    get-terminal-stdin: func() -> option<handle<...>>
}
wasi:cli/[email protected]: {
    get-terminal-stdout: func() -> option<handle<...>>
}
wasi:cli/[email protected]: {
    get-terminal-stderr: func() -> option<handle<...>>
}
wasi:clocks/[email protected]: {
    now: func() -> u64
    resolution: func() -> u64
    subscribe-instant: func(when: u64) -> handle<...>
}
wasi:clocks/[email protected]: {
    now: func() -> datetime
    resolution: func() -> datetime
}
wasi:filesystem/[email protected]: {
    [method]descriptor.write-via-stream: func(self: handle<...>, offset: u64) -> result<handle<...>, error-code>
    [method]descriptor.append-via-stream: func(self: handle<...>) -> result<handle<...>, error-code>
    [method]descriptor.get-flags: func(self: handle<...>) -> result<flags<...>, error-code>
    [method]descriptor.get-type: func(self: handle<...>) -> result<descriptor-type, error-code>
    [method]descriptor.stat: func(self: handle<...>) -> result<descriptor-stat, error-code>
    filesystem-error-code: func(err: handle<...>) -> option<error-code>
}
wasi:filesystem/[email protected]: {
    get-directories: func() -> list<tuple<handle<...>, string>>
}
wasi:random/[email protected]: {
    get-random-bytes: func(len: u64) -> list<u8>
    get-random-u64: func() -> u64
}
wasi:http/[email protected]: {
    [constructor]fields: func() -> handle<...>
    [static]fields.from-list: func(entries: list<tuple<string, list<u8>>>) -> result<handle<...>, header-error>
    [method]fields.get: func(self: handle<...>, name: string) -> list<list<u8>>
    [method]fields.has: func(self: handle<...>, name: string) -> bool
    [method]fields.set: func(self: handle<...>, name: string, value: list<list<u8>>) -> result<_, header-error>
    [method]fields.delete: func(self: handle<...>, name: string) -> result<_, header-error>
    [method]fields.append: func(self: handle<...>, name: string, value: list<u8>) -> result<_, header-error>
    [method]fields.entries: func(self: handle<...>) -> list<tuple<string, list<u8>>>
    [method]fields.clone: func(self: handle<...>) -> handle<...>
    [method]incoming-request.method: func(self: handle<...>) -> method
    [method]incoming-request.path-with-query: func(self: handle<...>) -> option<string>
    [method]incoming-request.scheme: func(self: handle<...>) -> option<scheme>
    [method]incoming-request.authority: func(self: handle<...>) -> option<string>
    [method]incoming-request.headers: func(self: handle<...>) -> handle<...>
    [method]incoming-request.consume: func(self: handle<...>) -> result<handle<...>>
    [constructor]outgoing-request: func(headers: handle<...>) -> handle<...>
    [method]outgoing-request.body: func(self: handle<...>) -> result<handle<...>>
    [method]outgoing-request.set-method: func(self: handle<...>, method: method) -> result
    [method]outgoing-request.set-path-with-query: func(self: handle<...>, path-with-query: option<string>) -> result
    [method]outgoing-request.set-scheme: func(self: handle<...>, scheme: option<scheme>) -> result
    [method]outgoing-request.set-authority: func(self: handle<...>, authority: option<string>) -> result
    [method]outgoing-request.headers: func(self: handle<...>) -> handle<...>
    [static]response-outparam.set: func(param: handle<...>, response: result<handle<...>, error-code>)
    [method]incoming-response.status: func(self: handle<...>) -> u16
    [method]incoming-response.headers: func(self: handle<...>) -> handle<...>
    [method]incoming-response.consume: func(self: handle<...>) -> result<handle<...>>
    [method]incoming-body.stream: func(self: handle<...>) -> result<handle<...>>
    [constructor]outgoing-response: func(headers: handle<...>) -> handle<...>
    [method]outgoing-response.set-status-code: func(self: handle<...>, status-code: u16) -> result
    [method]outgoing-response.headers: func(self: handle<...>) -> handle<...>
    [method]outgoing-response.body: func(self: handle<...>) -> result<handle<...>>
    [method]outgoing-body.write: func(self: handle<...>) -> result<handle<...>>
    [static]outgoing-body.finish: func(this: handle<...>, trailers: option<handle<...>>) -> result<_, error-code>
    [method]future-incoming-response.subscribe: func(self: handle<...>) -> handle<...>
    [method]future-incoming-response.get: func(self: handle<...>) -> option<result<result<handle<...>, error-code>>>
}
wasi:http/[email protected]: {
    handle: func(request: handle<...>, options: option<handle<...>>) -> result<handle<...>, error-code>
}
> .exports
test: func() -> string
> test()
Error: unimplemented import: wasi:clocks/[email protected]
Error: error while executing at wasm backtrace:
    0: 0xa31d91 - wit-component:adapter:wasi_snapshot_preview1!clock_time_get
    1: 0xa34ea3 - wit-component:shim!adapt-wasi_snapshot_preview1-clock_time_get
    2: 0x7a8ed0 - <unknown>!<wasm function 12274>
    3: 0x77d826 - <unknown>!<wasm function 9154>
    4: 0x79a0d3 - <unknown>!<wasm function 10706>
    5: 0x343c1f - <unknown>!<wasm function 481>
    6: 0x353b8e - <unknown>!<wasm function 505>
    7: 0x6aecaf - <unknown>!<wasm function 4783>
    8: 0x51bb5d - <unknown>!<wasm function 1762>
    9: 0x3348d8 - <unknown>!<wasm function 460>
   10: 0x7a9dcf - <unknown>!test
> 

I reached out to @rylev on the Bytecode Alliance Zulip and was expecting to be told that I needed to use the .link or .compose commands to satisfy the repltest.wasm imports. I haven't been able to find any examples of how to use .link or .compose, and wasn't able to figure it out from reading the wepl source.

@logaan
Copy link
Author

logaan commented Sep 17, 2024

It might also be worth mentioning that I tried using WASI-Virt. With that I was able to create a wasm file with no imports. But I think the code was still calling clock_time_get and so I would see a different error, one coming from virt because it wasn't expecting to be called.

@cataggar
Copy link

See #27. I think the Wasmtime being used needs to be updated to support WASI 0.2.0. This project is on Wasmtime 22 which supports WASI 0.1.0 according to Copilot. Wasmtime 23 & 24 support WASI 0.2.0. The recent released Wasmtime 25 supports WASI 0.2.1.

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

No branches or pull requests

2 participants