wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

`Atomics.waitAsync()` polyfill does not work in Safari's WebWorkers

Open maxammann opened this issue 2 years ago • 5 comments

Describe the Bug

The wasm-bindgen-futures crate uses Atomics.waitAsync() for muli-threaded/atomic usecases. This is not supported in Safari, therefore it fallsback to a polyfill which uses WebWorkers to fill it.

Unfortunately, spawning WebWorkers from WebWorkers is not supported in Safari. Therefore, the polyfill fails with an error: ReferenceError: Can't find variable: Worker

Steps to Reproduce

An application needs to run a Rust/WebAssembly program in a WebWorker and expose an async function. Call this function now from the WebWorker in JavaScript. The WebWorker in Safari will show the error: ReferenceError: Can't find variable: Worker

Note: I will provide a reproducible demo after I gained some information on this issue.

Expected Behavior

The async function should return a result.

Actual Behavior

A clear and concise description of what actually happened.

If applicable, add screenshots to help explain your problem.

Proposal

Two possible solutions:

  • Fallback to the single-threaded implementation on Safari or in WebWorkers in general
  • Find another polyfill which works with Safari (actually the current polyfill has some other issues too: https://github.com/tc39/proposal-atomics-wait-async/issues/32).

I'm not sure why this happens. If I replace the multi-threaded implementation with the single-threaded implementation in wasm-bindgen-futures then everything works nicely. Do I even need the multi-threaded implementation for my usecase?

Additional Context

  • Downstream issue: https://github.com/maplibre/maplibre-rs/issues/166
  • Related PR: https://github.com/rustwasm/wasm-bindgen/pull/1514

maxammann avatar Aug 30 '22 12:08 maxammann

@alexcrichton sorry for tagging you directly here 😬 Do you still remember what exactly you mean with threadsafe futures here? https://github.com/rustwasm/wasm-bindgen/issues/1379

I'm not exactly sure in which cases the execution of a Future/Promise differs in the sync vs. async case.

maxammann avatar Sep 07 '22 18:09 maxammann

This implementation and threadsafe futures is basically a low-level requirement necessary to implement Rust's async functions correctly in wasm. If spawning a worker doesn't work in safari then this probably just won't work on safari for the time being. Either that or you'll need to build an alternative futures runtime which is compatible with safari

alexcrichton avatar Sep 07 '22 20:09 alexcrichton

This implementation and threadsafe futures is basically a low-level requirement necessary to implement Rust's async functions correctly in wasm.

Does that mean that the implementation in task/singlethreaded.rs is incorrect? If so, we should remove it.

Otherwise, we can add a compiler flag to forcefully use it even if atomics feature is available

ranile avatar Sep 09 '22 20:09 ranile

Does that mean that the implementation in task/singlethreaded.rs is incorrect? If so, we should remove it.

It's not incorrect, it just assumes that the program is single-threaded and could cause UB if used in a multi-threaded context.

One way to make it work would be to check in Waker::wake whether the current thread is the thread that's being woken, and panic if not. But obviously that breaks any code that needs to wake other threads, which is what waitAsync is needed for.

Liamolucko avatar Sep 09 '22 21:09 Liamolucko

Otherwise, we can add a compiler flag to forcefully use it even if atomics feature is available

sounds reasonabl to me

One way to make it work would be to check in Waker::wake whether the current thread is the thread that's being woken, and panic if not

That would probably be very nice! My application does not use Futures across threads. I use futures only for fetching data vis browser APIs.

I think the singlethreaded impl would be sufficient for that.

I'll try to do a PR which throws a nicer error for safari. Debugging this took quite long, because I had no clue where the error came from.

maxammann avatar Sep 10 '22 06:09 maxammann

Atomics.waitAsync has been merged in webkit, safari should be soon

https://bugs.webkit.org/show_bug.cgi?id=241414

samdenty avatar Dec 01 '22 19:12 samdenty

Cool, did not expect that to happen! :D

maxammann avatar Dec 01 '22 19:12 maxammann

Now in safari tech preview 160

samdenty avatar Dec 16 '22 01:12 samdenty

This is now on Safari stable, version 16.4. https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes#JavaScript

daxpedda avatar Mar 27 '23 22:03 daxpedda

I'm gonna close this as I believe this is non-actionable from wasm-bindgens side and it will just require Safari v16.4 to work.

daxpedda avatar Sep 13 '23 11:09 daxpedda