From 6c8456d61ff60fc96f63f7cdfb003ea0510ce3eb Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Tue, 11 Apr 2023 03:03:42 +0100 Subject: [PATCH] deps: update undici to 5.21.1 PR-URL: https://github.com/nodejs/node/pull/47488 Reviewed-By: Debadree Chatterjee Reviewed-By: Rich Trott --- deps/undici/src/lib/core/symbols.js | 2 +- deps/undici/src/lib/core/util.js | 33 +++++-- deps/undici/src/lib/fetch/constants.js | 8 +- deps/undici/src/lib/fetch/formdata.js | 9 +- deps/undici/src/lib/fetch/index.js | 36 +++++--- deps/undici/src/lib/fetch/request.js | 25 ++++-- deps/undici/src/lib/fetch/response.js | 4 +- deps/undici/src/lib/fetch/util.js | 44 +++++++++- deps/undici/src/package.json | 12 +-- deps/undici/src/types/websocket.d.ts | 1 + deps/undici/undici.js | 114 ++++++++++++++++--------- src/undici_version.h | 2 +- 12 files changed, 196 insertions(+), 94 deletions(-) diff --git a/deps/undici/src/lib/core/symbols.js b/deps/undici/src/lib/core/symbols.js index 6d6b62919e6752..c852107a72af26 100644 --- a/deps/undici/src/lib/core/symbols.js +++ b/deps/undici/src/lib/core/symbols.js @@ -41,7 +41,7 @@ module.exports = { kClient: Symbol('client'), kParser: Symbol('parser'), kOnDestroyed: Symbol('destroy callbacks'), - kPipelining: Symbol('pipelinig'), + kPipelining: Symbol('pipelining'), kSocket: Symbol('socket'), kHostHeader: Symbol('host header'), kConnector: Symbol('connector'), diff --git a/deps/undici/src/lib/core/util.js b/deps/undici/src/lib/core/util.js index ab94bcfe51c8e3..bfee97946cdf93 100644 --- a/deps/undici/src/lib/core/util.js +++ b/deps/undici/src/lib/core/util.js @@ -48,38 +48,38 @@ function parseURL (url) { url = new URL(url) if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError('invalid protocol') + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') } return url } if (!url || typeof url !== 'object') { - throw new InvalidArgumentError('invalid url') + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') } if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) { - throw new InvalidArgumentError('invalid port') + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') } if (url.path != null && typeof url.path !== 'string') { - throw new InvalidArgumentError('invalid path') + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') } if (url.pathname != null && typeof url.pathname !== 'string') { - throw new InvalidArgumentError('invalid pathname') + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') } if (url.hostname != null && typeof url.hostname !== 'string') { - throw new InvalidArgumentError('invalid hostname') + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') } if (url.origin != null && typeof url.origin !== 'string') { - throw new InvalidArgumentError('invalid origin') + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') } if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError('invalid protocol') + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') } if (!(url instanceof URL)) { @@ -409,6 +409,21 @@ function throwIfAborted (signal) { } } +const hasToWellFormed = !!String.prototype.toWellFormed + +/** + * @param {string} val + */ +function toUSVString (val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed() + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val) + } + + return `${val}` +} + const kEnumerableProperty = Object.create(null) kEnumerableProperty.enumerable = true @@ -418,7 +433,7 @@ module.exports = { isDisturbed, isErrored, isReadable, - toUSVString: nodeUtil.toUSVString || ((val) => `${val}`), + toUSVString, isReadableAborted, isBlobLike, parseOrigin, diff --git a/deps/undici/src/lib/fetch/constants.js b/deps/undici/src/lib/fetch/constants.js index bc90a031cde31a..a5294a994fbc45 100644 --- a/deps/undici/src/lib/fetch/constants.js +++ b/deps/undici/src/lib/fetch/constants.js @@ -48,11 +48,17 @@ const requestCache = [ 'only-if-cached' ] +// https://fetch.spec.whatwg.org/#request-body-header-name const requestBodyHeader = [ 'content-encoding', 'content-language', 'content-location', - 'content-type' + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' ] // https://fetch.spec.whatwg.org/#enumdef-requestduplex diff --git a/deps/undici/src/lib/fetch/formdata.js b/deps/undici/src/lib/fetch/formdata.js index a957a80e02af7c..5975e26c1a0803 100644 --- a/deps/undici/src/lib/fetch/formdata.js +++ b/deps/undici/src/lib/fetch/formdata.js @@ -61,14 +61,7 @@ class FormData { // The delete(name) method steps are to remove all entries whose name // is name from this’s entry list. - const next = [] - for (const entry of this[kState]) { - if (entry.name !== name) { - next.push(entry) - } - } - - this[kState] = next + this[kState] = this[kState].filter(entry => entry.name !== name) } get (name) { diff --git a/deps/undici/src/lib/fetch/index.js b/deps/undici/src/lib/fetch/index.js index e3834a7f1c614a..0b2e3394322501 100644 --- a/deps/undici/src/lib/fetch/index.js +++ b/deps/undici/src/lib/fetch/index.js @@ -37,7 +37,10 @@ const { isErrorLike, fullyReadBody, readableStreamClose, - isomorphicEncode + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme } = require('./util') const { kState, kHeaders, kGuard, kRealm, kHeadersCaseInsensitive } = require('./symbols') const assert = require('assert') @@ -272,7 +275,7 @@ function finalizeAndReportTiming (response, initiatorType = 'other') { let cacheState = response.cacheState // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. - if (!/^https?:/.test(originalURL.protocol)) { + if (!urlIsHttpHttpsScheme(originalURL)) { return } @@ -530,10 +533,7 @@ async function mainFetch (fetchParams, recursive = false) { // 3. If request’s local-URLs-only flag is set and request’s current URL is // not local, then set response to a network error. - if ( - request.localURLsOnly && - !/^(about|blob|data):/.test(requestCurrentURL(request).protocol) - ) { + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { response = makeNetworkError('local URLs only') } @@ -623,7 +623,7 @@ async function mainFetch (fetchParams, recursive = false) { } // request’s current URL’s scheme is not an HTTP(S) scheme - if (!/^https?:/.test(requestCurrentURL(request).protocol)) { + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { // Return a network error. return makeNetworkError('URL scheme must be a HTTP(S) scheme') } @@ -1130,7 +1130,7 @@ async function httpRedirectFetch (fetchParams, response) { // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network // error. - if (!/^https?:/.test(locationURL.protocol)) { + if (!urlIsHttpHttpsScheme(locationURL)) { return makeNetworkError('URL scheme must be a HTTP(S) scheme') } @@ -1205,7 +1205,7 @@ async function httpRedirectFetch (fetchParams, response) { // 14. If request’s body is non-null, then set request’s body to the first return // value of safely extracting request’s body’s source. if (request.body != null) { - assert(request.body.source) + assert(request.body.source != null) request.body = safelyExtractBody(request.body.source)[0] } @@ -1399,7 +1399,7 @@ async function httpNetworkOrCacheFetch ( // header if httpRequest’s header list contains that header’s name. // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 if (!httpRequest.headersList.contains('accept-encoding')) { - if (/^https:/.test(requestCurrentURL(httpRequest).protocol)) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate') } else { httpRequest.headersList.append('accept-encoding', 'gzip, deflate') @@ -1845,6 +1845,7 @@ async function httpNetworkFetch ( // 4. Set bytes to the result of handling content codings given // codings and bytes. let bytes + let isFailure try { const { done, value } = await fetchParams.controller.next() @@ -1859,6 +1860,10 @@ async function httpNetworkFetch ( bytes = undefined } else { bytes = err + + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true } } @@ -1878,7 +1883,7 @@ async function httpNetworkFetch ( timingInfo.decodedBodySize += bytes?.byteLength ?? 0 // 6. If bytes is failure, then terminate fetchParams’s controller. - if (isErrorLike(bytes)) { + if (isFailure) { fetchParams.controller.terminate(bytes) return } @@ -1979,7 +1984,9 @@ async function httpNetworkFetch ( const val = headersList[n + 1].toString('latin1') if (key.toLowerCase() === 'content-encoding') { - codings = val.split(',').map((x) => x.trim()) + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()) } else if (key.toLowerCase() === 'location') { location = val } @@ -1998,9 +2005,10 @@ async function httpNetworkFetch ( // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { for (const coding of codings) { - if (/(x-)?gzip/.test(coding)) { + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { decoders.push(zlib.createGunzip()) - } else if (/(x-)?deflate/.test(coding)) { + } else if (coding === 'deflate') { decoders.push(zlib.createInflate()) } else if (coding === 'br') { decoders.push(zlib.createBrotliDecompress()) diff --git a/deps/undici/src/lib/fetch/request.js b/deps/undici/src/lib/fetch/request.js index 080a5d7bfa37d3..32c84bf7e6b262 100644 --- a/deps/undici/src/lib/fetch/request.js +++ b/deps/undici/src/lib/fetch/request.js @@ -34,6 +34,7 @@ const { setMaxListeners, getEventListeners, defaultMaxListeners } = require('eve let TransformStream = globalThis.TransformStream const kInit = Symbol('init') +const kAbortController = Symbol('abortController') const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { signal.removeEventListener('abort', abort) @@ -128,12 +129,12 @@ class Request { } // 10. If init["window"] exists and is non-null, then throw a TypeError. - if (init.window !== undefined && init.window != null) { + if (init.window != null) { throw new TypeError(`'window' option '${window}' must be null`) } // 11. If init["window"] exists, then set window to "no-window". - if (init.window !== undefined) { + if ('window' in init) { window = 'no-window' } @@ -354,12 +355,22 @@ class Request { if (signal.aborted) { ac.abort(signal.reason) } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac + + const acRef = new WeakRef(ac) const abort = function () { - ac.abort(this.reason) + const ac = acRef.deref() + if (ac !== undefined) { + ac.abort(this.reason) + } } // Third-party AbortControllers may not work with these. - // See https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619 + // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. try { if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { setMaxListeners(100, signal) @@ -367,7 +378,7 @@ class Request { } catch {} signal.addEventListener('abort', abort, { once: true }) - requestFinalizer.register(this, { signal, abort }) + requestFinalizer.register(ac, { signal, abort }) } } @@ -427,7 +438,7 @@ class Request { // non-null, and request’s method is `GET` or `HEAD`, then throw a // TypeError. if ( - ((init.body !== undefined && init.body != null) || inputBody != null) && + (init.body != null || inputBody != null) && (request.method === 'GET' || request.method === 'HEAD') ) { throw new TypeError('Request with GET/HEAD method cannot have body.') @@ -437,7 +448,7 @@ class Request { let initBody = null // 36. If init["body"] exists and is non-null, then: - if (init.body !== undefined && init.body != null) { + if (init.body != null) { // 1. Let Content-Type be null. // 2. Set initBody and Content-Type to the result of extracting // init["body"], with keepalive set to request’s keepalive. diff --git a/deps/undici/src/lib/fetch/response.js b/deps/undici/src/lib/fetch/response.js index 09732114e7ae00..ff06bfb47d024f 100644 --- a/deps/undici/src/lib/fetch/response.js +++ b/deps/undici/src/lib/fetch/response.js @@ -348,9 +348,7 @@ function makeNetworkError (reason) { status: 0, error: isError ? reason - : new Error(reason ? String(reason) : reason, { - cause: isError ? reason : undefined - }), + : new Error(reason ? String(reason) : reason), aborted: reason && reason.name === 'AbortError' }) } diff --git a/deps/undici/src/lib/fetch/util.js b/deps/undici/src/lib/fetch/util.js index 2d8977f17baaae..4e44d9012af23a 100644 --- a/deps/undici/src/lib/fetch/util.js +++ b/deps/undici/src/lib/fetch/util.js @@ -64,7 +64,7 @@ function requestBadPort (request) { // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, // then return blocked. - if (/^https?:/.test(url.protocol) && badPorts.includes(url.port)) { + if (urlIsHttpHttpsScheme(url) && badPorts.includes(url.port)) { return 'blocked' } @@ -285,7 +285,7 @@ function appendRequestOriginHeader (request) { case 'strict-origin': case 'strict-origin-when-cross-origin': // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`. - if (/^https:/.test(request.origin) && !/^https:/.test(requestCurrentURL(request))) { + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { serializedOrigin = null } break @@ -944,6 +944,41 @@ async function readAllBytes (reader, successSteps, failureSteps) { } } +/** + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' +} + +/** + * @param {string|URL} url + */ +function urlHasHttpsScheme (url) { + if (typeof url === 'string') { + return url.startsWith('https:') + } + + return url.protocol === 'https:' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url + */ +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'http:' || protocol === 'https:' +} + /** * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. */ @@ -988,5 +1023,8 @@ module.exports = { isReadableStreamLike, readableStreamClose, isomorphicEncode, - isomorphicDecode + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme } diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index 39be1736f065d2..79aa9b2758cb4a 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "5.21.0", + "version": "5.21.1", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { @@ -49,7 +49,7 @@ "test": "npm run test:tap && npm run test:node-fetch && npm run test:fetch && npm run test:cookies && npm run test:wpt && npm run test:websocket && npm run test:jest && tsd", "test:cookies": "node scripts/verifyVersion 16 || tap test/cookie/*.js", "test:node-fetch": "node scripts/verifyVersion.js 16 || mocha test/node-fetch", - "test:fetch": "node scripts/verifyVersion.js 16 || (npm run build:node && tap test/fetch/*.js && tap test/webidl/*.js)", + "test:fetch": "node scripts/verifyVersion.js 16 || (npm run build:node && tap --expose-gc test/fetch/*.js && tap test/webidl/*.js)", "test:jest": "node scripts/verifyVersion.js 14 || jest", "test:tap": "tap test/*.js test/diagnostics-channel/*.js", "test:tdd": "tap test/*.js test/diagnostics-channel/*.js -w", @@ -75,7 +75,7 @@ "chai-as-promised": "^7.1.1", "chai-iterator": "^3.0.2", "chai-string": "^1.5.0", - "concurrently": "^7.1.0", + "concurrently": "^8.0.1", "cronometro": "^1.0.5", "delay": "^5.0.0", "dns-packet": "^5.4.0", @@ -98,9 +98,9 @@ "standard": "^17.0.0", "table": "^6.8.0", "tap": "^16.1.0", - "tsd": "^0.25.0", - "typescript": "^4.9.5", - "wait-on": "^6.0.0", + "tsd": "^0.27.0", + "typescript": "^5.0.2", + "wait-on": "^7.0.1", "ws": "^8.11.0" }, "engines": { diff --git a/deps/undici/src/types/websocket.d.ts b/deps/undici/src/types/websocket.d.ts index dadd8013c1e1c2..7524cbda6c4e44 100644 --- a/deps/undici/src/types/websocket.d.ts +++ b/deps/undici/src/types/websocket.d.ts @@ -1,5 +1,6 @@ /// +import type { Blob } from 'buffer' import type { MessagePort } from 'worker_threads' import { EventTarget, diff --git a/deps/undici/undici.js b/deps/undici/undici.js index cccf3f10431455..105d7a83fadda8 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -50,7 +50,7 @@ var require_symbols = __commonJS({ kClient: Symbol("client"), kParser: Symbol("parser"), kOnDestroyed: Symbol("destroy callbacks"), - kPipelining: Symbol("pipelinig"), + kPipelining: Symbol("pipelining"), kSocket: Symbol("socket"), kHostHeader: Symbol("host header"), kConnector: Symbol("connector"), @@ -319,30 +319,30 @@ var require_util = __commonJS({ if (typeof url === "string") { url = new URL(url); if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError("invalid protocol"); + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); } return url; } if (!url || typeof url !== "object") { - throw new InvalidArgumentError("invalid url"); + throw new InvalidArgumentError("Invalid URL: The URL argument must be a non-null object."); } if (url.port != null && url.port !== "" && !Number.isFinite(parseInt(url.port))) { - throw new InvalidArgumentError("invalid port"); + throw new InvalidArgumentError("Invalid URL: port must be a valid integer or a string representation of an integer."); } if (url.path != null && typeof url.path !== "string") { - throw new InvalidArgumentError("invalid path"); + throw new InvalidArgumentError("Invalid URL path: the path must be a string or null/undefined."); } if (url.pathname != null && typeof url.pathname !== "string") { - throw new InvalidArgumentError("invalid pathname"); + throw new InvalidArgumentError("Invalid URL pathname: the pathname must be a string or null/undefined."); } if (url.hostname != null && typeof url.hostname !== "string") { - throw new InvalidArgumentError("invalid hostname"); + throw new InvalidArgumentError("Invalid URL hostname: the hostname must be a string or null/undefined."); } if (url.origin != null && typeof url.origin !== "string") { - throw new InvalidArgumentError("invalid origin"); + throw new InvalidArgumentError("Invalid URL origin: the origin must be a string or null/undefined."); } if (!/^https?:/.test(url.origin || url.protocol)) { - throw new InvalidArgumentError("invalid protocol"); + throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); } if (!(url instanceof URL)) { const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; @@ -570,6 +570,15 @@ var require_util = __commonJS({ } } } + var hasToWellFormed = !!String.prototype.toWellFormed; + function toUSVString(val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed(); + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val); + } + return `${val}`; + } var kEnumerableProperty = /* @__PURE__ */ Object.create(null); kEnumerableProperty.enumerable = true; module2.exports = { @@ -578,7 +587,7 @@ var require_util = __commonJS({ isDisturbed, isErrored, isReadable, - toUSVString: nodeUtil.toUSVString || ((val) => `${val}`), + toUSVString, isReadableAborted, isBlobLike, parseOrigin, @@ -725,7 +734,8 @@ var require_constants = __commonJS({ "content-encoding", "content-language", "content-location", - "content-type" + "content-type", + "content-length" ]; var requestDuplex = [ "half" @@ -863,7 +873,7 @@ var require_util2 = __commonJS({ } function requestBadPort(request) { const url = requestCurrentURL(request); - if (/^https?:/.test(url.protocol) && badPorts.includes(url.port)) { + if (urlIsHttpHttpsScheme(url) && badPorts.includes(url.port)) { return "blocked"; } return "allowed"; @@ -955,7 +965,7 @@ var require_util2 = __commonJS({ case "no-referrer-when-downgrade": case "strict-origin": case "strict-origin-when-cross-origin": - if (/^https:/.test(request.origin) && !/^https:/.test(requestCurrentURL(request))) { + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { serializedOrigin = null; } break; @@ -1272,6 +1282,22 @@ var require_util2 = __commonJS({ byteLength += chunk.length; } } + function urlIsLocal(url) { + assert("protocol" in url); + const protocol = url.protocol; + return protocol === "about:" || protocol === "blob:" || protocol === "data:"; + } + function urlHasHttpsScheme(url) { + if (typeof url === "string") { + return url.startsWith("https:"); + } + return url.protocol === "https:"; + } + function urlIsHttpHttpsScheme(url) { + assert("protocol" in url); + const protocol = url.protocol; + return protocol === "http:" || protocol === "https:"; + } var hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)); module2.exports = { isAborted, @@ -1312,7 +1338,10 @@ var require_util2 = __commonJS({ isReadableStreamLike, readableStreamClose, isomorphicEncode, - isomorphicDecode + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme }; } }); @@ -6122,13 +6151,7 @@ var require_formdata = __commonJS({ webidl.brandCheck(this, FormData); webidl.argumentLengthCheck(arguments, 1, { header: "FormData.delete" }); name = webidl.converters.USVString(name); - const next = []; - for (const entry of this[kState]) { - if (entry.name !== name) { - next.push(entry); - } - } - this[kState] = next; + this[kState] = this[kState].filter((entry) => entry.name !== name); } get(name) { webidl.brandCheck(this, FormData); @@ -6799,9 +6822,7 @@ var require_response = __commonJS({ return makeResponse({ type: "error", status: 0, - error: isError ? reason : new Error(reason ? String(reason) : reason, { - cause: isError ? reason : void 0 - }), + error: isError ? reason : new Error(reason ? String(reason) : reason), aborted: reason && reason.name === "AbortError" }); } @@ -7011,6 +7032,7 @@ var require_request = __commonJS({ var { setMaxListeners, getEventListeners, defaultMaxListeners } = require("events"); var TransformStream = globalThis.TransformStream; var kInit = Symbol("init"); + var kAbortController = Symbol("abortController"); var requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { signal.removeEventListener("abort", abort); }); @@ -7057,10 +7079,10 @@ var require_request = __commonJS({ if (request.window?.constructor?.name === "EnvironmentSettingsObject" && sameOrigin(request.window, origin)) { window = request.window; } - if (init.window !== void 0 && init.window != null) { + if (init.window != null) { throw new TypeError(`'window' option '${window}' must be null`); } - if (init.window !== void 0) { + if ("window" in init) { window = "no-window"; } request = makeRequest({ @@ -7170,8 +7192,13 @@ var require_request = __commonJS({ if (signal.aborted) { ac.abort(signal.reason); } else { + this[kAbortController] = ac; + const acRef = new WeakRef(ac); const abort = function() { - ac.abort(this.reason); + const ac2 = acRef.deref(); + if (ac2 !== void 0) { + ac2.abort(this.reason); + } }; try { if (getEventListeners(signal, "abort").length >= defaultMaxListeners) { @@ -7180,7 +7207,7 @@ var require_request = __commonJS({ } catch { } signal.addEventListener("abort", abort, { once: true }); - requestFinalizer.register(this, { signal, abort }); + requestFinalizer.register(ac, { signal, abort }); } } this[kHeaders] = new Headers(); @@ -7208,11 +7235,11 @@ var require_request = __commonJS({ } } const inputBody = input instanceof Request ? input[kState].body : null; - if ((init.body !== void 0 && init.body != null || inputBody != null) && (request.method === "GET" || request.method === "HEAD")) { + if ((init.body != null || inputBody != null) && (request.method === "GET" || request.method === "HEAD")) { throw new TypeError("Request with GET/HEAD method cannot have body."); } let initBody = null; - if (init.body !== void 0 && init.body != null) { + if (init.body != null) { const [extractedBody, contentType] = extractBody(init.body, request.keepalive); initBody = extractedBody; if (contentType && !this[kHeaders][kHeadersList].contains("content-type")) { @@ -10536,7 +10563,10 @@ var require_fetch = __commonJS({ isErrorLike, fullyReadBody, readableStreamClose, - isomorphicEncode + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme } = require_util2(); var { kState, kHeaders, kGuard, kRealm, kHeadersCaseInsensitive } = require_symbols2(); var assert = require("assert"); @@ -10659,7 +10689,7 @@ var require_fetch = __commonJS({ const originalURL = response.urlList[0]; let timingInfo = response.timingInfo; let cacheState = response.cacheState; - if (!/^https?:/.test(originalURL.protocol)) { + if (!urlIsHttpHttpsScheme(originalURL)) { return; } if (timingInfo === null) { @@ -10771,7 +10801,7 @@ var require_fetch = __commonJS({ async function mainFetch(fetchParams, recursive = false) { const request = fetchParams.request; let response = null; - if (request.localURLsOnly && !/^(about|blob|data):/.test(requestCurrentURL(request).protocol)) { + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { response = makeNetworkError("local URLs only"); } tryUpgradeRequestToAPotentiallyTrustworthyURL(request); @@ -10801,7 +10831,7 @@ var require_fetch = __commonJS({ request.responseTainting = "opaque"; return await schemeFetch(fetchParams); } - if (!/^https?:/.test(requestCurrentURL(request).protocol)) { + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { return makeNetworkError("URL scheme must be a HTTP(S) scheme"); } request.responseTainting = "cors"; @@ -11025,7 +11055,7 @@ var require_fetch = __commonJS({ } catch (err) { return makeNetworkError(err); } - if (!/^https?:/.test(locationURL.protocol)) { + if (!urlIsHttpHttpsScheme(locationURL)) { return makeNetworkError("URL scheme must be a HTTP(S) scheme"); } if (request.redirectCount === 20) { @@ -11052,7 +11082,7 @@ var require_fetch = __commonJS({ request.headersList.delete("authorization"); } if (request.body != null) { - assert(request.body.source); + assert(request.body.source != null); request.body = safelyExtractBody(request.body.source)[0]; } const timingInfo = fetchParams.timingInfo; @@ -11119,7 +11149,7 @@ var require_fetch = __commonJS({ httpRequest.headersList.append("accept-encoding", "identity"); } if (!httpRequest.headersList.contains("accept-encoding")) { - if (/^https:/.test(requestCurrentURL(httpRequest).protocol)) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { httpRequest.headersList.append("accept-encoding", "br, gzip, deflate"); } else { httpRequest.headersList.append("accept-encoding", "gzip, deflate"); @@ -11279,6 +11309,7 @@ var require_fetch = __commonJS({ fetchParams.controller.resume = async () => { while (true) { let bytes; + let isFailure; try { const { done, value } = await fetchParams.controller.next(); if (isAborted(fetchParams)) { @@ -11290,6 +11321,7 @@ var require_fetch = __commonJS({ bytes = void 0; } else { bytes = err; + isFailure = true; } } if (bytes === void 0) { @@ -11298,7 +11330,7 @@ var require_fetch = __commonJS({ return; } timingInfo.decodedBodySize += bytes?.byteLength ?? 0; - if (isErrorLike(bytes)) { + if (isFailure) { fetchParams.controller.terminate(bytes); return; } @@ -11362,7 +11394,7 @@ var require_fetch = __commonJS({ const key = headersList[n + 0].toString("latin1"); const val = headersList[n + 1].toString("latin1"); if (key.toLowerCase() === "content-encoding") { - codings = val.split(",").map((x) => x.trim()); + codings = val.toLowerCase().split(",").map((x) => x.trim()); } else if (key.toLowerCase() === "location") { location = val; } @@ -11373,9 +11405,9 @@ var require_fetch = __commonJS({ const willFollow = request.redirect === "follow" && location && redirectStatus.includes(status); if (request.method !== "HEAD" && request.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { for (const coding of codings) { - if (/(x-)?gzip/.test(coding)) { + if (coding === "x-gzip" || coding === "gzip") { decoders.push(zlib.createGunzip()); - } else if (/(x-)?deflate/.test(coding)) { + } else if (coding === "deflate") { decoders.push(zlib.createInflate()); } else if (coding === "br") { decoders.push(zlib.createBrotliDecompress()); diff --git a/src/undici_version.h b/src/undici_version.h index 6ef1d2afc63371..84fcd207a4481a 100644 --- a/src/undici_version.h +++ b/src/undici_version.h @@ -2,5 +2,5 @@ // Refer to tools/update-undici.sh #ifndef SRC_UNDICI_VERSION_H_ #define SRC_UNDICI_VERSION_H_ -#define UNDICI_VERSION "5.21.0" +#define UNDICI_VERSION "5.21.1" #endif // SRC_UNDICI_VERSION_H_