GoogleChromeLabs / GoogleChromeLabs/comlink

In-flight requests are silently dropped when the proxy is GC'd mid-await

Open
#692 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
12.8k
Forks
435
PR merge metrics
No merged PRs in 30d

Description

Hit this in production. `Comlink.wrap(worker).slow()` style calls intermittently hang forever on Chrome with no error and nothing in the console. The trigger is V8 collecting the transient proxy during the suspended await; under memory pressure it fires reliably.

When the proxy is collected, comlink's `FinalizationRegistry` cleanup runs `releaseEndpoint`, which sends RELEASE, closes the port, and clears `pendingListeners`, without checking whether any of those listeners are still mid-flight. The worker's reply lands on a closed port and the Promise never resolves.

MDN is pretty explicit about not relying on FR semantics for correctness:

> Developers shouldn't rely on cleanup callbacks for essential program logic.

[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry)

## Repro

https://github.com/nyan-left/comlink-repro

## Workaround

Pin the proxy on a longer-lived ref so it stays reachable across the await:

```js
// Before, intermittently hangs
const result = await Comlink.wrap(worker).slow();

// After (works):
const proxy = Comlink.wrap(worker);
this._keepAlive = proxy;
try {
return await proxy.slow();
} finally {
this._keepAlive = undefined;
}
```

Awkward to ask every comlink user to remember though.

## Proposed fix

Open PR: https://github.com/GoogleChromeLabs/comlink/pull/693

## Related

- #600 - Safari 16 GC'ing MessageChannel mid-callback. Same family of bug.
- #601 - rejecting pending requests on explicit `releaseProxy()`. Related but doesn't cover GC-triggered path.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.