Skip to content

Add wasm32 support to the rust sdk#2704

Closed
thlsrms wants to merge 20 commits intoclockworklabs:masterfrom
thlsrms:rust-web-sdk
Closed

Add wasm32 support to the rust sdk#2704
thlsrms wants to merge 20 commits intoclockworklabs:masterfrom
thlsrms:rust-web-sdk

Conversation

@thlsrms
Copy link

@thlsrms thlsrms commented May 5, 2025

Description of Changes

Enabled the Rust SDK wasm32 compilation target for web usage.

  • Added web feature flag, incompatible with non-wasm32 targets.
  • Replaced unmaintained anymap crate with anymap3.

API and ABI breaking changes

None. Most changes apply only to the wasm32 target, so there are no global breaking changes. The main differences to the native targets are:

  • DBConnectionBuilder::build is now async on the web.
  • DbConnection's run_threaded and advance_one_message_blocking unavailable for the wasm32 target.
  • Added DbConnection::run_background_task as replacement for run_threaded on the web.
  • Authorization token is sent as a query parameter instead of in a header, due to browser limitation.
  • Credentials handling:
    • File struct unavailable on the web.
    • Two browser-friendly options are provided:
      • The re-exported API from gloo_storage for local/session storage.
      • A Cookie builder to manage cookies (except HttpOnly cookies).

Expected complexity level and risk

Estimated at 2:

  • Most work involves adjusting dependencies and feature flags.
  • Non-blocking alternatives replace a few native SDK code paths.

Testing

I built 2 demos to exercise the changes:

  1. Bevy https://github.com/thlsrms/tictactoe-stdb-bevy
  2. Leptos https://github.com/thlsrms/stdb-leptos-quickstart

Note: No automated tests have been written yet.

@CLAassistant
Copy link

CLAassistant commented May 5, 2025

CLA assistant check
All committers have signed the CLA.

@bfops
Copy link
Collaborator

bfops commented May 27, 2025

@thlsrms Thank you for opening this! What's the current status? Are there parts still in progress, or should we be getting a reviewer on this?

@thlsrms
Copy link
Author

thlsrms commented May 27, 2025

@thlsrms Thank you for opening this! What's the current status? Are there parts still in progress, or should we be getting a reviewer on this?

I've been working on support for the wasm32-unknown-emscripten target on this branch: https://github.com/thlsrms/SpacetimeDB/blob/rust-emscripten-sdk/crates/sdk/src/emscripten.rs, with the intention of including it in this PR. While it's functional on Chromium, Firefox requires further effort.

To keep this PR focused, I'll defer the emscripten support to a separate PR if necessary.

I'll make some minor adjustments and rebase onto master. I'll ping you tomorrow if that's alright.

@bfops
Copy link
Collaborator

bfops commented May 27, 2025

@thlsrms absolutely, thank you!

and no rush. I'm going to be out of office Wed-Fri this week, but either way it might take a little while for us to get around to reviewing, since we have some other things in progress right now.

@thlsrms thlsrms marked this pull request as ready for review May 28, 2025 21:29
@thlsrms
Copy link
Author

thlsrms commented May 28, 2025

@bfops When you're available, feel free to assign a reviewer. 👍

@geoffreygarrett
Copy link

+1

@enaut
Copy link

enaut commented Jun 21, 2025

