Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

Conversation

@alexcrichton
Copy link
Contributor

I think this was lost in various translations here and there, but I'm under the impression that the intention is that this is should be async-by-default.

I think this was lost in various translations here and there, but I'm under the impression that the intention is that this is should be `async`-by-default.
@sunfishcode
Copy link
Member

Should it be? Typical main functions in most languages aren't async. Even something like tokio::main expands to a synchronous main.

@alexcrichton
Copy link
Contributor Author

Personally, I think it should be. I agree that all precedent is a synchronous main, but this won't change that. The precedent exists as there has basically never been another option. For example there's basically no other way #[tokio::main] could be implemented.

For WASI though language integration will always keep synchronous fn main working in languages that support it, but when using bindings directly I think it'd be better to reflect the default of "main is async". Programs in WASIp3 are expected to do async things immediately so when using raw bindings it avoids the need for block_on(async { ... }) for example.

@sunfishcode
Copy link
Member

sunfishcode commented Aug 27, 2025

I can see the argument that all synchronous-main languages will just override the default anyway, so we should focus on people coding to the raw bindings. In that case, how easy will it be to write a basic run implementation to the generated async bindings, in popular languages?

@alexcrichton
Copy link
Contributor Author

In Rust you'd need to compile a cdylib which is a bit of a bummer (I don't know of a way to get a bin target working). For C you'd need to compile with -mexec-model=reactor and use the custom bindings. I'm not certain for other languages myself. For Rust my plan is to use #[wasi::main] async fn main() { ... } eventually so you also wouldn't interact with bindings in an async manner by default.

The trigger for this PR was WebAssembly/wasi-testsuite#120 and feeling that the generation option of:

    async: [
        "wasi:cli/[email protected]#run",
    ],

was unnecessary. I was thinking to update the wasi crate to WASIp3 but there the command::export! was by default using sync bindings instead of async bindings

@wingo
Copy link

wingo commented Sep 2, 2025

FWIW I am able to compile components just fine as bin targets in Rust without a mention of cdylib, with that explicit impl exports::wasi::cli::run::Guest block: https://github.com/WebAssembly/wasi-testsuite/pull/120/files#diff-b6728b0f825d6665dee3a643366066d04521965ac0e34b5c5d0a6412d9847693. The resulting bins run in wasmtime with -Wcomponent-model-async=y -Sp3=y.

@alexcrichton
Copy link
Contributor Author

Indeed that works! The way that ends up working though is because the WASIp1-to-WASIp2 wasi_snapshot_preview1.command.wasm adapter automatically exports the WASIp2 "run" function. The wasmtime CLI looks for either WASIp2 or p3 for the run function, so in the example it's running a p2 entrypoint to test p3 APIs. Nothing wrong with that of course, but we'll eventually want it to all be p3-native.

@sunfishcode
Copy link
Member

I don't have a strong opinion here, and this seems to be limited to people writing to the raw bindings. So I'm inclined to make this change and see how it goes. Since no one else has objected here, let's merge this. If this causes trouble for anyone, please file issues so that we can figure out what to do.

@sunfishcode sunfishcode merged commit b330ee8 into WebAssembly:main Sep 8, 2025
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants