Skip to content
Open
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
3 changes: 1 addition & 2 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,7 @@
return iterator.next().then(({ done, value }) => {
if (done) {
return queueMicrotask(() => {
controller.close()
controller.byobRequest?.respond(0)
readableStreamClose(controller)

Check failure on line 664 in lib/core/util.js

View workflow job for this annotation

GitHub Actions / Lint

'readableStreamClose' is not defined
})
} else {
const buf = Buffer.isBuffer(value) ? value : Buffer.from(value)
Expand Down
35 changes: 35 additions & 0 deletions test/fetch/readable-stream-from.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,38 @@ test('ReadableStream empty enqueue', async (t) => {
const response = new Response(iterable)
t.assert.deepStrictEqual(await response.text(), '')
})

// https://github.com/nodejs/undici/issues/5715
test('ReadableStream cancellation while iterator.next() is in flight', async (t) => {
let resolveNext
let startNext
const nextStarted = new Promise((resolve) => {
startNext = resolve
})
const iterable = {
[Symbol.asyncIterator] () {
return {
next () {
startNext()
return new Promise((resolve) => {
resolveNext = resolve
})
},
return () {
return Promise.resolve({ done: true, value: undefined })
}
}
}
}

const reader = new Response(iterable).body.getReader()
const read = reader.read()
await nextStarted
await reader.cancel()
resolveNext({ done: true, value: undefined })
t.assert.deepStrictEqual(await read, { done: true, value: undefined })

// Let the microtask that closes the controller run. It must not throw if
// cancellation already closed the stream.
await new Promise((resolve) => setImmediate(resolve))
})
Loading