Skip to content

typespec_client_core: New web_runtime to support wasm32-unknown-unknown #2770

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

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

magodo
Copy link

@magodo magodo commented Jul 8, 2025

The typespec_client_core::sleep::sleep is using the async_runtime's sleep implementation, which is complicated to support wasm32, and will panic now when targeting to wasm32. Instead of make the standard_runtime to support wasm32 sleep (I wonder if it's feasible), we can instead just introduce another sleep implementation to simply use the gloo_timers::future::sleep.

Also, this PR adds a cfg_attr for conditionally remove the Send trait from the async_trait for the RetryPolicy, as the other parts of the code do.

Additionally, the getrandom crate will enable wasm_js features when targetting to wasm, which is necessary.

Fix #2754

magodo added 2 commits July 8, 2025 14:03
…` when target wasm

The `typespec_client_core::sleep::sleep` is using the async_runtime's sleep implementation, which is complicated to support `wasm32`, and will panic now when targeting to `wasm32`. Instead of make the `standard_runtime` to support wasm32 sleep (I wonder if it's feasible), we can instead just introduce another `sleep` implementation to simply use the `gloo_timers::future::sleep`.

Also, this PR adds a `cfg_attr` for conditionally remove the `Send` trait from the `async_trait` for the `RetryPolicy`, as the other parts of the code do.

Additionally, the `getrandom` crate will enable `wasm_js` features when targetting to `wasm`, which is necessary.
@Copilot Copilot AI review requested due to automatic review settings July 8, 2025 04:11
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a WebAssembly-compatible sleep implementation using gloo_timers, adjusts async_trait attributes for WASM targets, and updates dependency declarations.

  • Introduce a wasm-only sleep using gloo_timers::future::sleep
  • Add cfg_attr macros to toggle async_trait for RetryPolicy on wasm32
  • Update Cargo.toml files to include gloo-timers and necessary features

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

File Description
sdk/typespec/typespec_client_core/src/sleep.rs Split sleep into non-WASM and WASM variants using cfgs
sdk/typespec/typespec_client_core/src/http/policies/retry/mod.rs Apply cfg_attr to async_trait for WASM vs non-WASM targets
sdk/typespec/typespec_client_core/Cargo.toml Add gloo-timers to WASM target dependencies
Cargo.toml Declare gloo-timers with the futures feature at workspace root
Comments suppressed due to low confidence (1)

sdk/typespec/typespec_client_core/src/sleep.rs:36

  • The WASM variant of sleep is missing a doc comment; consider adding one to explain its behavior and any conversion caveats.
pub async fn sleep(duration: Duration) {

@magodo magodo changed the title typespec_client_core: Use gloo_timers::future::sleep to impl sleep when target wasm typespec_client_core: New web_runtime to support wasm32 Jul 9, 2025
@magodo magodo changed the title typespec_client_core: New web_runtime to support wasm32 typespec_client_core: New web_runtime to support wasm32-unknown-unknown Jul 9, 2025
heaths
heaths previously requested changes Jul 9, 2025
Copy link
Member

@heaths heaths left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better, but a couple lingering changes.

@@ -150,7 +150,7 @@ impl AsyncRuntime for StdRuntime {
/// Uses a simple thread based implementation for sleep. A more efficient
/// implementation is available by using the `tokio` crate feature.
#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems this line is no longer needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to do #2770 (comment), this is still needed to allow a user to select the StdRuntime even target to wasm32.

@@ -189,12 +192,16 @@ pub fn set_async_runtime(runtime: Arc<dyn AsyncRuntime>) -> crate::Result<()> {
}

fn create_async_runtime() -> Arc<dyn AsyncRuntime> {
#[cfg(not(feature = "tokio"))]
#[cfg(target_arch = "wasm32")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better, but IMHO this should probably be tied to a specific feature which is the gloo runtime, unless you can assert safely that gloo is the runtime of choice for all wasm developers (I'm not familiar enough with wasm development to have an opinion here).

This is similar to how we've tied the tokio runtime to the tokio feature - because the tokio runtime is not a globally accepted async runtime, we hide its implementation behind a feature.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LarryOsterman The gloo-timers is provided by https://github.com/rustwasm, which is built on top of wasm-bindgen and js-sys, providing a more user friendly API. So if we really want to introduce a feature, then I'd prpose to name it "wasm-bindgen(as thespawnis based onwasm-bindgen-futures, and the sleepis based ongloo-timers, which in turn based on wasm-bindgen`).

Whilst, I believe even we use the target for this create_async_runtime(), it only means we provide a default runtime for the users. They are still able to call set_async_runtime() to choose the runtime of their choice. Otherwise, if we do:

    #[cfg(feature = "wasm-bindgen")]
    {
        Arc::new(web_runtime::WasmBindgenRuntime) as Arc<dyn AsyncRuntime>
    }
    #[cfg(feature = "tokio")]
    {
        Arc::new(tokio_runtime::TokioRuntime) as Arc<dyn AsyncRuntime>
    }
    #[cfg(not(any(feature = "tokio", feature = "wasm-bindgen")))]
    {
        Arc::new(standard_runtime::StdRuntime)
    }

For users who target to wasm32-unknown-unknown, without specifying the wasm-bindgen feature, then they'll get a StdRuntime by default, which will only panic in any case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can totally get behind a wasm-bindgen feature name.

Thank you for your patience here :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LarryOsterman Sure, I've pushed a new commit to introduce that feature name, made the wasm dependencies optional, and only bring them by this new feature.

@heaths heaths dismissed their stale review July 10, 2025 17:02

Going on holiday

@magodo
Copy link
Author

magodo commented Jul 22, 2025

Kindly ping @LarryOsterman

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

Successfully merging this pull request may close these issues.

wasm32-unknown-unknown failed to run
3 participants