From e70bd47da986741c0f34fdade41cfc47322867ab Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Thu, 22 Aug 2024 12:08:49 -0400 Subject: [PATCH] deps: update undici to 6.19.8 PR-URL: https://github.com/nodejs/node/pull/54456 Reviewed-By: Marco Ippolito Reviewed-By: Matteo Collina --- deps/undici/src/CONTRIBUTING.md | 1 + deps/undici/src/build/wasm.js | 7 +- .../src/lib/dispatcher/balanced-pool.js | 25 ++++- deps/undici/src/lib/llhttp/wasm_build_env.txt | 4 +- deps/undici/src/lib/web/fetch/body.js | 32 ++++++- deps/undici/src/lib/web/fetch/request.js | 8 +- deps/undici/src/lib/web/fetch/response.js | 23 +---- deps/undici/src/package-lock.json | 95 ++++++++++++++----- deps/undici/src/package.json | 2 +- deps/undici/undici.js | 60 ++++++------ src/undici_version.h | 2 +- 11 files changed, 172 insertions(+), 87 deletions(-) diff --git a/deps/undici/src/CONTRIBUTING.md b/deps/undici/src/CONTRIBUTING.md index 6b6c01d2264e33..68c9b977f1a862 100644 --- a/deps/undici/src/CONTRIBUTING.md +++ b/deps/undici/src/CONTRIBUTING.md @@ -159,6 +159,7 @@ an unbundled version instead of bundling one in `libnode.so`. To enable this, pass `EXTERNAL_PATH=/path/to/global/node_modules/undici` to `build/wasm.js`. Pass this path with `loader.js` appended to `--shared-builtin-undici/undici-path` in Node.js's `configure.py`. If building on a non-Alpine Linux distribution, you may need to also set the `WASM_CC`, `WASM_CFLAGS`, `WASM_LDFLAGS` and `WASM_LDLIBS` environment variables before running `build/wasm.js`. +Similarly, you can set the `WASM_OPT` environment variable to utilize your own `wasm-opt` optimizer. ### Benchmarks diff --git a/deps/undici/src/build/wasm.js b/deps/undici/src/build/wasm.js index 2f65c0e1d74159..1880ce3dfe4a4c 100644 --- a/deps/undici/src/build/wasm.js +++ b/deps/undici/src/build/wasm.js @@ -14,6 +14,7 @@ const WASM_CC = process.env.WASM_CC || 'clang' let WASM_CFLAGS = process.env.WASM_CFLAGS || '--sysroot=/usr/share/wasi-sysroot -target wasm32-unknown-wasi' let WASM_LDFLAGS = process.env.WASM_LDFLAGS || '' const WASM_LDLIBS = process.env.WASM_LDLIBS || '' +const WASM_OPT = process.env.WASM_OPT || './wasm-opt' // For compatibility with Node.js' `configure --shared-builtin-undici/undici-path ...` const EXTERNAL_PATH = process.env.EXTERNAL_PATH @@ -77,7 +78,7 @@ const hasApk = (function () { try { execSync('command -v apk'); return true } catch (error) { return false } })() const hasOptimizer = (function () { - try { execSync('./wasm-opt --version'); return true } catch (error) { return false } + try { execSync(`${WASM_OPT} --version`); return true } catch (error) { return false } })() if (hasApk) { // Gather information about the tools used for the build @@ -97,7 +98,7 @@ ${join(WASM_SRC, 'src')}/*.c \ ${WASM_LDLIBS}`, { stdio: 'inherit' }) if (hasOptimizer) { - execSync(`./wasm-opt ${WASM_OPT_FLAGS} -o ${join(WASM_OUT, 'llhttp.wasm')} ${join(WASM_OUT, 'llhttp.wasm')}`, { stdio: 'inherit' }) + execSync(`${WASM_OPT} ${WASM_OPT_FLAGS} -o ${join(WASM_OUT, 'llhttp.wasm')} ${join(WASM_OUT, 'llhttp.wasm')}`, { stdio: 'inherit' }) } writeWasmChunk('llhttp.wasm', 'llhttp-wasm.js') @@ -109,7 +110,7 @@ ${join(WASM_SRC, 'src')}/*.c \ ${WASM_LDLIBS}`, { stdio: 'inherit' }) if (hasOptimizer) { - execSync(`./wasm-opt ${WASM_OPT_FLAGS} --enable-simd -o ${join(WASM_OUT, 'llhttp_simd.wasm')} ${join(WASM_OUT, 'llhttp_simd.wasm')}`, { stdio: 'inherit' }) + execSync(`${WASM_OPT} ${WASM_OPT_FLAGS} --enable-simd -o ${join(WASM_OUT, 'llhttp_simd.wasm')} ${join(WASM_OUT, 'llhttp_simd.wasm')}`, { stdio: 'inherit' }) } writeWasmChunk('llhttp_simd.wasm', 'llhttp_simd-wasm.js') diff --git a/deps/undici/src/lib/dispatcher/balanced-pool.js b/deps/undici/src/lib/dispatcher/balanced-pool.js index 15a7e7b5879761..1e2de289cb73fa 100644 --- a/deps/undici/src/lib/dispatcher/balanced-pool.js +++ b/deps/undici/src/lib/dispatcher/balanced-pool.js @@ -25,9 +25,23 @@ const kWeight = Symbol('kWeight') const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') const kErrorPenalty = Symbol('kErrorPenalty') +/** + * Calculate the greatest common divisor of two numbers by + * using the Euclidean algorithm. + * + * @param {number} a + * @param {number} b + * @returns {number} + */ function getGreatestCommonDivisor (a, b) { - if (b === 0) return a - return getGreatestCommonDivisor(b, a % b) + if (a === 0) return b + + while (b !== 0) { + const t = b + b = a % b + a = t + } + return a } function defaultFactory (origin, opts) { @@ -105,7 +119,12 @@ class BalancedPool extends PoolBase { } _updateBalancedPoolStats () { - this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0) + let result = 0 + for (let i = 0; i < this[kClients].length; i++) { + result = getGreatestCommonDivisor(this[kClients][i][kWeight], result) + } + + this[kGreatestCommonDivisor] = result } removeUpstream (upstream) { diff --git a/deps/undici/src/lib/llhttp/wasm_build_env.txt b/deps/undici/src/lib/llhttp/wasm_build_env.txt index cef6c799b6a14e..88676cd7cd04d1 100644 --- a/deps/undici/src/lib/llhttp/wasm_build_env.txt +++ b/deps/undici/src/lib/llhttp/wasm_build_env.txt @@ -1,12 +1,12 @@ -> undici@6.19.7 prebuild:wasm +> undici@6.19.8 prebuild:wasm > node build/wasm.js --prebuild > 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 -> undici@6.19.7 build:wasm +> undici@6.19.8 build:wasm > node build/wasm.js --docker > 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 diff --git a/deps/undici/src/lib/web/fetch/body.js b/deps/undici/src/lib/web/fetch/body.js index 55718ac7c8165d..464e7b50e5ced7 100644 --- a/deps/undici/src/lib/web/fetch/body.js +++ b/deps/undici/src/lib/web/fetch/body.js @@ -16,12 +16,25 @@ const { kState } = require('./symbols') const { webidl } = require('./webidl') const { Blob } = require('node:buffer') const assert = require('node:assert') -const { isErrored } = require('../../core/util') +const { isErrored, isDisturbed } = require('node:stream') const { isArrayBuffer } = require('node:util/types') const { serializeAMimeType } = require('./data-url') const { multipartFormDataParser } = require('./formdata-parser') const textEncoder = new TextEncoder() +function noop () {} + +const hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf('v18') !== 0 +let streamRegistry + +if (hasFinalizationRegistry) { + streamRegistry = new FinalizationRegistry((weakRef) => { + const stream = weakRef.deref() + if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { + stream.cancel('Response object has been garbage collected').catch(noop) + } + }) +} // https://fetch.spec.whatwg.org/#concept-bodyinit-extract function extractBody (object, keepalive = false) { @@ -264,7 +277,7 @@ function safelyExtractBody (object, keepalive = false) { return extractBody(object, keepalive) } -function cloneBody (body) { +function cloneBody (instance, body) { // To clone a body body, run these steps: // https://fetch.spec.whatwg.org/#concept-body-clone @@ -272,6 +285,10 @@ function cloneBody (body) { // 1. Let « out1, out2 » be the result of teeing body’s stream. const [out1, out2] = body.stream.tee() + if (hasFinalizationRegistry) { + streamRegistry.register(instance, new WeakRef(out1)) + } + // 2. Set body’s stream to out1. body.stream = out1 @@ -414,7 +431,7 @@ async function consumeBody (object, convertBytesToJSValue, instance) { // 1. If object is unusable, then return a promise rejected // with a TypeError. - if (bodyUnusable(object[kState].body)) { + if (bodyUnusable(object)) { throw new TypeError('Body is unusable: Body has already been read') } @@ -454,7 +471,9 @@ async function consumeBody (object, convertBytesToJSValue, instance) { } // https://fetch.spec.whatwg.org/#body-unusable -function bodyUnusable (body) { +function bodyUnusable (object) { + const body = object[kState].body + // An object including the Body interface mixin is // said to be unusable if its body is non-null and // its body’s stream is disturbed or locked. @@ -496,5 +515,8 @@ module.exports = { extractBody, safelyExtractBody, cloneBody, - mixinBody + mixinBody, + streamRegistry, + hasFinalizationRegistry, + bodyUnusable } diff --git a/deps/undici/src/lib/web/fetch/request.js b/deps/undici/src/lib/web/fetch/request.js index bc436aa9705e34..542ea7fb28a0ed 100644 --- a/deps/undici/src/lib/web/fetch/request.js +++ b/deps/undici/src/lib/web/fetch/request.js @@ -2,7 +2,7 @@ 'use strict' -const { extractBody, mixinBody, cloneBody } = require('./body') +const { extractBody, mixinBody, cloneBody, bodyUnusable } = require('./body') const { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require('./headers') const { FinalizationRegistry } = require('./dispatcher-weakref')() const util = require('../../core/util') @@ -557,7 +557,7 @@ class Request { // 40. If initBody is null and inputBody is non-null, then: if (initBody == null && inputBody != null) { // 1. If input is unusable, then throw a TypeError. - if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + if (bodyUnusable(input)) { throw new TypeError( 'Cannot construct a Request with a Request object that has already been used.' ) @@ -759,7 +759,7 @@ class Request { webidl.brandCheck(this, Request) // 1. If this is unusable, then throw a TypeError. - if (this.bodyUsed || this.body?.locked) { + if (bodyUnusable(this)) { throw new TypeError('unusable') } @@ -877,7 +877,7 @@ function cloneRequest (request) { // 2. If request’s body is non-null, set newRequest’s body to the // result of cloning request’s body. if (request.body != null) { - newRequest.body = cloneBody(request.body) + newRequest.body = cloneBody(newRequest, request.body) } // 3. Return newRequest. diff --git a/deps/undici/src/lib/web/fetch/response.js b/deps/undici/src/lib/web/fetch/response.js index 603410a4a63e4a..155dbadd1adc7f 100644 --- a/deps/undici/src/lib/web/fetch/response.js +++ b/deps/undici/src/lib/web/fetch/response.js @@ -1,7 +1,7 @@ 'use strict' const { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require('./headers') -const { extractBody, cloneBody, mixinBody } = require('./body') +const { extractBody, cloneBody, mixinBody, hasFinalizationRegistry, streamRegistry, bodyUnusable } = require('./body') const util = require('../../core/util') const nodeUtil = require('node:util') const { kEnumerableProperty } = util @@ -26,24 +26,9 @@ const { URLSerializer } = require('./data-url') const { kConstruct } = require('../../core/symbols') const assert = require('node:assert') const { types } = require('node:util') -const { isDisturbed, isErrored } = require('node:stream') const textEncoder = new TextEncoder('utf-8') -const hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf('v18') !== 0 -let registry - -if (hasFinalizationRegistry) { - registry = new FinalizationRegistry((weakRef) => { - const stream = weakRef.deref() - if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { - stream.cancel('Response object has been garbage collected').catch(noop) - } - }) -} - -function noop () {} - // https://fetch.spec.whatwg.org/#response-class class Response { // Creates network error Response. @@ -244,7 +229,7 @@ class Response { webidl.brandCheck(this, Response) // 1. If this is unusable, then throw a TypeError. - if (this.bodyUsed || this.body?.locked) { + if (bodyUnusable(this)) { throw webidl.errors.exception({ header: 'Response.clone', message: 'Body has already been consumed.' @@ -327,7 +312,7 @@ function cloneResponse (response) { // 3. If response’s body is non-null, then set newResponse’s body to the // result of cloning response’s body. if (response.body != null) { - newResponse.body = cloneBody(response.body) + newResponse.body = cloneBody(newResponse, response.body) } // 4. Return newResponse. @@ -532,7 +517,7 @@ function fromInnerResponse (innerResponse, guard) { // a primitive or an object, even undefined. If the held value is an object, the registry keeps // a strong reference to it (so it can pass it to the cleanup callback later). Reworded from // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry - registry.register(response, new WeakRef(innerResponse.body.stream)) + streamRegistry.register(response, new WeakRef(innerResponse.body.stream)) } return response diff --git a/deps/undici/src/package-lock.json b/deps/undici/src/package-lock.json index 5c3f78dec80f4b..67e74b4e445fee 100644 --- a/deps/undici/src/package-lock.json +++ b/deps/undici/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "undici", - "version": "6.19.7", + "version": "6.19.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "undici", - "version": "6.19.7", + "version": "6.19.8", "license": "MIT", "devDependencies": { "@fastify/busboy": "2.1.1", @@ -50,9 +50,9 @@ } }, "node_modules/@actions/http-client": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", - "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.2.tgz", + "integrity": "sha512-2TvX5LskKQzDDQI+bobIDGAjkn0NJiQlg4MTrKnZ8HfQ7nDEUbtJ1ytxPDb2bfk3Hr2XD99X8oAJISAmIoiSAQ==", "dev": true, "license": "MIT", "dependencies": { @@ -412,6 +412,38 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -532,6 +564,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -1616,9 +1664,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.43", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.43.tgz", - "integrity": "sha512-Mw/YlgXnyJdEwLoFv2dpuJaDFriX+Pc+0qOBJ57jC1H6cDxIj2xc5yUrdtArDVG0m+KV6622a4p2tenEqB3C/g==", + "version": "18.19.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.45.tgz", + "integrity": "sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==", "dev": true, "license": "MIT", "dependencies": { @@ -2257,24 +2305,27 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "license": "MIT", "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3202,9 +3253,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz", - "integrity": "sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.11.tgz", + "integrity": "sha512-R1CccCDYqndR25CaXFd6hp/u9RaaMcftMkphmvuepXr5b1vfLkRml6aWVeBhXJ7rbevHkKEMJtz8XqPf7ffmew==", "dev": true, "license": "ISC" }, @@ -5036,9 +5087,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index 86fbc7e26b36f2..bf777b24a2b90a 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "6.19.7", + "version": "6.19.8", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/deps/undici/undici.js b/deps/undici/undici.js index b2e064facf2a64..acbece91687872 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -5210,11 +5210,24 @@ var require_body = __commonJS({ var { webidl } = require_webidl(); var { Blob: Blob2 } = require("node:buffer"); var assert = require("node:assert"); - var { isErrored } = require_util(); + var { isErrored, isDisturbed } = require("node:stream"); var { isArrayBuffer } = require("node:util/types"); var { serializeAMimeType } = require_data_url(); var { multipartFormDataParser } = require_formdata_parser(); var textEncoder = new TextEncoder(); + function noop() { + } + __name(noop, "noop"); + var hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf("v18") !== 0; + var streamRegistry; + if (hasFinalizationRegistry) { + streamRegistry = new FinalizationRegistry((weakRef) => { + const stream = weakRef.deref(); + if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { + stream.cancel("Response object has been garbage collected").catch(noop); + } + }); + } function extractBody(object, keepalive = false) { let stream = null; if (object instanceof ReadableStream) { @@ -5359,8 +5372,11 @@ Content-Type: ${value.type || "application/octet-stream"}\r return extractBody(object, keepalive); } __name(safelyExtractBody, "safelyExtractBody"); - function cloneBody(body) { + function cloneBody(instance, body) { const [out1, out2] = body.stream.tee(); + if (hasFinalizationRegistry) { + streamRegistry.register(instance, new WeakRef(out1)); + } body.stream = out1; return { stream: out2, @@ -5443,7 +5459,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r __name(mixinBody, "mixinBody"); async function consumeBody(object, convertBytesToJSValue, instance) { webidl.brandCheck(object, instance); - if (bodyUnusable(object[kState].body)) { + if (bodyUnusable(object)) { throw new TypeError("Body is unusable: Body has already been read"); } throwIfAborted(object[kState]); @@ -5464,7 +5480,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r return promise.promise; } __name(consumeBody, "consumeBody"); - function bodyUnusable(body) { + function bodyUnusable(object) { + const body = object[kState].body; return body != null && (body.stream.locked || util.isDisturbed(body.stream)); } __name(bodyUnusable, "bodyUnusable"); @@ -5485,7 +5502,10 @@ Content-Type: ${value.type || "application/octet-stream"}\r extractBody, safelyExtractBody, cloneBody, - mixinBody + mixinBody, + streamRegistry, + hasFinalizationRegistry, + bodyUnusable }; } }); @@ -8719,7 +8739,7 @@ var require_response = __commonJS({ "lib/web/fetch/response.js"(exports2, module2) { "use strict"; var { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require_headers(); - var { extractBody, cloneBody, mixinBody } = require_body(); + var { extractBody, cloneBody, mixinBody, hasFinalizationRegistry, streamRegistry, bodyUnusable } = require_body(); var util = require_util(); var nodeUtil = require("node:util"); var { kEnumerableProperty } = util; @@ -8744,21 +8764,7 @@ var require_response = __commonJS({ var { kConstruct } = require_symbols(); var assert = require("node:assert"); var { types } = require("node:util"); - var { isDisturbed, isErrored } = require("node:stream"); var textEncoder = new TextEncoder("utf-8"); - var hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf("v18") !== 0; - var registry; - if (hasFinalizationRegistry) { - registry = new FinalizationRegistry((weakRef) => { - const stream = weakRef.deref(); - if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { - stream.cancel("Response object has been garbage collected").catch(noop); - } - }); - } - function noop() { - } - __name(noop, "noop"); var Response = class _Response { static { __name(this, "Response"); @@ -8873,7 +8879,7 @@ var require_response = __commonJS({ // Returns a clone of response. clone() { webidl.brandCheck(this, _Response); - if (this.bodyUsed || this.body?.locked) { + if (bodyUnusable(this)) { throw webidl.errors.exception({ header: "Response.clone", message: "Body has already been consumed." @@ -8932,7 +8938,7 @@ var require_response = __commonJS({ } const newResponse = makeResponse({ ...response, body: null }); if (response.body != null) { - newResponse.body = cloneBody(response.body); + newResponse.body = cloneBody(newResponse, response.body); } return newResponse; } @@ -9065,7 +9071,7 @@ var require_response = __commonJS({ setHeadersList(response[kHeaders], innerResponse.headersList); setHeadersGuard(response[kHeaders], guard); if (hasFinalizationRegistry && innerResponse.body?.stream) { - registry.register(response, new WeakRef(innerResponse.body.stream)); + streamRegistry.register(response, new WeakRef(innerResponse.body.stream)); } return response; } @@ -9187,7 +9193,7 @@ var require_dispatcher_weakref = __commonJS({ var require_request2 = __commonJS({ "lib/web/fetch/request.js"(exports2, module2) { "use strict"; - var { extractBody, mixinBody, cloneBody } = require_body(); + var { extractBody, mixinBody, cloneBody, bodyUnusable } = require_body(); var { Headers, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require_headers(); var { FinalizationRegistry: FinalizationRegistry2 } = require_dispatcher_weakref()(); var util = require_util(); @@ -9513,7 +9519,7 @@ var require_request2 = __commonJS({ } let finalBody = inputOrInitBody; if (initBody == null && inputBody != null) { - if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + if (bodyUnusable(input)) { throw new TypeError( "Cannot construct a Request with a Request object that has already been used." ); @@ -9648,7 +9654,7 @@ var require_request2 = __commonJS({ // Returns a clone of request. clone() { webidl.brandCheck(this, _Request); - if (this.bodyUsed || this.body?.locked) { + if (bodyUnusable(this)) { throw new TypeError("unusable"); } const clonedRequest = cloneRequest(this[kState]); @@ -9742,7 +9748,7 @@ var require_request2 = __commonJS({ function cloneRequest(request) { const newRequest = makeRequest({ ...request, body: null }); if (request.body != null) { - newRequest.body = cloneBody(request.body); + newRequest.body = cloneBody(newRequest, request.body); } return newRequest; } diff --git a/src/undici_version.h b/src/undici_version.h index ac384500e05a5d..8a50f720dbfd9b 100644 --- a/src/undici_version.h +++ b/src/undici_version.h @@ -2,5 +2,5 @@ // Refer to tools/dep_updaters/update-undici.sh #ifndef SRC_UNDICI_VERSION_H_ #define SRC_UNDICI_VERSION_H_ -#define UNDICI_VERSION "6.19.7" +#define UNDICI_VERSION "6.19.8" #endif // SRC_UNDICI_VERSION_H_