test(turbo-tasks): run the wasm tests with a Node wasi host
turbo-tasks wasm test binaries build but no stock runtime can start them:
Error: unknown import: `env::read_custom_section` has not been defined
turbo-tasks gathers its task registries at link time with `link-section`. wasm
has no section start/stop symbols, so the crate keeps each registry in a custom
section and expects the embedder to hand it back through that import — data the
guest cannot reach itself. wasmtime cannot inject host imports from the CLI, so
until now nothing in this crate family could be tested on wasm at all.
scripts/wasi-test-host/ is a cargo target runner that supplies it, plus WASI
preview1 (node:wasi), the imported shared memory (limits parsed out of the
binary, since JS reflection does not expose them) and `wasi.thread-spawn` over
worker_threads. It uses only Node built-ins: the CI job runs with
skipInstallBuild, so node_modules does not exist there.
Two details worth recording. Threads spawn threads directly rather than asking
the main thread to do it, because a Tokio worker spawns further workers while
the main wasm thread is usually parked in Atomics.wait and cannot run its event
loop; thread ids therefore come from one Atomics.add counter in shared memory.
And `wasi.initialize()` refuses a module exporting `_start`, so a spawned thread
hides that export to get the WASI binding and then calls `wasi_thread_start`.
`read_custom_section` implements the full two-phase protocol rather than
returning 0, which would leave the registries empty; `registries_are_populated`
guards that from the Rust side.
Tests that cannot work on wasm are marked ignored with the reason, so they show
as `ignored, <reason>` instead of disappearing, and only on wasm — native still
runs the full set. The three causes are all real platform limits: wasm has no
unwinding, so `#[should_panic]` and `catch_unwind` cannot work; the pinned
parking_lot cannot block on wasm, so contended locks panic; and WASI preview1
has no temp directory. The parking_lot fix is a separate change.
criterion moves to a non-wasm dev-dependency for turbo-tasks-backend for the
same reason as turbo-tasks: it is benchmark-only but pulls in rayon, which
refuses to compile for wasi, and cargo resolves dev-dependencies even for
`cargo test --lib`.
Co-authored-by: Luke Sandberg <210140+lukesandberg@users.noreply.github.com>
Co-authored-by: Tobias Koppers <1365881+sokra@users.noreply.github.com>
Because this layer starts running the suites while `parking_lot_core` is
still 0.9.8 — whose wasm parker is a stub that panics
("Parking not supported on this platform", `thread_parker/wasm.rs:26`) —
16 of the 17 `scope_unbounded` tests cannot pass here. wasm is
`panic = abort`, so one of them aborts the whole process rather than
failing a single test. They are ignored with the same
`parking_lot cannot block on wasm` reason already used by the other
lock-contending tests at this layer, so the set stays uniform and
greppable.
Each of the 16 was run individually to confirm it panics in the parker;
`test_unbounded_current_thread_direct_call_completes` passes and is
deliberately left enabled rather than ignored for symmetry.
These 16 ignores are temporary: the next layer replaces the parker and
removes them again (12 become enabled, 3 become `no unwinding on wasm`,
1 becomes the runtime-teardown reason). The churn is deliberate — it is
what lets this layer pass its own CI instead of depending on a fix that
lands later in the stack.