Skip to content

Commit abd2bd4

Browse files
nodejs-github-botruyadorno
authored andcommitted
deps: update undici to 6.20.1
PR-URL: #55503 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent 445d117 commit abd2bd4

17 files changed

+536
-381
lines changed

deps/undici/src/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ The `body` mixins are the most common way to format the request/response body. M
8484

8585
- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)
8686
- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)
87+
- [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)
8788
- [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
8889
- [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)
8990

deps/undici/src/docs/docs/api/Dispatcher.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -488,11 +488,13 @@ The `RequestOptions.method` property should not be value `'CONNECT'`.
488488

489489
`body` contains the following additional [body mixin](https://fetch.spec.whatwg.org/#body-mixin) methods and properties:
490490

491-
- `text()`
492-
- `json()`
493-
- `arrayBuffer()`
494-
- `body`
495-
- `bodyUsed`
491+
* [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)
492+
* [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)
493+
* [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)
494+
* [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
495+
* [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)
496+
* `body`
497+
* `bodyUsed`
496498

497499
`body` can not be consumed twice. For example, calling `text()` after `json()` throws `TypeError`.
498500

deps/undici/src/docs/docs/api/Fetch.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ This API is implemented as per the standard, you can find documentation on [MDN]
2828

2929
- [`.arrayBuffer()`](https://fetch.spec.whatwg.org/#dom-body-arraybuffer)
3030
- [`.blob()`](https://fetch.spec.whatwg.org/#dom-body-blob)
31+
- [`.bytes()`](https://fetch.spec.whatwg.org/#dom-body-bytes)
3132
- [`.formData()`](https://fetch.spec.whatwg.org/#dom-body-formdata)
3233
- [`.json()`](https://fetch.spec.whatwg.org/#dom-body-json)
3334
- [`.text()`](https://fetch.spec.whatwg.org/#dom-body-text)

deps/undici/src/lib/api/readable.js

+33-9
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ class BodyReadable extends Readable {
121121
return consume(this, 'blob')
122122
}
123123

124+
// https://fetch.spec.whatwg.org/#dom-body-bytes
125+
async bytes () {
126+
return consume(this, 'bytes')
127+
}
128+
124129
// https://fetch.spec.whatwg.org/#dom-body-arraybuffer
125130
async arrayBuffer () {
126131
return consume(this, 'arrayBuffer')
@@ -306,6 +311,31 @@ function chunksDecode (chunks, length) {
306311
return buffer.utf8Slice(start, bufferLength)
307312
}
308313

314+
/**
315+
* @param {Buffer[]} chunks
316+
* @param {number} length
317+
* @returns {Uint8Array}
318+
*/
319+
function chunksConcat (chunks, length) {
320+
if (chunks.length === 0 || length === 0) {
321+
return new Uint8Array(0)
322+
}
323+
if (chunks.length === 1) {
324+
// fast-path
325+
return new Uint8Array(chunks[0])
326+
}
327+
const buffer = new Uint8Array(Buffer.allocUnsafeSlow(length).buffer)
328+
329+
let offset = 0
330+
for (let i = 0; i < chunks.length; ++i) {
331+
const chunk = chunks[i]
332+
buffer.set(chunk, offset)
333+
offset += chunk.length
334+
}
335+
336+
return buffer
337+
}
338+
309339
function consumeEnd (consume) {
310340
const { type, body, resolve, stream, length } = consume
311341

@@ -315,17 +345,11 @@ function consumeEnd (consume) {
315345
} else if (type === 'json') {
316346
resolve(JSON.parse(chunksDecode(body, length)))
317347
} else if (type === 'arrayBuffer') {
318-
const dst = new Uint8Array(length)
319-
320-
let pos = 0
321-
for (const buf of body) {
322-
dst.set(buf, pos)
323-
pos += buf.byteLength
324-
}
325-
326-
resolve(dst.buffer)
348+
resolve(chunksConcat(body, length).buffer)
327349
} else if (type === 'blob') {
328350
resolve(new Blob(body, { type: stream[kContentType] }))
351+
} else if (type === 'bytes') {
352+
resolve(chunksConcat(body, length))
329353
}
330354

331355
consumeFinish(consume)

deps/undici/src/lib/dispatcher/client-h1.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,10 @@ function writeH1 (client, request) {
860860
const expectsPayload = (
861861
method === 'PUT' ||
862862
method === 'POST' ||
863-
method === 'PATCH'
863+
method === 'PATCH' ||
864+
method === 'QUERY' ||
865+
method === 'PROPFIND' ||
866+
method === 'PROPPATCH'
864867
)
865868

866869
if (util.isFormDataLike(body)) {
@@ -1139,7 +1142,7 @@ function writeBuffer (abort, body, client, request, socket, contentLength, heade
11391142
socket.uncork()
11401143
request.onBodySent(body)
11411144

1142-
if (!expectsPayload) {
1145+
if (!expectsPayload && request.reset !== false) {
11431146
socket[kReset] = true
11441147
}
11451148
}
@@ -1169,7 +1172,7 @@ async function writeBlob (abort, body, client, request, socket, contentLength, h
11691172
request.onBodySent(buffer)
11701173
request.onRequestSent()
11711174

1172-
if (!expectsPayload) {
1175+
if (!expectsPayload && request.reset !== false) {
11731176
socket[kReset] = true
11741177
}
11751178

@@ -1270,7 +1273,7 @@ class AsyncWriter {
12701273
socket.cork()
12711274

12721275
if (bytesWritten === 0) {
1273-
if (!expectsPayload) {
1276+
if (!expectsPayload && request.reset !== false) {
12741277
socket[kReset] = true
12751278
}
12761279

deps/undici/src/lib/dispatcher/client-h2.js

+56-19
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ const {
2424
kOnError,
2525
kMaxConcurrentStreams,
2626
kHTTP2Session,
27-
kResume
27+
kResume,
28+
kSize,
29+
kHTTPContext
2830
} = require('../core/symbols.js')
2931

3032
const kOpenStreams = Symbol('open streams')
@@ -160,11 +162,10 @@ async function connectH2 (client, socket) {
160162
version: 'h2',
161163
defaultPipelining: Infinity,
162164
write (...args) {
163-
// TODO (fix): return
164-
writeH2(client, ...args)
165+
return writeH2(client, ...args)
165166
},
166167
resume () {
167-
168+
resumeH2(client)
168169
},
169170
destroy (err, callback) {
170171
if (closed) {
@@ -183,6 +184,20 @@ async function connectH2 (client, socket) {
183184
}
184185
}
185186

187+
function resumeH2 (client) {
188+
const socket = client[kSocket]
189+
190+
if (socket?.destroyed === false) {
191+
if (client[kSize] === 0 && client[kMaxConcurrentStreams] === 0) {
192+
socket.unref()
193+
client[kHTTP2Session].unref()
194+
} else {
195+
socket.ref()
196+
client[kHTTP2Session].ref()
197+
}
198+
}
199+
}
200+
186201
function onHttp2SessionError (err) {
187202
assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID')
188203

@@ -210,17 +225,32 @@ function onHttp2SessionEnd () {
210225
* along with the socket right away
211226
*/
212227
function onHTTP2GoAway (code) {
213-
const err = new RequestAbortedError(`HTTP/2: "GOAWAY" frame received with code ${code}`)
228+
// We cannot recover, so best to close the session and the socket
229+
const err = this[kError] || new SocketError(`HTTP/2: "GOAWAY" frame received with code ${code}`, util.getSocketInfo(this))
230+
const client = this[kClient]
214231

215-
// We need to trigger the close cycle right away
216-
// We need to destroy the session and the socket
217-
// Requests should be failed with the error after the current one is handled
218-
this[kSocket][kError] = err
219-
this[kClient][kOnError](err)
232+
client[kSocket] = null
233+
client[kHTTPContext] = null
220234

221-
this.unref()
235+
if (this[kHTTP2Session] != null) {
236+
this[kHTTP2Session].destroy(err)
237+
this[kHTTP2Session] = null
238+
}
222239

223240
util.destroy(this[kSocket], err)
241+
242+
// Fail head of pipeline.
243+
const request = client[kQueue][client[kRunningIdx]]
244+
client[kQueue][client[kRunningIdx]++] = null
245+
util.errorRequest(client, request, err)
246+
247+
client[kPendingIdx] = client[kRunningIdx]
248+
249+
assert(client[kRunning] === 0)
250+
251+
client.emit('disconnect', client[kUrl], [client], err)
252+
253+
client[kResume]()
224254
}
225255

226256
// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
@@ -237,10 +267,6 @@ function writeH2 (client, request) {
237267
return false
238268
}
239269

240-
if (request.aborted) {
241-
return false
242-
}
243-
244270
const headers = {}
245271
for (let n = 0; n < reqHeaders.length; n += 2) {
246272
const key = reqHeaders[n + 0]
@@ -283,6 +309,8 @@ function writeH2 (client, request) {
283309
// We do not destroy the socket as we can continue using the session
284310
// the stream get's destroyed and the session remains to create new streams
285311
util.destroy(body, err)
312+
client[kQueue][client[kRunningIdx]++] = null
313+
client[kResume]()
286314
}
287315

288316
try {
@@ -293,6 +321,10 @@ function writeH2 (client, request) {
293321
util.errorRequest(client, request, err)
294322
}
295323

324+
if (request.aborted) {
325+
return false
326+
}
327+
296328
if (method === 'CONNECT') {
297329
session.ref()
298330
// We are already connected, streams are pending, first request
@@ -304,10 +336,12 @@ function writeH2 (client, request) {
304336
if (stream.id && !stream.pending) {
305337
request.onUpgrade(null, null, stream)
306338
++session[kOpenStreams]
339+
client[kQueue][client[kRunningIdx]++] = null
307340
} else {
308341
stream.once('ready', () => {
309342
request.onUpgrade(null, null, stream)
310343
++session[kOpenStreams]
344+
client[kQueue][client[kRunningIdx]++] = null
311345
})
312346
}
313347

@@ -428,17 +462,20 @@ function writeH2 (client, request) {
428462
// Present specially when using pipeline or stream
429463
if (stream.state?.state == null || stream.state.state < 6) {
430464
request.onComplete([])
431-
return
432465
}
433466

434-
// Stream is closed or half-closed-remote (6), decrement counter and cleanup
435-
// It does not have sense to continue working with the stream as we do not
436-
// have yet RST_STREAM support on client-side
437467
if (session[kOpenStreams] === 0) {
468+
// Stream is closed or half-closed-remote (6), decrement counter and cleanup
469+
// It does not have sense to continue working with the stream as we do not
470+
// have yet RST_STREAM support on client-side
471+
438472
session.unref()
439473
}
440474

441475
abort(new InformationalError('HTTP/2: stream half-closed (remote)'))
476+
client[kQueue][client[kRunningIdx]++] = null
477+
client[kPendingIdx] = client[kRunningIdx]
478+
client[kResume]()
442479
})
443480

444481
stream.once('close', () => {

deps/undici/src/lib/dispatcher/client.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ let deprecatedInterceptorWarned = false
6363

6464
const kClosedResolve = Symbol('kClosedResolve')
6565

66+
const noop = () => {}
67+
6668
function getPipelining (client) {
6769
return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1
6870
}
@@ -442,7 +444,7 @@ async function connect (client) {
442444
})
443445

444446
if (client.destroyed) {
445-
util.destroy(socket.on('error', () => {}), new ClientDestroyedError())
447+
util.destroy(socket.on('error', noop), new ClientDestroyedError())
446448
return
447449
}
448450

@@ -453,7 +455,7 @@ async function connect (client) {
453455
? await connectH2(client, socket)
454456
: await connectH1(client, socket)
455457
} catch (err) {
456-
socket.destroy().on('error', () => {})
458+
socket.destroy().on('error', noop)
457459
throw err
458460
}
459461

deps/undici/src/lib/dispatcher/pool-base.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ class PoolBase extends DispatcherBase {
113113

114114
async [kClose] () {
115115
if (this[kQueue].isEmpty()) {
116-
return Promise.all(this[kClients].map(c => c.close()))
116+
await Promise.all(this[kClients].map(c => c.close()))
117117
} else {
118-
return new Promise((resolve) => {
118+
await new Promise((resolve) => {
119119
this[kClosedResolve] = resolve
120120
})
121121
}
@@ -130,7 +130,7 @@ class PoolBase extends DispatcherBase {
130130
item.handler.onError(err)
131131
}
132132

133-
return Promise.all(this[kClients].map(c => c.destroy(err)))
133+
await Promise.all(this[kClients].map(c => c.destroy(err)))
134134
}
135135

136136
[kDispatch] (opts, handler) {

deps/undici/src/lib/dispatcher/proxy-agent.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ function defaultFactory (origin, opts) {
2323
return new Pool(origin, opts)
2424
}
2525

26+
const noop = () => {}
27+
2628
class ProxyAgent extends DispatcherBase {
2729
constructor (opts) {
2830
super()
@@ -81,7 +83,7 @@ class ProxyAgent extends DispatcherBase {
8183
servername: this[kProxyTls]?.servername || proxyHostname
8284
})
8385
if (statusCode !== 200) {
84-
socket.on('error', () => {}).destroy()
86+
socket.on('error', noop).destroy()
8587
callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`))
8688
}
8789
if (opts.protocol !== 'https:') {

deps/undici/src/lib/llhttp/wasm_build_env.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

2-
> undici@6.20.0 prebuild:wasm
2+
> undici@6.20.1 prebuild:wasm
33
> node build/wasm.js --prebuild
44

55
> docker build --platform=linux/x86_64 -t llhttp_wasm_builder -f /home/runner/work/node/node/deps/undici/src/build/Dockerfile /home/runner/work/node/node/deps/undici/src
66

77

88

9-
> undici@6.20.0 build:wasm
9+
> undici@6.20.1 build:wasm
1010
> node build/wasm.js --docker
1111

1212
> docker run --rm -t --platform=linux/x86_64 --user 1001:127 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/undici/lib/llhttp llhttp_wasm_builder node build/wasm.js

0 commit comments

Comments
 (0)