Skip to content

Unable to run JS wasm compiled by jco #26

@logaan

Description

@logaan

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions