undici 6.0.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -62,6 +62,18 @@ module.exports = class BodyReadable extends Readable {
62
62
  return super.destroy(err)
63
63
  }
64
64
 
65
+ _destroy (err, callback) {
66
+ // Workaround for Node "bug". If the stream is destroyed in same
67
+ // tick as it is created, then a user who is waiting for a
68
+ // promise (i.e micro tick) for installing a 'error' listener will
69
+ // never get a chance and will always encounter an unhandled exception.
70
+ // - tick => process.nextTick(fn)
71
+ // - micro tick => queueMicrotask(fn)
72
+ queueMicrotask(() => {
73
+ callback(err)
74
+ })
75
+ }
76
+
65
77
  emit (ev, ...args) {
66
78
  if (ev === 'data') {
67
79
  // Node < 16.7
@@ -166,7 +178,7 @@ module.exports = class BodyReadable extends Readable {
166
178
  }
167
179
  }
168
180
 
169
- if (this.closed) {
181
+ if (this._readableState.closeEmitted) {
170
182
  return Promise.resolve(null)
171
183
  }
172
184
 
@@ -210,33 +222,44 @@ function isUnusable (self) {
210
222
  }
211
223
 
212
224
  async function consume (stream, type) {
213
- if (isUnusable(stream)) {
214
- throw new TypeError('unusable')
215
- }
216
-
217
225
  assert(!stream[kConsume])
218
226
 
219
227
  return new Promise((resolve, reject) => {
220
- stream[kConsume] = {
221
- type,
222
- stream,
223
- resolve,
224
- reject,
225
- length: 0,
226
- body: []
227
- }
228
+ if (isUnusable(stream)) {
229
+ const rState = stream._readableState
230
+ if (rState.destroyed && rState.closeEmitted === false) {
231
+ stream
232
+ .on('error', err => {
233
+ reject(err)
234
+ })
235
+ .on('close', () => {
236
+ reject(new TypeError('unusable'))
237
+ })
238
+ } else {
239
+ reject(rState.errored ?? new TypeError('unusable'))
240
+ }
241
+ } else {
242
+ stream[kConsume] = {
243
+ type,
244
+ stream,
245
+ resolve,
246
+ reject,
247
+ length: 0,
248
+ body: []
249
+ }
228
250
 
229
- stream
230
- .on('error', function (err) {
231
- consumeFinish(this[kConsume], err)
232
- })
233
- .on('close', function () {
234
- if (this[kConsume].body !== null) {
235
- consumeFinish(this[kConsume], new RequestAbortedError())
236
- }
237
- })
251
+ stream
252
+ .on('error', function (err) {
253
+ consumeFinish(this[kConsume], err)
254
+ })
255
+ .on('close', function () {
256
+ if (this[kConsume].body !== null) {
257
+ consumeFinish(this[kConsume], new RequestAbortedError())
258
+ }
259
+ })
238
260
 
239
- process.nextTick(consumeStart, stream[kConsume])
261
+ queueMicrotask(() => consumeStart(stream[kConsume]))
262
+ }
240
263
  })
241
264
  }
242
265
 
package/lib/client.js CHANGED
@@ -1963,12 +1963,19 @@ function writeStream ({ h2stream, body, client, request, socket, contentLength,
1963
1963
  body.resume()
1964
1964
  }
1965
1965
  }
1966
- const onAbort = function () {
1967
- if (finished) {
1968
- return
1966
+ const onClose = function () {
1967
+ // 'close' might be emitted *before* 'error' for
1968
+ // broken streams. Wait a tick to avoid this case.
1969
+ queueMicrotask(() => {
1970
+ // It's only safe to remove 'error' listener after
1971
+ // 'close'.
1972
+ body.removeListener('error', onFinished)
1973
+ })
1974
+
1975
+ if (!finished) {
1976
+ const err = new RequestAbortedError()
1977
+ queueMicrotask(() => onFinished(err))
1969
1978
  }
1970
- const err = new RequestAbortedError()
1971
- queueMicrotask(() => onFinished(err))
1972
1979
  }
1973
1980
  const onFinished = function (err) {
1974
1981
  if (finished) {
@@ -1986,8 +1993,7 @@ function writeStream ({ h2stream, body, client, request, socket, contentLength,
1986
1993
  body
1987
1994
  .removeListener('data', onData)
1988
1995
  .removeListener('end', onFinished)
1989
- .removeListener('error', onFinished)
1990
- .removeListener('close', onAbort)
1996
+ .removeListener('close', onClose)
1991
1997
 
1992
1998
  if (!err) {
1993
1999
  try {
@@ -2010,7 +2016,7 @@ function writeStream ({ h2stream, body, client, request, socket, contentLength,
2010
2016
  .on('data', onData)
2011
2017
  .on('end', onFinished)
2012
2018
  .on('error', onFinished)
2013
- .on('close', onAbort)
2019
+ .on('close', onClose)
2014
2020
 
2015
2021
  if (body.resume) {
2016
2022
  body.resume()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "6.0.0",
3
+ "version": "6.0.1",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {