Skip to content

Enable wasm-bindgen feature with target wasm32-unknown-emscripten - #1349

Open
DouglasDwyer wants to merge 1 commit into
RustAudio:masterfrom
DouglasDwyer:webaudio-reach-any-wasm-target
Open

Enable wasm-bindgen feature with target wasm32-unknown-emscripten#1349
DouglasDwyer wants to merge 1 commit into
RustAudio:masterfrom
DouglasDwyer:webaudio-reach-any-wasm-target

Conversation

@DouglasDwyer

@DouglasDwyer DouglasDwyer commented Sep 1, 2026

Copy link
Copy Markdown

Summary

The wasm-bindgen tool is finally getting support for integration with Emscripten. The feature is still quite new, but this means that most of Rust's web ecosystem can now work with the Emscripten target. I'd like to use cpal in a WASM/Emscripten project, but right now the wasm32-unknown-emscripten target is hard-coded to use the null backend. This PR eliminates the feature gate to make the wasm-bindgen feature work with wasm32-unknown-emscripten too.

This PR exposes the webaudio backend but not the audioworklet backend. That backend relies on re-instantiating the WASM module, but the way Emscripten modules get instantiated is different, so it wouldn't work without more changes.

Changes

  • Replace #[cfg(all(target_arch = "wasm32", target_os = "unknown", feature = "wasm-bindgen"))] with #[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))] for the webaudio backend
  • Use Closure::wrap_aborting instead of Closure::wrap so that the code properly compiles on WASM targets with panic=unwind
  • Bump wasm-bindgen dependency to 0.2.110 in order to use Closure::wrap_aborting
  • Add an additional CI job for the Emscripten target

Testing

In my own project, I have gotten cpal audio working with a Rust/Emscripten WASM module in Chrome. This PR also adds CI checks to ensure that compilation is successful.

Related issues

#92 #413 #810

@roderickvd roderickvd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's great! Not so long ago we removed the old Emscripten host that had become defunct. This seems like a light-weight manner to get Emscripten support back.

Beyond the changes requested in the review points, please also consider updating README.md with Emscripten support.

Comment thread src/host/webaudio/mod.rs Outdated
Comment thread Cargo.toml Outdated
Comment thread CHANGELOG.md Outdated
@DouglasDwyer
DouglasDwyer force-pushed the webaudio-reach-any-wasm-target branch from 0eda773 to ccac245 Compare September 2, 2026 03:23
Enable the WebAudio host (and its wasm-bindgen/js-sys/web-sys deps) for
`wasm32-unknown-emscripten`, gated on
`any(target_os = "emscripten", target_os = "unknown")` so nothing
wasm-bindgen-related is pulled in for `wasm32-wasip1`/`wasip2`. The
AudioWorklet host stays `wasm32-unknown-unknown`-only.

The three WebAudio JS callbacks keep using `Closure::wrap`. Dropping the
`as Box<dyn FnMut(_)>` cast keeps the closures concrete, so their captures
(all `UnwindSafe`) satisfy the `panic=unwind` bound on Emscripten without
`wrap_aborting` -- a callback panic still surfaces as a JS exception
rather than aborting the instance. Minimum `wasm-bindgen` stays at 0.2.

README: document the `wasm32-unknown-emscripten` target (Emscripten 6.0.3,
wasm-bindgen 0.2.127) and list it under the `wasm-bindgen` feature. Adds
an Emscripten CI job.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@DouglasDwyer
DouglasDwyer force-pushed the webaudio-reach-any-wasm-target branch from ccac245 to 1620436 Compare September 2, 2026 03:24
@DouglasDwyer

Copy link
Copy Markdown
Author

Thank you for your swift response! I have responded to the comments, and additionally updated the tables in the README to reflect support for the Emscripten target.

@roderickvd roderickvd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the quick turnaround. Here's a few points, hopefully the last.

Comment thread README.md
| WASAPI / ASIO | Windows | 1.85 | Windows 8 |
| WASM (`wasm32-unknown`) | WebAssembly | 1.85 | — |
| WASM (`wasm32-unknown-unknown`) | WebAssembly | 1.85 | — |
| WASM (`wasm32-unknown-emscripten`) | WebAssembly | 1.85 | Emscripten 6.0.3, wasm-bindgen 0.2.127 |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it's wasm-bindgen 0.2.127 and up specifically, then should that version not also be pinned in Cargo.toml?

Comment thread CHANGELOG.md
- **ALSA**: Update `alsa` dependency to 0.12.
- **Linux**: `realtime` can now promote threads without requiring `realtime-dbus`.
- **PipeWire**: Set `node.rate` property so that `default.clock.allowed-rates` PipeWire config works.
- **WebAudio**: the WebAudio host now works on `wasm32-unknown-emscripten` via [wasm-bindgen/Emscripten integration](https://github.com/wasm-bindgen/wasm-bindgen/issues/5237).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I propose to move this to the "Added" section, rephrasing it to "WebAudio: added support for Emscripten targets via ..."

Comment thread src/platform/mod.rs
assert!(
WebAudioHost::is_available(),
"WebAudio is not available in this context; \
AudioContext requires a Window (not a Worker or Service Worker)"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

...or now Emscripten...

Comment thread src/host/webaudio/mod.rs
let current_time_bits_cb = current_time_bits.clone();

let on_audio_process = Closure::wrap(Box::new(move |event: AudioProcessingEvent| {
let on_audio_process_fn = Box::new(move |event: AudioProcessingEvent| {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are these changes to make it a _fn and wrap it later still necessary? Seems they can be removed and reduce the diff size, unless you think it reads a lot better or I'm missing something else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants