Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions lib/web/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ class Response {
// 2. Let clonedResponse be the result of cloning this’s response.
const clonedResponse = cloneResponse(this.#state)

// Note: To re-register because of a new stream.
if (this.#state.body?.stream) {
streamRegistry.register(this, new WeakRef(this.#state.body.stream))
}

// 3. Return the result of creating a Response object, given
// clonedResponse, this’s headers’s guard, and this’s relevant Realm.
return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers))
Expand Down Expand Up @@ -354,8 +359,6 @@ function cloneResponse (response) {
// result of cloning response’s body.
if (response.body != null) {
newResponse.body = cloneBody(response.body)

streamRegistry.register(newResponse, new WeakRef(response.body.stream))
}

// 4. Return newResponse.
Expand Down
30 changes: 23 additions & 7 deletions test/fetch/fire-and-forget.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use strict'

const { randomFillSync } = require('node:crypto')
const { setTimeout: sleep } = require('node:timers/promises')
const { setTimeout: sleep, setImmediate: nextTick } = require('node:timers/promises')
const { test } = require('node:test')
const { fetch, Request, Agent, setGlobalDispatcher } = require('../..')
const { fetch, Request, Response, Agent, setGlobalDispatcher } = require('../..')
const { createServer } = require('node:http')
const { closeServerAsPromise } = require('../utils/node-http')
const assert = require('node:assert')

const blob = randomFillSync(new Uint8Array(1024 * 512))

Expand All @@ -20,14 +19,31 @@ test('test finalizer cloned request', async () => {

const request = new Request('http://localhost', { method: 'POST', body: 'Hello' })

for (let i = 0; i < 800; ++i) request.clone()
request.clone()

await sleep(50)
await nextTick()
// eslint-disable-next-line no-undef
gc()

await nextTick()
await request.arrayBuffer() // check consume body
})

test('test finalizer cloned response', async () => {
if (!hasGC) {
throw new Error('gc is not available. Run with \'--expose-gc\'.')
}

const response = new Response('Hello')

response.clone()

await nextTick()
// eslint-disable-next-line no-undef
gc(true)
gc()

assert.strictEqual(request.bodyUsed, false)
await nextTick()
await response.arrayBuffer() // check consume body
})

test('does not need the body to be consumed to continue', { timeout: 180_000 }, async (t) => {
Expand Down
Loading