Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deps: update undici to 7.2.3 #56624

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 17 additions & 12 deletions deps/undici/src/lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -600,20 +600,25 @@ function ReadableStreamFrom (iterable) {
async start () {
iterator = iterable[Symbol.asyncIterator]()
},
async pull (controller) {
const { done, value } = await iterator.next()
if (done) {
queueMicrotask(() => {
controller.close()
controller.byobRequest?.respond(0)
})
} else {
const buf = Buffer.isBuffer(value) ? value : Buffer.from(value)
if (buf.byteLength) {
controller.enqueue(new Uint8Array(buf))
pull (controller) {
async function pull () {
const { done, value } = await iterator.next()
if (done) {
queueMicrotask(() => {
controller.close()
controller.byobRequest?.respond(0)
})
} else {
const buf = Buffer.isBuffer(value) ? value : Buffer.from(value)
if (buf.byteLength) {
controller.enqueue(new Uint8Array(buf))
} else {
return await pull()
}
}
}
return controller.desiredSize > 0

return pull()
},
async cancel () {
await iterator.return()
Expand Down
101 changes: 77 additions & 24 deletions deps/undici/src/lib/interceptor/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DNSInstance {

// If full, we just return the origin
if (ips == null && this.full) {
cb(null, origin.origin)
cb(null, origin)
return
}

Expand Down Expand Up @@ -74,9 +74,9 @@ class DNSInstance {

cb(
null,
`${origin.protocol}//${
new URL(`${origin.protocol}//${
ip.family === 6 ? `[${ip.address}]` : ip.address
}${port}`
}${port}`)
)
})
} else {
Expand Down Expand Up @@ -105,9 +105,9 @@ class DNSInstance {

cb(
null,
`${origin.protocol}//${
new URL(`${origin.protocol}//${
ip.family === 6 ? `[${ip.address}]` : ip.address
}${port}`
}${port}`)
)
}
}
Expand Down Expand Up @@ -192,6 +192,38 @@ class DNSInstance {
return ip
}

pickFamily (origin, ipFamily) {
const records = this.#records.get(origin.hostname)?.records
if (!records) {
return null
}

const family = records[ipFamily]
if (!family) {
return null
}

if (family.offset == null || family.offset === maxInt) {
family.offset = 0
} else {
family.offset++
}

const position = family.offset % family.ips.length
const ip = family.ips[position] ?? null
if (ip == null) {
return ip
}

if (Date.now() - ip.timestamp > ip.ttl) { // record TTL is already in ms
// We delete expired records
// It is possible that they have different TTL, so we manage them individually
family.ips.splice(position, 1)
}

return ip
}

