Skip to content
Merged
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
4 changes: 4 additions & 0 deletions deps/undici/src/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ undici-fetch.js

# File generated by /test/request-timeout.js
test/request-timeout.10mb.bin

# Claude files
CLAUDE.md
.claude
6 changes: 4 additions & 2 deletions deps/undici/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ const response = await fetch('https://api.example.com/data');
#### Use Built-in Fetch When:
- You want zero dependencies
- Building isomorphic code that runs in browsers and Node.js
- Publishing to npm and want to maximize compatibility with JS runtimes
- Simple HTTP requests without advanced configuration
- You're okay with the undici version bundled in your Node.js version
- You're publishing to npm and you want to maximize compatiblity
- You don't depend on features from a specific version of undici

#### Use Undici Module When:
- You need the latest undici features and performance improvements
Expand Down Expand Up @@ -209,7 +211,7 @@ The `install()` function adds the following classes to `globalThis`:
- `fetch` - The fetch function
- `Headers` - HTTP headers management
- `Response` - HTTP response representation
- `Request` - HTTP request representation
- `Request` - HTTP request representation
- `FormData` - Form data handling
- `WebSocket` - WebSocket client
- `CloseEvent`, `ErrorEvent`, `MessageEvent` - WebSocket events
Expand Down
11 changes: 7 additions & 4 deletions deps/undici/src/docs/docs/api/DiagnosticsChannel.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,11 @@ This message is published after the client has successfully connected to a serve
```js
import diagnosticsChannel from 'diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:open').subscribe(({ address, protocol, extensions }) => {
diagnosticsChannel.channel('undici:websocket:open').subscribe(({ address, protocol, extensions, websocket }) => {
console.log(address) // address, family, and port
console.log(protocol) // negotiated subprotocols
console.log(extensions) // negotiated extensions
console.log(websocket) // the WebSocket instance
})
```

Expand All @@ -184,7 +185,7 @@ This message is published after the connection has closed.
import diagnosticsChannel from 'diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:close').subscribe(({ websocket, code, reason }) => {
console.log(websocket) // the WebSocket object
console.log(websocket) // the WebSocket instance
console.log(code) // the closing status code
console.log(reason) // the closing reason
})
Expand All @@ -209,9 +210,10 @@ This message is published after the client receives a ping frame, if the connect
```js
import diagnosticsChannel from 'diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload }) => {
diagnosticsChannel.channel('undici:websocket:ping').subscribe(({ payload, websocket }) => {
// a Buffer or undefined, containing the optional application data of the frame
console.log(payload)
console.log(websocket) // the WebSocket instance
})
```

Expand All @@ -222,8 +224,9 @@ This message is published after the client receives a pong frame.
```js
import diagnosticsChannel from 'diagnostics_channel'

diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload }) => {
diagnosticsChannel.channel('undici:websocket:pong').subscribe(({ payload, websocket }) => {
// a Buffer or undefined, containing the optional application data of the frame
console.log(payload)
console.log(websocket) // the WebSocket instance
})
```
4 changes: 2 additions & 2 deletions deps/undici/src/docs/docs/api/Dispatcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -1103,8 +1103,8 @@ The `cache` interceptor implements client-side response caching as described in

- `store` - The [`CacheStore`](/docs/docs/api/CacheStore.md) to store and retrieve responses from. Default is [`MemoryCacheStore`](/docs/docs/api/CacheStore.md#memorycachestore).
- `methods` - The [**safe** HTTP methods](https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1) to cache the response of.
- `cacheByDefault` - The default expiration time to cache responses by if they don't have an explicit expiration. If this isn't present, responses without explicit expiration will not be cached. Default `undefined`.
- `type` - The type of cache for Undici to act as. Can be `shared` or `private`. Default `shared`.
- `cacheByDefault` - The default expiration time to cache responses by if they don't have an explicit expiration and cannot have an heuristic expiry computed. If this isn't present, responses neither with an explicit expiration nor heuristically cacheable will not be cached. Default `undefined`.
- `type` - The [type of cache](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching#types_of_caches) for Undici to act as. Can be `shared` or `private`. Default `shared`. `private` implies privately cacheable responses will be cached and potentially shared with other users of your application.

## Instance Events

Expand Down
27 changes: 27 additions & 0 deletions deps/undici/src/docs/docs/api/WebSocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,33 @@ setInterval(() => write(), 5000)

```

## ping(websocket, payload)
Arguments:

* **websocket** `WebSocket` - The WebSocket instance to send the ping frame on
* **payload** `Buffer|undefined` (optional) - Optional payload data to include with the ping frame. Must not exceed 125 bytes.

Sends a ping frame to the WebSocket server. The server must respond with a pong frame containing the same payload data. This can be used for keepalive purposes or to verify that the connection is still active.

### Example:

```js
import { WebSocket, ping } from 'undici'

const ws = new WebSocket('wss://echo.websocket.events')

ws.addEventListener('open', () => {
// Send ping with no payload
ping(ws)

// Send ping with payload
const payload = Buffer.from('hello')
ping(ws, payload)
})
```

**Note**: A ping frame cannot have a payload larger than 125 bytes. The ping will only be sent if the WebSocket connection is in the OPEN state.

## Read More

- [MDN - WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
Expand Down
4 changes: 3 additions & 1 deletion deps/undici/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,12 @@ module.exports.parseMIMEType = parseMIMEType
module.exports.serializeAMimeType = serializeAMimeType

const { CloseEvent, ErrorEvent, MessageEvent } = require('./lib/web/websocket/events')
module.exports.WebSocket = require('./lib/web/websocket/websocket').WebSocket
const { WebSocket, ping } = require('./lib/web/websocket/websocket')
module.exports.WebSocket = WebSocket
module.exports.CloseEvent = CloseEvent
module.exports.ErrorEvent = ErrorEvent
module.exports.MessageEvent = MessageEvent
module.exports.ping = ping

module.exports.WebSocketStream = require('./lib/web/websocket/stream/websocketstream').WebSocketStream
module.exports.WebSocketError = require('./lib/web/websocket/stream/websocketerror').WebSocketError
Expand Down
4 changes: 1 addition & 3 deletions deps/undici/src/lib/api/readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ class BodyReadable extends Readable {
// promise (i.e micro tick) for installing an 'error' listener will
// never get a chance and will always encounter an unhandled exception.
if (!this[kUsed]) {
setImmediate(() => {
callback(err)
})
setImmediate(callback, err)
} else {
callback(err)
}
Expand Down
7 changes: 6 additions & 1 deletion deps/undici/src/lib/core/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class Request {
reset,
expectContinue,
servername,
throwOnError
throwOnError,
maxRedirections
}, handler) {
if (typeof path !== 'string') {
throw new InvalidArgumentError('path must be a string')
Expand Down Expand Up @@ -86,6 +87,10 @@ class Request {
throw new InvalidArgumentError('invalid throwOnError')
}

if (maxRedirections != null && maxRedirections !== 0) {
throw new InvalidArgumentError('maxRedirections is not supported, use the redirect interceptor')
}

this.headersTimeout = headersTimeout

this.bodyTimeout = bodyTimeout
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/core/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class TstNode {

/**
* @param {Uint8Array} key
* @return {TstNode | null}
* @returns {TstNode | null}
*/
search (key) {
const keylength = key.length
Expand Down
25 changes: 8 additions & 17 deletions deps/undici/src/lib/dispatcher/client-h1.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,23 @@ const removeAllListeners = util.removeAllListeners

let extractBody

async function lazyllhttp () {
function lazyllhttp () {
const llhttpWasmData = process.env.JEST_WORKER_ID ? require('../llhttp/llhttp-wasm.js') : undefined

let mod
try {
mod = await WebAssembly.compile(require('../llhttp/llhttp_simd-wasm.js'))
mod = new WebAssembly.Module(require('../llhttp/llhttp_simd-wasm.js'))
} catch (e) {
/* istanbul ignore next */

// We could check if the error was caused by the simd option not
// being enabled, but the occurring of this other error
// * https://github.com/emscripten-core/emscripten/issues/11495
// got me to remove that check to avoid breaking Node 12.
mod = await WebAssembly.compile(llhttpWasmData || require('../llhttp/llhttp-wasm.js'))
mod = new WebAssembly.Module(llhttpWasmData || require('../llhttp/llhttp-wasm.js'))
}

return await WebAssembly.instantiate(mod, {
return new WebAssembly.Instance(mod, {
env: {
/**
* @param {number} p
Expand Down Expand Up @@ -165,11 +165,6 @@ async function lazyllhttp () {
}

let llhttpInstance = null
/**
* @type {Promise<WebAssembly.Instance>|null}
*/
let llhttpPromise = lazyllhttp()
llhttpPromise.catch()

/**
* @type {Parser|null}
Expand Down Expand Up @@ -732,7 +727,7 @@ class Parser {
// We must wait a full event loop cycle to reuse this socket to make sure
// that non-spec compliant servers are not closing the connection even if they
// said they won't.
setImmediate(() => client[kResume]())
setImmediate(client[kResume])
} else {
client[kResume]()
}
Expand Down Expand Up @@ -769,11 +764,7 @@ async function connectH1 (client, socket) {
client[kSocket] = socket

if (!llhttpInstance) {
const noop = () => {}
socket.on('error', noop)
llhttpInstance = await llhttpPromise
llhttpPromise = null
socket.off('error', noop)
llhttpInstance = lazyllhttp()
}

if (socket.errored) {
Expand Down Expand Up @@ -1297,9 +1288,9 @@ function writeStream (abort, body, client, request, socket, contentLength, heade
.on('error', onFinished)

if (body.errorEmitted ?? body.errored) {
setImmediate(() => onFinished(body.errored))
setImmediate(onFinished, body.errored)
} else if (body.endEmitted ?? body.readableEnded) {
setImmediate(() => onFinished(null))
setImmediate(onFinished, null)
}

if (body.closeEmitted ?? body.closed) {
Expand Down
5 changes: 4 additions & 1 deletion deps/undici/src/lib/handler/cache-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,10 @@ class CacheHandler {
* @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
*/
function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives) {
if (statusCode !== 200 && statusCode !== 307) {
// Allow caching for status codes 200 and 307 (original behavior)
// Also allow caching for other status codes that are heuristically cacheable
// when they have explicit cache directives
if (statusCode !== 200 && statusCode !== 307 && !HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode)) {
return false
}

Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/lib/handler/redirect-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class RedirectHandler {

this.dispatch = dispatch
this.location = null
this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy
const { maxRedirections: _, ...cleanOpts } = opts
this.opts = cleanOpts // opts must be a copy, exclude maxRedirections
this.maxRedirections = maxRedirections
this.handler = handler
this.history = []
Expand Down Expand Up @@ -138,7 +139,6 @@ class RedirectHandler {
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin)
this.opts.path = path
this.opts.origin = origin
this.opts.maxRedirections = 0
this.opts.query = null
}

Expand Down
4 changes: 2 additions & 2 deletions deps/undici/src/lib/interceptor/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,11 @@ module.exports = (opts = {}) => {
assertCacheMethods(methods, 'opts.methods')

if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') {
throw new TypeError(`exepcted opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)
throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)
}

if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') {
throw new TypeError(`exepcted opts.type to be shared, private, or undefined, got ${typeof type}`)
throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`)
}

const globalOpts = {
Expand Down
2 changes: 1 addition & 1 deletion deps/undici/src/lib/interceptor/redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }
return dispatch(opts, handler)
}

const dispatchOpts = { ...rest, maxRedirections: 0 } // Stop sub dispatcher from also redirecting.
const dispatchOpts = { ...rest } // Stop sub dispatcher from also redirecting.
const redirectHandler = new RedirectHandler(dispatch, maxRedirections, dispatchOpts, handler)
return dispatch(dispatchOpts, redirectHandler)
}
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 @@

> undici@7.11.0 build:wasm
> undici@7.12.0 build:wasm
> node build/wasm.js --docker

> docker run --rm --platform=linux/x86_64 --user 1001:118 --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
2 changes: 1 addition & 1 deletion deps/undici/src/lib/util/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function makeCacheKey (opts) {

/**
* @param {Record<string, string[] | string>}
* @return {Record<string, string[] | string>}
* @returns {Record<string, string[] | string>}
*/
function normaliseHeaders (opts) {
let headers
Expand Down
28 changes: 28 additions & 0 deletions deps/undici/src/lib/util/promise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict'

/**
* @template {*} T
* @typedef {Object} DeferredPromise
* @property {Promise<T>} promise
* @property {(value?: T) => void} resolve
* @property {(reason?: any) => void} reject
*/

/**
* @template {*} T
* @returns {DeferredPromise<T>} An object containing a promise and its resolve/reject methods.
*/
function createDeferredPromise () {
let res
let rej
const promise = new Promise((resolve, reject) => {
res = resolve
rej = reject
})

return { promise, resolve: res, reject: rej }
}

module.exports = {
createDeferredPromise
}
Loading
Loading