dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.26k stars 1.58k forks source link

Type discrepancies when working with JS/WASM Web Workers #57113

Open d-markey opened 5 hours ago

d-markey commented 5 hours ago

Background: I maintain a package dealing with Web and native multithreading and recently ported it to Wasm. I've come across various issues especially in terms of type management (how to reenter Dart-land and regain strong types after a payload was sent with postMessage()) but eventually managed to complete the migration. Some articles were very helpful eg. https://github.com/dart-lang/sdk/issues/55203.

Issue: recently, a user reported a bug where they're sending a Map<int, double> to a WASM Web worker, causing the worker to fail with exception message JSString is not a subtype of type num in type cast.

At first, I thought the issue was likely in user-code because I didn't understand why a Map<int, double> payload would cause a problem related to some JSString.

It turns out it's a real issue and Map<int, double> is effectively received by the worker as a Map<Object?, Object?> (that is expected) with values of type double (OK also) but with keys of type JSStringImpl (not OK).

I've implemented a quick test to reproduce --> https://github.com/d-markey/wasm-test

Turns out the keys of a Map<bool, bool> are also received by the worker as JSStringImpl in WASM (String in JS).

Does anyone know whether this is a Dart issue, or by design per postMessage() / structured-clone spec, or maybe due to some browser-specific implementation? Will keys of a map always materialize as Strings or JSStrings after going through postMessage()?

I managed to implement a quick fix for this issue, but it really looks like a hack IMHO. I would like to know if there's a better way to go to ensure key types are preserved, or maybe if this is a bug in Dart's runtime that could be fixed?

All comments welcome!

dart-github-bot commented 5 hours ago

Summary: WebAssembly worker receives Map keys as JSStringImpl instead of their original type after using postMessage(), causing type errors. A workaround exists, but a proper solution is needed.