GoogleChromeLabs / GoogleChromeLabs/comlink
intermittent callback/channel issues in Safari 16
- Dominant language
- TypeScript
- Stars
- 12.8k
- Forks
- 435
- PR merge metrics
- No merged PRs in 30d
Description
I apologize upfront for the somewhat low quality of this bug report. It is a very hard bug to reproduce outside of our particular app (which is a big, heavy, app). And, even then, it's non-deterministic, so a reduced repro isn't going to be of much value. The bug isn't in comlink, but I think there is a potential mitigation within comlink. Also, having this issue documented may help others.
On Safari 16.0, the basic callback pattern described here will sometimes silently stop working.
https://github.com/GoogleChromeLabs/comlink/tree/main/docs/examples/02-callback-example
Meaning, the callback may work for awhile, but at some point the callback function stops being called on the Main thread. This happens for callbacks with and without parameters passed in. Once it stops working, it never starts working again.
I traced into comlink and found that the postMessage from the Worker is successfully executed, but the `addEventListener('message', ...)` associated with the `MessageChannel` callback port is never invoked on the Main thread. There's no messageerror callback on main, either.
I believe what's happening is that Safari is inappropriately garbage collecting the MessageChannel under certain conditions. Things like memory pressure appear to play a role. Retaining the Endpoint created by the `proxyTransferHandler` and subscribed to in `expose` by pushing it into a module scoped data structure thus far appears to completely mitigate the problem for us.
It looks like Safari has had some issue in this space reported before:
https://bugs.webkit.org/show_bug.cgi?id=193184
https://bugs.webkit.org/show_bug.cgi?id=184502
Contributor guide
Assessment
This issue has not been assessed yet.