Add wasm32/web browser support to the Rust SDK#4319
Add wasm32/web browser support to the Rust SDK#4319drdozer wants to merge 20 commits intoclockworklabs:masterfrom
Conversation
- `DbConnectionBuilder::build` becomes async without tokio's block_in_place. Still need to add `web` feature flag.
Renamed the `run_threaded` method on `wasm32` to better reflect its behavior of spawning a background task. The generated `DbConnection` methods `run_threaded`, `run_background`, and `advance_one_message_blocking` now include runtime panics with a clear error feedback when called on unsupported targets.
Trim down repetitive `cfg` clauses by extracting common lock patterns into `get_lock_[sync|async]`.
Moves the creation of DbContextImplInner and DbContextImpl into private helper functions (`build_db_ctx_inner` and `build_db_ctx`) to reduce duplication between the web and non-web implementations of `build_impl`.
- Update websocket API references: ServerMessage<BsatnFormat> -> ws::v2::ServerMessage, ClientMessage<Bytes> -> ws::v2::ClientMessage, BIN_PROTOCOL -> ws::v2::BIN_PROTOCOL - Rename module_name -> database_name in wasm32 build_impl - Remove call_reducer_flags field (removed upstream) - Remove unused HashMap import - Gate sql-parser size assertions to 64-bit targets (struct sizes differ on wasm32 due to pointer width) - Update codegen snapshot
|
In the interests of full transparency, I told the Zed coding agent that I wanted the outstanding wasm32 PR fixed. I have not yet done a proper review of exactly what it tinkered with, but will do so once we've got an idea of how far it gets through the CI. |
|
@drdozer sry but what is the motivation behind this? is my branch broken? what did you add to this? if you didnt even test it what makes this better than the version i opened? The pr is currently blocked on ci changes so this one will also not get merged till they get the ci working :) |
I had misunderstood then -- the pull didn't seem to be getting any updates and was collecting conflicts, so I had assumed it was functionally abandoned. Who is blocking it getting merged in then? And why/how? |
|
They first wanna get this tested in ci and then merge the pr. bfops already tried but likely couldnt get it done before 2.0 since they are trying to get it out the door currently. Id suggest waiting before 2.0 breaking changes are out the door and then rersolving the merge conflicts. |
Overview
This PR adds web browser (wasm32) support to the SpacetimeDB Rust SDK behind an opt-in
webCargo feature flag. When enabled, the SDK can be compiled to WebAssembly and run in a browser environment, using browser-native APIs for WebSockets, storage, and async task spawning — all while keeping the existing native (tokio-based) code path completely unchanged when the feature is not enabled.This is a rebased and updated continuation of #2704 by @thlsrms, with further work by @kistz on their rust-web-sdk-updated branch.
Motivation
The Rust SDK currently assumes a native runtime (tokio, file I/O, threads). This prevents Rust-to-WASM web applications (e.g. via
wasm-bindgen/wasm-pack) from using the SDK. This PR bridges that gap, allowing the samespacetimedb-sdkcrate to target both native and web platforms.Changes
New
webfeature flag (sdks/rust/Cargo.toml)webfeature that gates all browser-specific dependenciesgloo-console,gloo-net,gloo-storage,gloo-utils,js-sys,web-sys,wasm-bindgen,wasm-bindgen-futures,tokio-tungstenite-wasm,getrandom(withwasm_js)home,tokio, andtokio-tungsteniteunder[target.'cfg(not(target_arch = "wasm32"))'.dependencies]Credentials (
sdks/rust/src/credentials.rs)homecratecredentials::cookies::Cookie) with a builder pattern for get/set/delete, plus re-exports ofgloo_storage::{LocalStorage, SessionStorage, Storage}for web-standard storageWebSocket connection (
sdks/rust/src/websocket.rs)tokio-tungsteniteconnection with HTTP upgrade headerstokio-tungstenite-wasmfor the browser WebSocket APIfetch_ws_token()— an HTTP POST to/v1/identity/websocket-tokento exchange a bearer token for a short-lived WebSocket token (since browsers cannot set custom headers on WebSocket handshakes)spawn_message_loopusingwasm_bindgen_futures::spawn_localwithfutures::select!for concurrent inbound/outbound message handlingDbConnection (
sdks/rust/src/db_connection.rs)SharedAsyncCell<T>—TokioMutexon native,StdMutexon webget_lock_sync/get_lock_asyncabstract over the two mutex typesDbConnectionBuilder::build()becomesasyncon web (native remains synchronous)build_db_ctx_inner()andbuild_db_ctx()helper functions to reduce duplication between native and webbuild_implrun_threaded/advance_one_message_blockingare#[cfg(not(feature = "web"))]run_background_taskmethod on web: spawns awasm_bindgen_futures::spawn_localloop callingadvance_one_message_asyncfutures::select!instead oftokio::select!on the web pathCodegen (
crates/codegen/src/rust.rs)DbConnectiontype conditionally exposesrun_threaded+advance_one_message_blocking(native) orrun_background_task(wasm32)SQL parser fix (
crates/sql-parser/src/parser/mod.rs)size_ofcompile-time assertions to#[cfg(target_pointer_width = "64")], since struct sizes differ on wasm32 due to pointer widthDesign Decisions
webfeature must be explicitly opted into, rather than activating automatically ontarget_arch = "wasm32". This keeps the default build unaffected and avoids issues in non-browser wasm contexts.wasm-bindgen-futuresandfutures::select!instead.Testing
cargo build --target wasm32-unknown-unknown --features web -p spacetimedb-sdkCredits
Built on earlier exploration by @kistz and @thlsrms (see #2704). Developed with Zed Coding Agent (Claude Opus 4.6).