setRecords (origin, addresses) {
const timestamp = Date.now()
const records = { records: { 4: null, 6: null } }
Expand Down Expand Up @@ -228,10 +260,13 @@ class DNSDispatchHandler extends DecoratorHandler {
#dispatch = null
#origin = null
#controller = null
#newOrigin = null
#firstTry = true

constructor (state, { origin, handler, dispatch }, opts) {
constructor (state, { origin, handler, dispatch, newOrigin }, opts) {
super(handler)
this.#origin = origin
this.#newOrigin = newOrigin
this.#opts = { ...opts }
this.#state = state
this.#dispatch = dispatch
Expand All @@ -242,21 +277,36 @@ class DNSDispatchHandler extends DecoratorHandler {
case 'ETIMEDOUT':
case 'ECONNREFUSED': {
if (this.#state.dualStack) {
// We delete the record and retry
this.#state.runLookup(this.#origin, this.#opts, (err, newOrigin) => {
if (err) {
super.onResponseError(controller, err)
return
}

const dispatchOpts = {
...this.#opts,
origin: newOrigin
}
if (!this.#firstTry) {
super.onResponseError(controller, err)
return
}
this.#firstTry = false

// Pick an ip address from the other family
const otherFamily = this.#newOrigin.hostname[0] === '[' ? 4 : 6
const ip = this.#state.pickFamily(this.#origin, otherFamily)
if (ip == null) {
super.onResponseError(controller, err)
return
}

this.#dispatch(dispatchOpts, this)
})
let port
if (typeof ip.port === 'number') {
port = `:${ip.port}`
} else if (this.#origin.port !== '') {
port = `:${this.#origin.port}`
} else {
port = ''
}

const dispatchOpts = {
...this.#opts,
origin: `${this.#origin.protocol}//${
ip.family === 6 ? `[${ip.address}]` : ip.address
}${port}`
}
this.#dispatch(dispatchOpts, this)
return
}

Expand All @@ -266,7 +316,8 @@ class DNSDispatchHandler extends DecoratorHandler {
}
case 'ENOTFOUND':
this.#state.deleteRecords(this.#origin)
// eslint-disable-next-line no-fallthrough
super.onResponseError(controller, err)
break
default:
super.onResponseError(controller, err)
break
Expand Down Expand Up @@ -356,11 +407,10 @@ module.exports = interceptorOpts => {
return handler.onResponseError(null, err)
}

let dispatchOpts = null
dispatchOpts = {
const dispatchOpts = {
...origDispatchOpts,
servername: origin.hostname, // For SNI on TLS
origin: newOrigin,
origin: newOrigin.origin,
headers: {
host: origin.host,
...origDispatchOpts.headers
Expand All @@ -369,7 +419,10 @@ module.exports = interceptorOpts => {

dispatch(
dispatchOpts,
instance.getHandler({ origin, dispatch, handler }, origDispatchOpts)
instance.getHandler(
{ origin, dispatch, handler, newOrigin },
origDispatchOpts
)
)
})

Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/llhttp/wasm_build_env.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

> [email protected].1 build:wasm
> [email protected].3 build:wasm
> node build/wasm.js --docker

> docker run --rm --platform=linux/x86_64 --user 1001:128 --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
Expand Down
10 changes: 9 additions & 1 deletion deps/undici/src/lib/web/fetch/body.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ const { isErrored, isDisturbed } = require('node:stream')
const { isArrayBuffer } = require('node:util/types')
const { serializeAMimeType } = require('./data-url')
const { multipartFormDataParser } = require('./formdata-parser')
let random

try {
const crypto = require('node:crypto')
random = (max) => crypto.randomInt(0, max)
} catch {
random = (max) => Math.floor(Math.random(max))
}

const textEncoder = new TextEncoder()
function noop () {}
Expand Down Expand Up @@ -110,7 +118,7 @@ function extractBody (object, keepalive = false) {
// Set source to a copy of the bytes held by object.
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
} else if (webidl.is.FormData(object)) {
const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}`
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}`
const prefix = `--${boundary}\r\nContent-Disposition: form-data`

/*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
Expand Down
27 changes: 26 additions & 1 deletion deps/undici/src/lib/web/websocket/connection.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require('./constants')
const { failWebsocketConnection, parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util')
const { parseExtensions, isClosed, isClosing, isEstablished, validateCloseCodeAndReason } = require('./util')
const { channels } = require('../../core/diagnostics')
const { makeRequest } = require('../fetch/request')
const { fetching } = require('../fetch/index')
Expand Down Expand Up @@ -294,7 +294,32 @@ function closeWebSocketConnection (object, code, reason, validate = false) {
}
}

/**
* @param {import('./websocket').Handler} handler
* @param {number} code
* @param {string|undefined} reason
* @returns {void}
*/
function failWebsocketConnection (handler, code, reason) {
// If _The WebSocket Connection is Established_ prior to the point where
// the endpoint is required to _Fail the WebSocket Connection_, the
// endpoint SHOULD send a Close frame with an appropriate status code
// (Section 7.4) before proceeding to _Close the WebSocket Connection_.
if (isEstablished(handler.readyState)) {
closeWebSocketConnection(handler, code, reason, false)
}

handler.controller.abort()

if (handler.socket?.destroyed === false) {
handler.socket.destroy()
}

handler.onFail(code, reason)
}

module.exports = {
establishWebSocketConnection,
failWebsocketConnection,
closeWebSocketConnection
}
2 changes: 1 addition & 1 deletion deps/undici/src/lib/web/websocket/receiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ const { channels } = require('../../core/diagnostics')
const {
isValidStatusCode,
isValidOpcode,
failWebsocketConnection,
websocketMessageReceived,
utf8Decode,
isControlFrame,
isTextBinaryFrame,
isContinuationFrame
} = require('./util')
const { failWebsocketConnection } = require('./connection')
const { WebsocketFrameSend } = require('./frame')
const { PerMessageDeflate } = require('./permessage-deflate')

Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/lib/web/websocket/stream/websocketstream.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
const { createDeferredPromise, environmentSettingsObject } = require('../../fetch/util')
const { states, opcodes, sentCloseFrameState } = require('../constants')
const { webidl } = require('../../fetch/webidl')
const { getURLRecord, isValidSubprotocol, isEstablished, failWebsocketConnection, utf8Decode } = require('../util')
const { establishWebSocketConnection, closeWebSocketConnection } = require('../connection')
const { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require('../util')
const { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require('../connection')
const { types } = require('node:util')
const { channels } = require('../../../core/diagnostics')
const { WebsocketFrameSend } = require('../frame')
Expand Down
27 changes: 0 additions & 27 deletions deps/undici/src/lib/web/websocket/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,32 +156,6 @@ function isValidStatusCode (code) {
return code >= 3000 && code <= 4999
}

/**
* @param {import('./websocket').Handler} handler
* @param {number} code
* @param {string|undefined} reason
* @returns {void}
*/
function failWebsocketConnection (handler, code, reason) {
// If _The WebSocket Connection is Established_ prior to the point where
// the endpoint is required to _Fail the WebSocket Connection_, the
// endpoint SHOULD send a Close frame with an appropriate status code
// (Section 7.4) before proceeding to _Close the WebSocket Connection_.
if (isEstablished(handler.readyState)) {
// avoid circular require - performance is not important here
const { closeWebSocketConnection } = require('./connection')
closeWebSocketConnection(handler, code, reason, false)
}

handler.controller.abort()

if (handler.socket?.destroyed === false) {
handler.socket.destroy()
}

handler.onFail(code, reason)
}

/**
* @see https://datatracker.ietf.org/doc/html/rfc6455#section-5.5
* @param {number} opcode
Expand Down Expand Up @@ -350,7 +324,6 @@ module.exports = {
fireEvent,
isValidSubprotocol,
isValidStatusCode,
failWebsocketConnection,
websocketMessageReceived,
utf8Decode,
isControlFrame,
Expand Down
3 changes: 1 addition & 2 deletions deps/undici/src/lib/web/websocket/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ const {
isClosing,
isValidSubprotocol,
fireEvent,
failWebsocketConnection,
utf8Decode,
toArrayBuffer,
getURLRecord
} = require('./util')
const { establishWebSocketConnection, closeWebSocketConnection } = require('./connection')
const { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require('./connection')
const { ByteParser } = require('./receiver')
const { kEnumerableProperty } = require('../../core/util')
const { getGlobalDispatcher } = require('../../global')
Expand Down
Loading
Loading