feat: JSPI support for wasm32-unknown-emscripten - #1
Open
guybedford wants to merge 3 commits into
Open
Conversation
guybedford
force-pushed
the
emscripten-jspi
branch
4 times, most recently
from
July 18, 2026 03:34
6121ff9 to
3258304
Compare
guybedford
force-pushed
the
emscripten-target
branch
from
July 28, 2026 01:51
44ba412 to
f6527a5
Compare
Integrates the #[tokio::test] suite for wasm32-unknown-emscripten using the canonical current_thread scheduler, drivers, and task system on top of JSPI, including the native block_on drive loop. The only platform-specific code is the JSPI park, where inside a JSPI promising wrapper (entered by the #[tokio::test] expansion via the jspi crate's enter_promising) a timed park suspends the whole stack on a host timer while the host event loop runs, so that waits are real. This JSPI suspension path is guarded by an activation wrapper which is only enabled by the test suite currently. Outside an activation, or for a wait nothing could ever wake (no reactor here, and host timers are the only mid-park wake source), the leaf panics with a targeted error instead of deadlocking the host loop. spawn_blocking remains unsupported (no threads). CI runs the contract tests in two lanes: -sJSPI (waits suspend) and without (waits panic).
guybedford
force-pushed
the
emscripten-jspi
branch
from
July 28, 2026 01:53
25e78d4 to
54a7119
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Supporting the
wasm32-unknown-emscriptenplatform.Solution
This extends and is based to tokio-rs#8281, the single-threaded wasm32-unknown-emscripten target, to support JavaScript Promise Integration (JSPI)-based suspension.
Under a single-threaded build, Emscripten shares the host event loop with JavaScript, throwing on any blocking operations.
With JSPI, operations may suspend the Wasm execution on a JS promise allowing the runtime to be suspended but reentrant. For this reason, this is not like a wake, but instead multiple of these parked JSPI blocks can coexist and be woken in any order. When JSPI is enabled, and a
block_onfuture would have to suspend (a timer deadline, an external wake, or a deferred yield_now's host turn), the calling Wasm stack parks on the host loop via JSPI-specific parking and resumes on the wake.Runtime::block_on,Handle::block_on, and theblocking_*sync APIs all behave as on native. The scheduler, task system, and time driver are all core Tokio. The Emscripten-specific aspect is just the hosted event loop drive loop and the JSPI park primitive over Emscripten's promise API, along with timer/keepalive glue. The parked stacks live in an Emscripten member of the existingruntime::contextthread-local and no new public API is added.spawn_blockingremains unsupported. Sincetokio::fsand the stdio types do rely on it, the internal blocking shim completes their std calls inline, which is possible since Emscripten's filesystem syscalls are synchronous and there is nothing to offload.netis currently not included as it depends on unreleased Emscripten epoll work. When that is ready this PR can either be updated with that.This PR does not include
netfunctionality yet, as that depends on the Mio PR in tokio-rs/mio#1969. But extending this approach to full socket epolls is straightforward on top of this base as the next follow-on once the Mio PR lands.Tests run in Node.js with two modes -
The JSPI suite tests include features
rt,time,sync,macros,fs,io-util,io-std,test-utilas some emscripten-specific tests. There are only a couple of documented ignores (dup(), link() MEMFS limits, on_thread_park). - 744 passed, 0 failed, 12 ignoredThe non-JSPI tests remain limited pending deeper host event loop runtime work, a separate follow-on. - 4 passing, 0 failed.