In case it helps someone: I created a proof of concept integration of spacetime into Dioxus - it works™, however it does not feel very native as the interaction with the signals Dioxus uses for its state tracking does not seem very good yet (https://github.com/enaut/kommunikationszentrum/blob/7d04e04c4fede15101f995bec74e1b23adf7d68d/admin/src/main.rs). It might also be that I know neither spacetime nor Dioxus too well, so I might just have not found the clean solution. Nonetheless, I wanted to share that this PR works for Dioxus too. I did not test the updated spacetime generate as I just applied the changes manually.

@liamaharon
Copy link

Thanks so much @thlsrms for your work here! Your branch got a little stale, I had a go merging master into it, if you are interested in cherry-picking: master...liamaharon:SpacetimeDB:rust-web-sdk-updated

It compiles to wasm and native, but I have not yet tested it thoroughly.

@bfops how are priorities looking on your end? It would be great if this could eventually be merged.

@thlsrms
Copy link
Author

thlsrms commented Oct 7, 2025

@liamaharon Thanks, and your merge was on point.
Sorry for the dealy, was AFK this past month.

I had some time this morning to fix the conflicts and rebase.

@gefjon
Copy link
Contributor

gefjon commented Oct 14, 2025

Why is it necessary for DbConnectionBuilder::build to be async? I find this an undesirable difference from the regular API, and it doesn't seem obviously necessary. Of course, I don't write Rust for the browser target, so I may be missing something obvious.

Why do we need to pass the auth token as a query parameter? If it is necessary, are we obtaining a short--lived token via /v1/identity/websocket-token POST, or are we just putting the user's long-lived token directly into the URL?

@thlsrms
Copy link
Author

thlsrms commented Oct 16, 2025

Why is it necessary for DbConnectionBuilder::build to be async? I find this an undesirable difference from the regular API, and it doesn't seem obviously necessary. Of course, I don't write Rust for the browser target, so I may be missing something obvious.

The native version relies on tokio's block_in_place function which blocks the current thread until the connection task is finished, this is unavailable in the browser's single-threaded environment. Making it async also passes the polling responsibility to the application level, which allows the caller to integrate the connection into their asynchronous executor.

Why do we need to pass the auth token as a query parameter? If it is necessary, are we obtaining a short--lived token via /v1/identity/websocket-token POST, or are we just putting the user's long-lived token directly into the URL?

This is a limitation on the browser's websocket API which doesn't allow header manipulation. Yes, before building the connection uri we call fetch_ws_token to get a short-lived one when an auth token is used.

Copy link
Contributor

@gefjon gefjon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't say I love making build be async, but I see that it's necessary, so what are you gonna do.

We're discussing internally how to get this tested. Once that's figured out, we should be able to merge this.

@jdetter
Copy link
Collaborator

jdetter commented Oct 22, 2025

When/If this merges give me a ping on this so we can move forward this ticket: #3462

Copy link
Contributor

@kistz kistz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am no member of clockworklabs just a guy but thought this could be useful info :>

@cheekyleek
Copy link

Very excited about this

@thlsrms
Copy link
Author

thlsrms commented Oct 23, 2025

@gefjon Thanks for taking a look at this, I'll try tackling it over the weekend or at the start of the next week.

Copy link
Contributor

@gefjon gefjon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! A few minor things, then if you can get this updated for latest master and passing CI, I think we'll be good to go.

pub fn add_unique_constraint<Col>(&mut self, unique_index_name: &'static str, get_unique_col: fn(&Row) -> &Col)
where
Col: Any + Clone + std::hash::Hash + Eq + Send + Sync + std::fmt::Debug + 'static,
Col: std::any::Any + Clone + std::hash::Hash + Eq + Send + Sync + std::fmt::Debug + 'static,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change?

ahash = { version = "0.8", default-features = false, features = ["std"] }
anyhow = "1.0.68"
anymap = "0.12"
anymap = { package = "anymap3", version = "1.0.1" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update your PR description to document & justify this change.

@jazzay
Copy link

jazzay commented Nov 20, 2025

@thlsrms any chance you could wrap this up in time for the next stdb release?

@thlsrms
Copy link
Author

thlsrms commented Nov 20, 2025

@thlsrms any chance you could wrap this up in time for the next stdb release?

Yes! I'll do my best to do it Saturday morning!

- `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`.
@gefjon
Copy link
Contributor

gefjon commented Nov 26, 2025

Replaced unmaintained anymap crate with anymap3.

If the only reason to replace anymap with anymap3 is that the former is unmaintained, that's not a compelling enough reason to make the change, and certainly not strong enough to make it in an unrelated PR. If anymap was in a good state when it stopped receiving updates, we'd rather continue using it as-is than take the time to evaluate and test a new crate. And more importantly, if we need or want to switch for reasons not directly related to adding Wasm32 support to the Rust client SDK, then the switch should be a separate PR.

What I'm looking for in the PR description is: Why is it a necessity that we switch to anymap3 in this PR, in order to make the Rust client SDK work on the Wasm32 target.

@kistz
Copy link
Contributor

kistz commented Dec 2, 2025

@thlsrms do you have any capacity at the moment to adress the feedback? (gentle ping, no rush, hope it is not annoying)

@drdozer
Copy link

drdozer commented Jan 16, 2026

Any progress on this? If you need an extra pair of hands for something, I can help. I would very much like to explore SpacetimeDB+dioxus, and this is a blocking issue for me.

@enaut
Copy link

enaut commented Jan 17, 2026

@drdozer I already did explore spacetime+dioxus: enaut/dioxus_use_spacetime#1 (AI was used)

There I'm more or less also waiting for wasm support to continue. But it already works with the git dependency on this PR

@enaut
Copy link

enaut commented Jan 17, 2026

@drdozer sorry the mixup I actually wrote an additional language export which had way better ergonomics than my first try: enaut#2 (branch here: https://github.com/enaut/SpacetimeDB/tree/copilot/explore-dioxus-signals-hooks ) when using... what it basically does is it hooks in the spacetime generate step and generates dioxus native signals so that it easily/natively integrates.

@enaut
Copy link

enaut commented Jan 20, 2026

@gefjon You can just revert 51b77f0 . the commit does mention a crash - that I did not experience... so I don't know why the dependency was added... but I think that could be handled in a separate PR. That way this PR could be merged and wasm support could land!

@drdozer
Copy link

drdozer commented Feb 5, 2026

@drdozer sorry the mixup I actually wrote an additional language export [...] what it basically does is it hooks in the spacetime generate step and generates dioxus native signals so that it easily/natively integrates.

That looks really nice. Was there a reason you closed that pull request without merging? Sorry, I'm still trying to carve out some time where I can try this stuff out.

@enaut
Copy link

enaut commented Feb 6, 2026

That looks really nice. Was there a reason you closed that pull request without merging? Sorry, I'm still trying to carve out some time where I can try this stuff out.

@drdozer I'm not yet confident enough it is actually any good... I had the Idea and thought AI might generate something useful - It did do rather well - I think. I haven't had any time to thoroughly test anything, though. And I don't want to just open a PR here and let someone else sift through the AI stuff... the PR was mostly for copilot to have something to work with and was only as merge into my own fork... If you are interested and you don't mind that it is untested AI you are quite welcome to comment on the stuff... I also generated a proof of concept TODOmvc with it... That I only have offline... I could publish that too if you are interested...

@shahroz-wilder
Copy link

Looking forward for this one 🙌

@bfops
Copy link
Collaborator

bfops commented Mar 18, 2026

Thank you for opening this! Closing this since #4089 is based on this and updates it for more recent versions of master.

@bfops bfops closed this Mar 18, 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.