Skip to content

feat(web-async): add portable time module - #38

Merged
kixelated merged 1 commit into
mainfrom
web-async-time
Jun 9, 2026
Merged

feat(web-async): add portable time module#38
kixelated merged 1 commit into
mainfrom
web-async-time

Conversation

@kixelated

Copy link
Copy Markdown
Owner

Adds web_async::time so code can use timers and Instant on both native and the browser, the same way web_async::spawn already abstracts task spawning.

Why

tokio::time does not work on wasm32-unknown-unknown:

  • tokio's clock is std::time::Instant::now(), which panics on wasm (no clock).
  • tokio's timers need a runtime time driver, which wasm_bindgen_futures::spawn_local (what web_async::spawn uses on wasm) does not provide.

So any crate that sleeps, ticks on an interval, or reads an Instant currently can't compile-and-run on both targets. This came up making moq-net run in the browser, but it's the same problem for anything in this ecosystem.

What

time.rs is a thin cfg-switched re-export mirroring tokio::time 1:1:

  • native / wasi: tokio::time::{Instant, Sleep, Interval, Timeout, MissedTickBehavior, sleep, sleep_until, interval, interval_at, timeout, timeout_at}
  • browser wasm: the same names from wasmtimer, which implements that API on performance.now() + setTimeout, plus wasmtimer::std::Instant.
  • Duration re-exported for convenience.

Callers swap tokio::time for web_async::time and the same code runs on both.

Notes:

  • wasmtimer is under [target.'cfg(target_arch = "wasm32")'.dependencies], so native builds never pull it. Native just gains tokio's time feature.
  • The cfg split (wasi grouped with native) matches spawn.rs.
  • The mockable test clock (tokio::time::pause/advance) is intentionally not re-exported: it lives behind tokio's test-util feature, which shouldn't leak into normal builds, and only runs in native tests.

Test

  • cargo fmt --check, cargo clippy -- -D warnings clean (native).
  • Builds for both host and wasm32-unknown-unknown.

🤖 Generated with Claude Code

Add `web_async::time`, a thin cfg-switched re-export of the tokio::time
surface (sleep, sleep_until, interval, interval_at, timeout, timeout_at,
Sleep, Interval, Timeout, MissedTickBehavior, Instant) plus Duration.

Native (and wasi) re-export tokio::time directly. Browser wasm routes
through wasmtimer, which implements the same API on performance.now() +
setTimeout. tokio's own clock is std::time::Instant::now(), which panics
on wasm32 (no clock), and its timers need a runtime time driver that
spawn_local doesn't provide, so tokio::time can't be used there directly.

This is the sibling of the existing spawn split: code can use
web_async::time in place of tokio::time and run unchanged on both targets.
wasmtimer is a wasm-only dependency, so native builds are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kixelated
kixelated merged commit fa8b513 into main Jun 9, 2026
1 check failed
@kixelated
kixelated deleted the web-async-time branch June 9, 2026 22:05
@github-actions github-actions Bot mentioned this pull request Jun 9, 2026
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.

1 participant