Stream: wit-bindgen

Topic: TS / AseemblyScript guest language support


view this post on Zulip Karel Hrkal (kajacx) (Jun 01 2023 at 19:53):

Hello. I wanted to ask if TypeScript (well, AssemblyScript) has WIT bindgen support on the plugin (guest) side, when I want to compile my TS code into a WASM module and use WIT bindgen to communicate with the host.

I could work on a pull request if need be.

view this post on Zulip Lann Martin (Jun 01 2023 at 20:22):

At this point the path of least resistance for running TypeScript is probably to compile to JavaScript and use https://github.com/bytecodealliance/jco componentize to generate a component.

JavaScript tooling for working with WebAssembly Components - GitHub - bytecodealliance/jco: JavaScript tooling for working with WebAssembly Components

view this post on Zulip Ralph (Jun 02 2023 at 10:07):

My expectation is that this will become rapidly easier over the summer. I note someone just posted https://betterprogramming.pub/share-rust-types-with-typescript-for-webassembly-a91381e00b4c

Discover the most seamless developer experience with Rust and WebAssembly. This is the fastest way to auto-generate TypeScript definitions…

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:08):

Thanks @Lann Martin , I have followed this tutorial: https://github.com/bytecodealliance/componentize-js/blob/main/EXAMPLE.md and on one hand, it works, but on the other hand, it has a big problem.

The "componentize" JS script does absolutely no checking on whether the functions defined in the .wit file are acutally implemented in the JS file. It just hapilly creates the WASM file. When I later call the exported function, I get a runtime error.

This is horrible. Can I generate a typescript definition from the wai file? Just to be clear, there is a typescript types file describing the build module and how to use it, but I see no types file for when you are writing the modules - which functions you need to implement to meet the wai definition.

Contribute to bytecodealliance/componentize-js development by creating an account on GitHub.

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:11):

@Ralph Thanks, but that's for wasm_bindgen. That's not what I want, I am looking for a way to implement a wit format in TypeScript (or Assembly Script) and compile that to a wit-compatible WASM module.

view this post on Zulip Ralph (Jun 02 2023 at 10:14):

you should discuss componentize-js and jco with @Guy Bedford who can answer your questions more directly I think..... are you expecting an implementation of the component to be generated? Do I understand you correctly?

view this post on Zulip Ralph (Jun 02 2023 at 10:15):

as it is, there are experiments all around looking at TS-->JS-->components ongoing, I know that....

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:17):

are you expecting an implementation of the component to be generated? The TS types for the implementation, yes. For example, if the protocol specifies a method "hello_abc(): string", I am expecting a TS type definition that would require me for implement this method with that signature. An interface would probably be a best fit.

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:18):

For example, when using wit bindgen for TS host, I get an interface for the imported method that I need to implement with correct TS types.

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:22):

Example: protocol-host.wai:
add-one-to-all: func(numbers: list<u8>) -> list<u8>

Running command:
wasmer run wasmer/wai-bindgen-cli --dir . -- js --export ./protocol-host.wai

Generates:
export function addProtocolHostToImports(imports: any, obj: ProtocolHost, get_export: (name: string) => WebAssembly.ExportValue): void;
export interface ProtocolHost {
addOneToAll(numbers: Uint8Array): Uint8Array;
}

So I get the interface I need to implement, and the method to "plug" the imports into the runtime. I am looking for the same thing, but for the plugin (guest).

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 10:31):

Of course, for the guest, there would only be the interface to implement. But the tutorial I followed generated no such TS types for the guest implementation.

view this post on Zulip Lann Martin (Jun 02 2023 at 12:24):

I would open an issue at https://github.com/bytecodealliance/jco/issues; if TS guest type gen isn't already done/planned I'm sure it would be an appreciated contribution

JavaScript tooling for working with WebAssembly Components - Issues · bytecodealliance/jco

view this post on Zulip Guy Bedford (Jun 02 2023 at 15:01):

jco automatically generates typescript types, yes, they're in the output folder of transpilation

view this post on Zulip Lann Martin (Jun 02 2023 at 15:27):

So to generate guest TS defs it looks like you have to componentize, then transpile that generated component? Seems to work for me for a simple example; maybe that could be streamlined as a jco bindgen <wit> -o types/ to simplify the guest-only workflow?

view this post on Zulip Joel Dice (Jun 02 2023 at 15:29):

For example, componentize-py has a bindings subcommand for just generating guest bindings and nothing else.

view this post on Zulip Karel Hrkal (kajacx) (Jun 02 2023 at 19:59):

From what I remember, the TS type bindings for a TS guest do generate, but only on the consuming side for a TS host.

For example, you get a type definition on what the module will provide and what methods you can call on it, but I didn't see any type definition for me to fulfill when I was writing the plug-in code in TypeScript.

I will provide more details when I get to a computer tomorrow.

view this post on Zulip Lann Martin (Jun 02 2023 at 20:42):

$ cd jco/test/fixtures/componentize
$ cat source.wit
default world test {
  export hello: func() -> string
}
$ npx jco componentize source.js -w source.wit -o component.wasm
...
$ npx jco transpile component.wasm -o types
...
$ cat types/component.d.ts
...
import { Preopens as PreopensImports } from './imports/preopens';
import { Exit as ExitImports } from './imports/exit';
export function hello(): string;

view this post on Zulip Lann Martin (Jun 02 2023 at 20:50):

That seems like the right sort of thing, but I guess my Typescript is pretty rusty; I'm not sure if that can be usefully adapted for guest type checking

view this post on Zulip Karel Hrkal (kajacx) (Jun 03 2023 at 12:43):

Yes, I was using the "componentize" command followed by "transpile", like in your example @Lann Martin. But the resulting file isn't exactly what I need. The export function hello(): string; line is better than nothing, but it would require some wild regexes to turn in into an interface. And also there is the issue of properly exporting the methods from the interface implementation.

Again, I am comparing it to how wai bindgen works in Rust, but the current solution (manage type signatures manually with no compile error and absolutely no build error, only a runtime error after you actually try to run your module) is just horrible.

I can try and work on a PR perhaps, but currently I have other tasks to do before focusing on supporting more guest languages.

view this post on Zulip Guy Bedford (Jun 04 2023 at 01:39):

@Karel Hrkal thanks for the suggestions, I've created https://github.com/bytecodealliance/componentize-js/issues/30 to track improving the experience here, hoping to get some updates to that soon

In the recent bindgen updates, import checks at Wizer time were removed, these should be added back. In addition we should extend these checks to the exports shape as well. Relatively simple work, ...

Last updated: Dec 23 2024 at 13:07 UTC