Skip to content

Commit 638ee32

Browse files
snyamathimcollina
authored andcommitted
fix: memory leak in finalization first appearing in v6.16.0 (#3445)
* fix: memory leak Holding a reference to the stream in the finalization registry causes a memory leak, even when consuming the body. * docs: add comment explaining the strong reference * typo
1 parent 8499c4b commit 638ee32

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

lib/web/fetch/response.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ const hasFinalizationRegistry = globalThis.FinalizationRegistry && process.versi
3434
let registry
3535

3636
if (hasFinalizationRegistry) {
37-
registry = new FinalizationRegistry((stream) => {
38-
if (!stream.locked && !isDisturbed(stream) && !isErrored(stream)) {
37+
registry = new FinalizationRegistry((weakRef) => {
38+
const stream = weakRef.deref()
39+
if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) {
3940
stream.cancel('Response object has been garbage collected').catch(noop)
4041
}
4142
})
@@ -526,7 +527,12 @@ function fromInnerResponse (innerResponse, guard) {
526527
setHeadersGuard(response[kHeaders], guard)
527528

528529
if (hasFinalizationRegistry && innerResponse.body?.stream) {
529-
registry.register(response, innerResponse.body.stream)
530+
// If the target (response) is reclaimed, the cleanup callback may be called at some point with
531+
// the held value provided for it (innerResponse.body.stream). The held value can be any value:
532+
// a primitive or an object, even undefined. If the held value is an object, the registry keeps
533+
// a strong reference to it (so it can pass it to the cleanup callback later). Reworded from
534+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
535+
registry.register(response, new WeakRef(innerResponse.body.stream))
530536
}
531537

532538
return response

0 commit comments

Comments
 (0)