fix(turbo-tasks): compile EventListener::wait on wasm (#97853)
> Replaces #97579, which was **not merged**. Reordering this stack
briefly left that PR
> pointing at a base branch that had come to contain its own head
commit, so GitHub closed it
> as merged and deleted its branch. Nothing from it reached `canary`. It
had been approved;
> this PR is the same commit (`1d868fd710`), restored, and needs review
again. Sorry for the churn.
### What?
Gives `turbo_tasks::EventListener::wait` a working blocking
implementation on wasm targets, instead
of failing to compile there.
Also moves `criterion` to a non-wasm dev-dependency, which is what makes
`cargo test -p turbo-tasks --lib --target wasm32-wasip1-threads`
buildable at all — see *How?*.
### Why?
`event-listener` gates its blocking `wait()` / `wait_timeout()` /
`wait_deadline()` behind
`#[cfg(all(feature = "std", not(target_family = "wasm")))]`, so they are
unavailable on **every**
wasm target — even `wasm32-wasip1-threads`, which has real threads that
can park. That made
`EventListener::wait` fail to compile.
This is load-bearing rather than a corner case: `wait()` backs the
priority runner's task barriers
(six call sites in
`turbopack/crates/turbo-tasks/src/priority_runner.rs`) and
`turbopack/crates/turbo-tasks/src/scope.rs`. Anything that merely
compiled while `wait()` was
unusable would be hollow.
### How?
`event-listener`'s own native implementation (`wait_internal` →
`wait_with_parker`) is just "register
an unparker as the listener's task, then `Parker::park()` in a loop".
`EventListener` already
implements `Future`, so on wasm the same thing is expressed one level
up:
```rust
fn block_on_listener(listener: event_listener::EventListener) {
#[cfg(not(target_family = "wasm"))]
{ use event_listener::Listener as _; listener.wait(); }
#[cfg(target_family = "wasm")]
futures::executor::block_on(listener);
}
```
`futures` is already a dependency of this crate, `executor` is one of
its default features, and
`futures-executor` is already in the wasm dependency graph, so nothing
new is pulled in. Native
targets keep calling `event-listener` directly, so their behaviour and
fast path are untouched.
Both `wait()` implementations — the default one and the
`hanging_detection` one — route through that
single helper, so the two cannot drift apart and the target `cfg` exists
in exactly one place.
**Verification.** A new test registers a listener, spawns a thread that
sleeps before notifying, then
waits — so the listener parks first and the parking path is exercised
rather than the
already-notified fast path. It asserts both that the notifier ran *and*
that time actually elapsed,
so a `wait()` that returned early fails instead of silently passing.
It passes natively, and the wasm code path was executed under wasmtime
with real wasi threads on
`wasm32-wasip1-threads`: the waiter blocked **300.9 ms** against a 300
ms notifier delay and was
woken by the other thread. As a control, a deliberately non-blocking
variant returns in ~1 µs and
fails the assertions.
Two notes on the surrounding tooling:
- `criterion` is used only by the `[[bench]]` targets, but it pulls in
`rayon`, which refuses to
compile for wasi, and cargo resolves dev-dependencies even for `cargo
test --lib`. Gating it to
non-wasm targets is semantically right (the benchmarks don't run on
wasm) and unblocks wasm test
binaries for this crate generally. Native benchmarks are unaffected.
- The test binary now *builds* for wasm but cannot be instantiated by a
plain runtime, because
`turbo-tasks` imports `env.read_custom_section` for its link-time task
registries and no CLI
runtime provides it. That hook is tracked separately; until it exists,
the runtime evidence above
comes from a standalone binary that copies the helper's wasm body
verbatim against the same
`event-listener` and `futures` versions.
<!-- NEXT_JS_LLM -->
<!-- fleet b6d0486f-97c7-42a7-bdaf-3490774cdec3 -->
Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>