Skip to content

Commit e5e1cf5

Browse files
panvagithub-actions[bot]
authored andcommitted
deps: update undici to 7.20.0
1 parent 8c32389 commit e5e1cf5

File tree

17 files changed

+338
-173
lines changed

17 files changed

+338
-173
lines changed

β€Ždeps/undici/src/docs/docs/api/Dispatcher.mdβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ The `RequestOptions.method` property should not be value `'CONNECT'`.
476476
#### Parameter: `ResponseData`
477477

478478
* **statusCode** `number`
479+
* **statusText** `string` - The status message from the response (e.g., "OK", "Not Found").
479480
* **headers** `Record<string, string | string[]>` - Note that all header keys are lower-cased, e.g. `content-type`.
480481
* **body** `stream.Readable` which also implements [the body mixin from the Fetch Standard](https://fetch.spec.whatwg.org/#body-mixin).
481482
* **trailers** `Record<string, string>` - This object starts out
@@ -517,7 +518,7 @@ await once(server, 'listening')
517518
const client = new Client(`http://localhost:${server.address().port}`)
518519

519520
try {
520-
const { body, headers, statusCode, trailers } = await client.request({
521+
const { body, headers, statusCode, statusText, trailers } = await client.request({
521522
path: '/',
522523
method: 'GET'
523524
})

β€Ždeps/undici/src/docs/docs/api/MockPool.mdβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ try {
323323
method: 'GET'
324324
})
325325
} catch (error) {
326-
console.error(error) // Error: kaboom
326+
console.error(error) // TypeError: fetch failed
327+
console.error(error.cause) // Error: kaboom
327328
}
328329
```
329330

β€Ždeps/undici/src/index-fetch.jsβ€Ž

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,33 @@ const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
44
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
55
const fetchImpl = require('./lib/web/fetch').fetch
66

7+
function appendFetchStackTrace (err, filename) {
8+
if (!err || typeof err !== 'object') {
9+
return
10+
}
11+
12+
const stack = typeof err.stack === 'string' ? err.stack : ''
13+
const normalizedFilename = filename.replace(/\\/g, '/')
14+
15+
if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) {
16+
return
17+
}
18+
19+
const capture = {}
20+
Error.captureStackTrace(capture, appendFetchStackTrace)
21+
22+
if (!capture.stack) {
23+
return
24+
}
25+
26+
const captureLines = capture.stack.split('\n').slice(1).join('\n')
27+
28+
err.stack = stack ? `${stack}\n${captureLines}` : capture.stack
29+
}
30+
731
module.exports.fetch = function fetch (init, options = undefined) {
832
return fetchImpl(init, options).catch(err => {
9-
if (err && typeof err === 'object') {
10-
Error.captureStackTrace(err)
11-
}
33+
appendFetchStackTrace(err, __filename)
1234
throw err
1335
})
1436
}

β€Ždeps/undici/src/index.jsβ€Ž

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,33 @@ module.exports.getGlobalDispatcher = getGlobalDispatcher
121121

122122
const fetchImpl = require('./lib/web/fetch').fetch
123123

124+
function appendFetchStackTrace (err, filename) {
125+
if (!err || typeof err !== 'object') {
126+
return
127+
}
128+
129+
const stack = typeof err.stack === 'string' ? err.stack : ''
130+
const normalizedFilename = filename.replace(/\\/g, '/')
131+
132+
if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) {
133+
return
134+
}
135+
136+
const capture = {}
137+
Error.captureStackTrace(capture, appendFetchStackTrace)
138+
139+
if (!capture.stack) {
140+
return
141+
}
142+
143+
const captureLines = capture.stack.split('\n').slice(1).join('\n')
144+
145+
err.stack = stack ? `${stack}\n${captureLines}` : capture.stack
146+
}
147+
124148
module.exports.fetch = function fetch (init, options = undefined) {
125149
return fetchImpl(init, options).catch(err => {
126-
if (err && typeof err === 'object') {
127-
Error.captureStackTrace(err)
128-
}
150+
appendFetchStackTrace(err, __filename)
129151
throw err
130152
})
131153
}

β€Ždeps/undici/src/lib/api/api-request.jsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class RequestHandler extends AsyncResource {
121121
try {
122122
this.runInAsyncScope(callback, null, null, {
123123
statusCode,
124+
statusText: statusMessage,
124125
headers,
125126
trailers: this.trailers,
126127
opaque,

β€Ždeps/undici/src/lib/dispatcher/client-h1.jsβ€Ž

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,13 @@ class Parser {
735735
}
736736
}
737737

738-
function onParserTimeout (parser) {
739-
const { socket, timeoutType, client, paused } = parser.deref()
738+
function onParserTimeout (parserWeakRef) {
739+
const parser = parserWeakRef.deref()
740+
if (!parser) {
741+
return
742+
}
743+
744+
const { socket, timeoutType, client, paused } = parser
740745

741746
if (timeoutType === TIMEOUT_HEADERS) {
742747
if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) {

β€Ždeps/undici/src/lib/llhttp/wasm_build_env.txtβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
> undici@7.19.2 build:wasm
2+
> undici@7.20.0 build:wasm
33
> node build/wasm.js --docker
44

55
> docker run --rm --platform=linux/x86_64 --user 1001:1001 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js

β€Ždeps/undici/src/lib/mock/mock-utils.jsβ€Ž

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,16 +312,45 @@ function mockDispatch (opts, handler) {
312312
return true
313313
}
314314

315+
// Track whether the request has been aborted
316+
let aborted = false
317+
let timer = null
318+
319+
function abort (err) {
320+
if (aborted) {
321+
return
322+
}
323+
aborted = true
324+
325+
// Clear the pending delayed response if any
326+
if (timer !== null) {
327+
clearTimeout(timer)
328+
timer = null
329+
}
330+
331+
// Notify the handler of the abort
332+
handler.onError(err)
333+
}
334+
335+
// Call onConnect to allow the handler to register the abort callback
336+
handler.onConnect?.(abort, null)
337+
315338
// Handle the request with a delay if necessary
316339
if (typeof delay === 'number' && delay > 0) {
317-
setTimeout(() => {
340+
timer = setTimeout(() => {
341+
timer = null
318342
handleReply(this[kDispatches])
319343
}, delay)
320344
} else {
321345
handleReply(this[kDispatches])
322346
}
323347

324348
function handleReply (mockDispatches, _data = data) {
349+
// Don't send response if the request was aborted
350+
if (aborted) {
351+
return
352+
}
353+
325354
// fetch's HeadersList is a 1D string array
326355
const optsHeaders = Array.isArray(opts.headers)
327356
? buildHeadersFromArray(opts.headers)
@@ -340,11 +369,15 @@ function mockDispatch (opts, handler) {
340369
return body.then((newData) => handleReply(mockDispatches, newData))
341370
}
342371

372+
// Check again if aborted after async body resolution
373+
if (aborted) {
374+
return
375+
}
376+
343377
const responseData = getResponseData(body)
344378
const responseHeaders = generateKeyValues(headers)
345379
const responseTrailers = generateKeyValues(trailers)
346380

347-
handler.onConnect?.(err => handler.onError(err), null)
348381
handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode))
349382
handler.onData?.(Buffer.from(responseData))
350383
handler.onComplete?.(responseTrailers)

β€Ždeps/undici/src/lib/web/fetch/body.jsβ€Ž

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const { FormData, setFormDataState } = require('./formdata')
1111
const { webidl } = require('../webidl')
1212
const assert = require('node:assert')
1313
const { isErrored, isDisturbed } = require('node:stream')
14-
const { isArrayBuffer } = require('node:util/types')
14+
const { isUint8Array } = require('node:util/types')
1515
const { serializeAMimeType } = require('./data-url')
1616
const { multipartFormDataParser } = require('./formdata-parser')
1717
const { createDeferredPromise } = require('../../util/promise')
@@ -45,6 +45,7 @@ const streamRegistry = new FinalizationRegistry((weakRef) => {
4545
function extractBody (object, keepalive = false) {
4646
// 1. Let stream be null.
4747
let stream = null
48+
let controller = null
4849

4950
// 2. If object is a ReadableStream object, then set stream to object.
5051
if (webidl.is.ReadableStream(object)) {
@@ -57,16 +58,11 @@ function extractBody (object, keepalive = false) {
5758
// 4. Otherwise, set stream to a new ReadableStream object, and set
5859
// up stream with byte reading support.
5960
stream = new ReadableStream({
60-
pull (controller) {
61-
const buffer = typeof source === 'string' ? textEncoder.encode(source) : source
62-
63-
if (buffer.byteLength) {
64-
controller.enqueue(buffer)
65-
}
66-
67-
queueMicrotask(() => readableStreamClose(controller))
61+
pull () {},
62+
start (c) {
63+
controller = c
6864
},
69-
start () {},
65+
cancel () {},
7066
type: 'bytes'
7167
})
7268
}
@@ -108,9 +104,8 @@ function extractBody (object, keepalive = false) {
108104
// Set type to `application/x-www-form-urlencoded;charset=UTF-8`.
109105
type = 'application/x-www-form-urlencoded;charset=UTF-8'
110106
} else if (webidl.is.BufferSource(object)) {
111-
source = isArrayBuffer(object)
112-
? new Uint8Array(object.slice())
113-
: new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
107+
// Set source to a copy of the bytes held by object.
108+
source = webidl.util.getCopyOfBytesHeldByBufferSource(object)
114109
} else if (webidl.is.FormData(object)) {
115110
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}`
116111
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
@@ -213,45 +208,36 @@ function extractBody (object, keepalive = false) {
213208

214209
// 11. If source is a byte sequence, then set action to a
215210
// step that returns source and length to source’s length.
216-
if (typeof source === 'string' || util.isBuffer(source)) {
217-
length = Buffer.byteLength(source)
211+
if (typeof source === 'string' || isUint8Array(source)) {
212+
action = () => {
213+
length = typeof source === 'string' ? Buffer.byteLength(source) : source.length
214+
return source
215+
}
218216
}
219217

220-
// 12. If action is non-null, then run these steps in in parallel:
218+
// 12. If action is non-null, then run these steps in parallel:
221219
if (action != null) {
222-
// Run action.
223-
let iterator
224-
stream = new ReadableStream({
225-
start () {
226-
iterator = action(object)[Symbol.asyncIterator]()
227-
},
228-
pull (controller) {
229-
return iterator.next().then(({ value, done }) => {
230-
if (done) {
231-
// When running action is done, close stream.
232-
queueMicrotask(() => {
233-
controller.close()
234-
controller.byobRequest?.respond(0)
235-
})
236-
} else {
237-
// Whenever one or more bytes are available and stream is not errored,
238-
// enqueue a Uint8Array wrapping an ArrayBuffer containing the available
239-
// bytes into stream.
240-
if (!isErrored(stream)) {
241-
const buffer = new Uint8Array(value)
242-
if (buffer.byteLength) {
243-
controller.enqueue(buffer)
244-
}
245-
}
220+
;(async () => {
221+
// 1. Run action.
222+
const result = action()
223+
224+
// 2. Whenever one or more bytes are available and stream is not errored,
225+
// enqueue the result of creating a Uint8Array from the available bytes into stream.
226+
const iterator = result?.[Symbol.asyncIterator]?.()
227+
if (iterator) {
228+
for await (const bytes of iterator) {
229+
if (isErrored(stream)) break
230+
if (bytes.length) {
231+
controller.enqueue(new Uint8Array(bytes))
246232
}
247-
return controller.desiredSize > 0
248-
})
249-
},
250-
cancel (reason) {
251-
return iterator.return()
252-
},
253-
type: 'bytes'
254-
})
233+
}
234+
} else if (result?.length && !isErrored(stream)) {
235+
controller.enqueue(typeof result === 'string' ? textEncoder.encode(result) : new Uint8Array(result))
236+
}
237+
238+
// 3. When running action is done, close stream.
239+
queueMicrotask(() => readableStreamClose(controller))
240+
})()
255241
}
256242

257243
// 13. Let body be a body whose stream is stream, source is source,

β€Ždeps/undici/src/lib/web/fetch/index.jsβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,8 +1321,8 @@ function httpRedirectFetch (fetchParams, response) {
13211321
request.headersList.delete('host', true)
13221322
}
13231323

1324-
// 14. If request’s body is non-null, then set request’s body to the first return
1325-
// value of safely extracting request’s body’s source.
1324+
// 14. If request's body is non-null, then set request's body to the first return
1325+
// value of safely extracting request's body's source.
13261326
if (request.body != null) {
13271327
assert(request.body.source != null)
13281328
request.body = safelyExtractBody(request.body.source)[0]

0 commit comments

Comments
Β (0)