Skip to content

Conversation

pckrishnadas88
Copy link
Contributor

@pckrishnadas88 pckrishnadas88 commented Aug 9, 2025

Replace regex-based hostname normalization with direct string operations, selecting the most performant of three tested approaches:

Performance Hierarchy (http/proxy-config-ipv6-trim.js):

  1. stringOp (chosen implementation):
    • IPv6: 267,922,975 ops/sec (15.5x faster than regex)
    • IPv4: 354,683,255 ops/sec (9.3x faster than regex)
  2. normalize: 205-337M ops/sec
  3. regex: 17-38M ops/sec

Before (regex):

this.hostname = hostname.replace(/^\[|\]$/g, '');
// ~17M ops/sec (IPv6) | ~38M ops/sec (IPv4)

After (optimized):

this.hostname = this.#normalizeHostname(hostname); // Trim off the brackets from IPv6 addresses.
// Private helper method for performance optimization
#normalizeHostname(hostname) {
    return hostname.startsWith('[') && hostname.endsWith(']') ?
      hostname.slice(1, -1) :
      hostname;
}
// ~267M ops/sec (IPv6) | ~354M ops/sec (IPv4)

Implementation Details:

  • Uses direct startsWith('[') && endsWith(']') checks (stringOp)
  • Chosen over alternative implementations after benchmarking
  • Maintains 1:1 behavior with existing regex implementation
  • More efficient for proxy servers handling high connection volumes

Behavior remains identical while being significantly faster.

Verification:

  1. Run benchmarks:
    ./node benchmark/http/proxy-config-ipv6-trim.js

Benefits:

  • Faster proxy configuration for IPv6/IPv4 addresses
  • No behavior changes - purely an optimization
  • Better performance for HTTP servers handling many connections.

Note: This is unrelated to #59375 (approved, awaiting merge).

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/performance

@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Aug 9, 2025
Copy link
Contributor

@Uzlopak Uzlopak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The benchmark is actually wrong. You have to write a benchmark, which uses the effected node code. This is a microbenchmark where you compare the performance of two or three implementations. This is not useful, if you want to determine if there is any performance improvement between two node versions.

@Uzlopak
Copy link
Contributor

Uzlopak commented Aug 9, 2025

Is it even a hotpath?

@Uzlopak
Copy link
Contributor

Uzlopak commented Aug 9, 2025

The benchmark should look like this:

'use strict';
const common = require('../common.js');

// Benchmark configuration
const bench = common.createBenchmark(main, {
  hostname: [
    '[::]',
    '127.0.0.1',
    'localhost',
    'www.example.proxy',
  ],
  n: [1e6]
}, {
  flags: ['--expose-internals'],
});

function main({ hostname, n }) {

  const { parseProxyConfigFromEnv } = require('internal/http');

  const protocol = 'https:';
  const env = {
    https_proxy: `https://${hostname}`,
  }

  // Warmup
  for (let i = 0; i < n; i++) {
    parseProxyConfigFromEnv(env, protocol);
  }

  // // Benchmark
  bench.start();
  for (let i = 0; i < n; i++) {
    parseProxyConfigFromEnv(env, protocol);
  }
  bench.end(n);
}

// // Benchmark
bench.start();
for (let i = 0; i < n; i++) {
parseProxyConfigFromEnv(env, protocol);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a variable outside the loop to store the result of this function and add one assertion after the loop to ensure the returned value is valid

This is necessary to avoid v8 dead code elimination

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@H4ad is this what you suggested?

'use strict';
const common = require('../common.js');
const assert = require('assert');

// Benchmark configuration
const bench = common.createBenchmark(main, {
  hostname: [
    '[::]',
    '127.0.0.1',
    'localhost',
    'www.example.proxy',
  ],
  n: [1e6]
}, {
  flags: ['--expose-internals'],
});

function main({ hostname, n }) {
  const { parseProxyConfigFromEnv } = require('internal/http');

  const protocol = 'https:';
  const env = {
    https_proxy: `https://${hostname}`,
  };

  // Variable to store results outside the loop
  let lastResult;

  // Warmup
  for (let i = 0; i < n; i++) {
    lastResult = parseProxyConfigFromEnv(env, protocol);
  }

  // Expected hostname after parsing (square brackets removed for IPv6)
  const expectedHostname = hostname[0] === '[' ? hostname.slice(1, -1) : hostname;

  // Assertion to ensure the function returns a valid result
  assert(
    lastResult && typeof lastResult === 'object',
    'Invalid proxy config result after warmup'
  );
  assert(
    'hostname' in lastResult,
    'Proxy config result should have hostname property'
  );

  // Benchmark
  bench.start();
  for (let i = 0; i < n; i++) {
    lastResult = parseProxyConfigFromEnv(env, protocol);
  }
  bench.end(n);

  // Final validation
  assert(
    lastResult && typeof lastResult === 'object',
    'Invalid proxy config result after benchmark'
  );
  assert.strictEqual(
    lastResult.hostname,
    expectedHostname,
    `Proxy config hostname should be ${expectedHostname} (got ${lastResult.hostname})`
  );
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pckrishnadas88 That's right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark updated and pushed.

@lemire
Copy link
Member

lemire commented Aug 9, 2025

This looks like a very decent PR. Good work.

@pckrishnadas88
Copy link
Contributor Author

This looks like a very decent PR. Good work.

Thank you for the feedback. Just updated the benchmark as well as suggested by @H4ad

@Uzlopak
Copy link
Contributor

Uzlopak commented Aug 10, 2025

The warm up phase is still excessive. Instead of doing n-iterations it is enough to do 1000 iterations. For the warm up..

@pckrishnadas88
Copy link
Contributor Author

The warm up phase is still excessive. Instead of doing n-iterations it is enough to do 1000 iterations. For the warm up..

PR updated with that change. Thank you for the valuable suggestions.

@joyeecheung
Copy link
Member

joyeecheung commented Aug 10, 2025

Is it even a hotpath?

It's a path only used by http/https clients that are using proxies, and likely only ever called once throughout the lifetime of a Node.js http/https clients as part of the agent initialisation (typically, once per process to initialize the global agent), so...not really. (This path is not used by the server, FWIW).

I would suggest dropping the benchmark, that is a bit of an overkill for a code path like this. We don't do that for every single string operation we do in the initialisations that are usually only run once per application lifecycle.

@Uzlopak
Copy link
Contributor

Uzlopak commented Aug 10, 2025

@joyeecheung
@H4ad
May i interest you in #59426

this.href = proxyUrl; // Full URL of the proxy server.
this.host = host; // Full host including port, e.g. 'localhost:8080'.
this.hostname = hostname.replace(/^\[|\]$/g, ''); // Trim off the brackets from IPv6 addresses.
this.hostname = hostname[0] === '[' ? hostname.slice(1, -1) : hostname; // Trim off the brackets from IPv6 addresses.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change, since the original removes all leading and trailing brackets?

original

'[[[::1]]]' => '::1'

new

// double brackets at the end
'[::1]]' => '[::1]'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope.

aras@aras-HP-ZBook-15-G3:~/workspace/eventsource$ node
Welcome to Node.js v22.18.0.
Type ".help" for more information.
> new URL('http://[[::1]]')
Uncaught TypeError: Invalid URL
    at new URL (node:internal/url:825:25) {
  code: 'ERR_INVALID_URL',
  input: 'http://[[::1]]'
}
> 

@pckrishnadas88
Copy link
Contributor Author

Is it even a hotpath?

It's a path only used by http/https clients that are using proxies, and likely only ever called once throughout the lifetime of a Node.js http/https clients as part of the agent initialisation (typically, once per process to initialize the global agent), so...not really. (This path is not used by the server, FWIW).

I would suggest dropping the benchmark, that is a bit of an overkill for a code path like this. We don't do that for every single string operation we do in the initialisations that are usually only run once per application lifecycle.

I will remove the benchmark and update the PR soon.

@pckrishnadas88
Copy link
Contributor Author

Is it even a hotpath?

It's a path only used by http/https clients that are using proxies, and likely only ever called once throughout the lifetime of a Node.js http/https clients as part of the agent initialisation (typically, once per process to initialize the global agent), so...not really. (This path is not used by the server, FWIW).

I would suggest dropping the benchmark, that is a bit of an overkill for a code path like this. We don't do that for every single string operation we do in the initialisations that are usually only run once per application lifecycle.

Benchmark file removed as suggested.

@pckrishnadas88 pckrishnadas88 requested a review from lemire August 13, 2025 04:58
Copy link

codecov bot commented Aug 13, 2025

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 89.88%. Comparing base (dfee0b1) to head (e0b8723).
⚠️ Report is 238 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/http.js 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #59420      +/-   ##
==========================================
- Coverage   89.89%   89.88%   -0.02%     
==========================================
  Files         656      656              
  Lines      193141   193143       +2     
  Branches    37886    37884       -2     
==========================================
- Hits       173623   173599      -24     
- Misses      12051    12056       +5     
- Partials     7467     7488      +21     
Files with missing lines Coverage Δ
lib/internal/http.js 95.31% <66.66%> (-0.36%) ⬇️

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@Uzlopak Uzlopak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know my vote is irrelevant, but atleast it removes my blocker ;)

@pckrishnadas88
Copy link
Contributor Author

I know my vote is irrelevant, but atleast it removes my blocker ;)

Thank you. Learned a lot from your review.

@lemire lemire added the commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. label Aug 13, 2025
@pckrishnadas88
Copy link
Contributor Author

@lemire The test-macOS (pull_request) job has failed several times (around 35 min mark). The CI failure is from test-debugger-run-after-quit-restart.js on macOS. It looks unrelated to my changes — could this be a flaky test?

Copy link
Member

@tniessen tniessen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @pckrishnadas88. I am +0 on this sort of change.

FWIW, I generally do not recommend alleging concrete measurements of performance gains of such micro-optimizations in commit messages, for a number of reasons. Benchmarking such tiny changes, especially when not on a hot path, across all supported platforms and CPU architectures is tricky, and even if done properly, it may be difficult to claim any particular one numeric factor as the ultimate performance improvement.

@pckrishnadas88
Copy link
Contributor Author

Thanks @pckrishnadas88. I am +0 on this sort of change.

FWIW, I generally do not recommend alleging concrete measurements of performance gains of such micro-optimizations in commit messages, for a number of reasons. Benchmarking such tiny changes, especially when not on a hot path, across all supported platforms and CPU architectures is tricky, and even if done properly, it may be difficult to claim any particular one numeric factor as the ultimate performance improvement.

The benchmark file is removed already as per previous review. I recently started on contributing to Node.js this is my second PR so learning things now. Mistakes are not intentional and happy to correct as per the reviews. Thank you for the detailed explanations.

@joyeecheung
Copy link
Member

joyeecheung commented Aug 14, 2025

I agree with @tniessen - it's better to drop the performance statement in the commit message, because in the case of the code being changed here, that's very likely to be untrue. This code is likely only ever executed once per process, and the optimizing compiler is not likely to touch it. Performance numbers from repeatedly calling it in a loop where the optimizing compiler would kick in are not applicable to the actual use case of this code - it's mostly likely only interpreted.

@joyeecheung
Copy link
Member

Can you squash the commit and amend the commit message? I think something like this would work:

http: trim off brackets from IPv6 addresses with string operations

This is simpler than using regular expressions.

This is simpler than using regular expressions.
@pckrishnadas88 pckrishnadas88 force-pushed the net/proxy-optimize-ipv6-trim branch from 6c5a3f6 to e0b8723 Compare August 19, 2025 04:57
@pckrishnadas88
Copy link
Contributor Author

Can you squash the commit and amend the commit message? I think something like this would work:

http: trim off brackets from IPv6 addresses with string operations

This is simpler than using regular expressions.

This change has been done. Please let me know if anything else is required.

@joyeecheung joyeecheung added the request-ci Add this label to start a Jenkins CI on a PR. label Aug 19, 2025
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 19, 2025
@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@tniessen tniessen changed the title http: optimize IPv6 hostname normalization by 15.5x http: trim off brackets from IPv6 addresses with string operations Aug 19, 2025
@joyeecheung joyeecheung added the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 20, 2025
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 20, 2025
@nodejs-github-bot nodejs-github-bot merged commit 6c215fb into nodejs:main Aug 20, 2025
60 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 6c215fb

@pckrishnadas88
Copy link
Contributor Author

Thanks everyone for the reviews and guidance! I appreciate the time and feedback from all of you in helping this land. 🙏

@pckrishnadas88 pckrishnadas88 deleted the net/proxy-optimize-ipv6-trim branch August 20, 2025 13:27
targos pushed a commit that referenced this pull request Aug 21, 2025
This is simpler than using regular expressions.

PR-URL: #59420
Reviewed-By: Daniel Lemire <daniel@lemire.me>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Aug 28, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [node](https://nodejs.org) ([source](https://github.com/nodejs/node)) | minor | `24.6.0` -> `24.7.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>nodejs/node (node)</summary>

### [`v24.7.0`](https://github.com/nodejs/node/releases/tag/v24.7.0): 2025-08-27, Version 24.7.0 (Current), @&#8203;targos

[Compare Source](nodejs/node@v24.6.0...v24.7.0)

##### Notable Changes

##### Post-Quantum Cryptography in `node:crypto`

OpenSSL 3.5 on 24.x kicked off post-quantum cryptography efforts in Node.js by
allowing use of NIST's post-quantum cryptography standards for future-proofing
applications against quantum computing threats. The following post-quantum
algorithms are now available in `node:crypto`:

- ML-KEM (FIPS 203, Module-Lattice-Based Key-Encapsulation Mechanism Standard) through new `crypto.encapsulate()` and `crypto.decapsulate()` methods.
- ML-DSA (FIPS 204, Module-Lattice-Based Digital Signature Standard) in the existing `crypto.sign()` and `crypto.verify()` methods.

Contributed by Filip Skokan in [#&#8203;59259](nodejs/node#59259) and [#&#8203;59491](nodejs/node#59491).

##### Modern Algorithms in Web Cryptography API

The second substantial [extension to the Web Cryptography API](https://wicg.github.io/webcrypto-modern-algos/)
(`globalThis.crypto.subtle`) was recently accepted for incubation by WICG.
The following algorithms and methods from this extension are now available in
the Node.js Web Cryptography API implementation:

- AES-OCB
- ChaCha20-Poly1305
- ML-DSA
- ML-KEM
- SHA-3
- SHAKE
- `subtle.getPublicKey()`
- `SubtleCrypto.supports()`
- ... with more coming in future releases.

Contributed by Filip Skokan in [#&#8203;59365](nodejs/node#59365), [#&#8203;59569](nodejs/node#59569), [#&#8203;59461](nodejs/node#59461), and [#&#8203;59539](nodejs/node#59539).

##### Node.js execution argument support in single executable applications

The single executable application configuration now supports additional fields
to specify Node.js execution arguments and control how they can be extended when
the application is run.

- `execArgv` takes an array of strings for the execution arguments to be used.
- `execArgvExtension` takes one of the following values:
  - `"none"`: No additional execution arguments are allowed.
  - `"cli"`: Additional execution arguments can be provided via a special command-line flag `--node-options="--flag1 --flag2=value"` at run time.
  - `"env"` (default): Additional execution arguments can be provided via the `NODE_OPTIONS` environment variable at run time.

For example, with the following configuration:

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "execArgv": ["--no-warnings"],
  "execArgvExtension": "cli",
}
```

If the generated single executable application is named `sea`, then running:

```console
sea --node-options="--max-old-space-size=4096" user-arg1 user-arg2
```

Would be equivalent to running:

```console
node --no-warnings --max-old-space-size=4096 /path/to/bundled/script.js user-arg1 user-arg2
```

Contributed by Joyee Cheung in [#&#8203;59314](nodejs/node#59314) and [#&#8203;59560](nodejs/node#59560).

##### Root certificates updated to NSS 3.114

Certificates added:

- TrustAsia TLS ECC Root CA
- TrustAsia TLS RSA Root CA
- SwissSign RSA TLS Root CA 2022 - 1

Certificates removed:

- GlobalSign Root CA
- Entrust.net Premium 2048 Secure Server CA
- Baltimore CyberTrust Root
- Comodo AAA Services root
- XRamp Global CA Root
- Go Daddy Class 2 CA
- Starfield Class 2 CA

##### Other Notable Changes

- \[[`d3afc63c44`](nodejs/node@d3afc63c44)] - **(SEMVER-MINOR)** **crypto**: add argon2() and argon2Sync() methods (Ranieri Althoff) [#&#8203;50353](nodejs/node#50353)
- \[[`6ae202fcdf`](nodejs/node@6ae202fcdf)] - **(SEMVER-MINOR)** **http**: add Agent.agentKeepAliveTimeoutBuffer option (Haram Jeong) [#&#8203;59315](nodejs/node#59315)
- \[[`dafee05358`](nodejs/node@dafee05358)] - **(SEMVER-MINOR)** **http2**: add support for raw header arrays in h2Stream.respond() (Tim Perry) [#&#8203;59455](nodejs/node#59455)
- \[[`8dc6f5b696`](nodejs/node@8dc6f5b696)] - **(SEMVER-MINOR)** **stream**: add brotli support to CompressionStream and DecompressionStream (Matthew Aitken) [#&#8203;59464](nodejs/node#59464)

##### Commits

- \[[`0fa22cbf7c`](nodejs/node@0fa22cbf7c)] - **benchmark**: calibrate config v8/serialize.js (Rafael Gonzaga) [#&#8203;59586](nodejs/node#59586)
- \[[`f5ece45b45`](nodejs/node@f5ece45b45)] - **benchmark**: reduce readfile-permission-enabled config (Rafael Gonzaga) [#&#8203;59589](nodejs/node#59589)
- \[[`8ebd4f4434`](nodejs/node@8ebd4f4434)] - **benchmark**: calibrate length of util.diff (Rafael Gonzaga) [#&#8203;59588](nodejs/node#59588)
- \[[`7dee3ffd14`](nodejs/node@7dee3ffd14)] - **benchmark**: reflect current OpenSSL in crypto key benchmarks (Filip Skokan) [#&#8203;59459](nodejs/node#59459)
- \[[`027b861ca1`](nodejs/node@027b861ca1)] - **benchmark, test**: replace CRLF variable with string literal (Lee Jiho) [#&#8203;59466](nodejs/node#59466)
- \[[`89dd770889`](nodejs/node@89dd770889)] - **build**: do not set `-mminimal-toc` with `clang` (Richard Lau) [#&#8203;59484](nodejs/node#59484)
- \[[`e13de4542f`](nodejs/node@e13de4542f)] - **child\_process**: remove unsafe array iteration (hotpineapple) [#&#8203;59347](nodejs/node#59347)
- \[[`89fe63551e`](nodejs/node@89fe63551e)] - **crypto**: load system CA certificates off thread (Joyee Cheung) [#&#8203;59550](nodejs/node#59550)
- \[[`152c5ef518`](nodejs/node@152c5ef518)] - **(SEMVER-MINOR)** **crypto**: add AES-OCB Web Cryptography algorithm (Filip Skokan) [#&#8203;59539](nodejs/node#59539)
- \[[`c6c418343d`](nodejs/node@c6c418343d)] - **crypto**: update root certificates to NSS 3.114 (Node.js GitHub Bot) [#&#8203;59571](nodejs/node#59571)
- \[[`18a2ee5b6c`](nodejs/node@18a2ee5b6c)] - **(SEMVER-MINOR)** **crypto**: support ML-KEM in Web Cryptography (Filip Skokan) [#&#8203;59569](nodejs/node#59569)
- \[[`72937e5144`](nodejs/node@72937e5144)] - **crypto**: require HMAC key length with SHA-3 hashes in Web Cryptography (Filip Skokan) [#&#8203;59567](nodejs/node#59567)
- \[[`b7383186c7`](nodejs/node@b7383186c7)] - **crypto**: fix subtle.getPublicKey error for secret type key inputs (Filip Skokan) [#&#8203;59558](nodejs/node#59558)
- \[[`2d05c046db`](nodejs/node@2d05c046db)] - **crypto**: return cached copies from CryptoKey algorithm and usages getters (Filip Skokan) [#&#8203;59538](nodejs/node#59538)
- \[[`207ffbeb07`](nodejs/node@207ffbeb07)] - **crypto**: use CryptoKey internal slots in Web Cryptography (Filip Skokan) [#&#8203;59538](nodejs/node#59538)
- \[[`4276516781`](nodejs/node@4276516781)] - **crypto**: normalize RsaHashedKeyParams publicExponent (Filip Skokan) [#&#8203;59538](nodejs/node#59538)
- \[[`14741539a7`](nodejs/node@14741539a7)] - **(SEMVER-MINOR)** **crypto**: support ML-KEM, DHKEM, and RSASVE key encapsulation mechanisms (Filip Skokan) [#&#8203;59491](nodejs/node#59491)
- \[[`d3afc63c44`](nodejs/node@d3afc63c44)] - **(SEMVER-MINOR)** **crypto**: add argon2() and argon2Sync() methods (Ranieri Althoff) [#&#8203;50353](nodejs/node#50353)
- \[[`4fe383e45a`](nodejs/node@4fe383e45a)] - **(SEMVER-MINOR)** **crypto**: support ML-DSA spki/pkcs8 key formats in Web Cryptography (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`a95386fbf9`](nodejs/node@a95386fbf9)] - **(SEMVER-MINOR)** **crypto**: subject some algorithms in Web Cryptography on BoringSSL absence (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`3f47a2fb63`](nodejs/node@3f47a2fb63)] - **(SEMVER-MINOR)** **crypto**: add ChaCha20-Poly1305 Web Cryptography algorithm (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`6fcce9058a`](nodejs/node@6fcce9058a)] - **(SEMVER-MINOR)** **crypto**: add subtle.getPublicKey() utility function in Web Cryptography (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`76cde76429`](nodejs/node@76cde76429)] - **(SEMVER-MINOR)** **crypto**: add SHA-3 Web Cryptography digest algorithms (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`247d017501`](nodejs/node@247d017501)] - **(SEMVER-MINOR)** **crypto**: add SHAKE Web Cryptography digest algorithms (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`f4fbcca5ce`](nodejs/node@f4fbcca5ce)] - **(SEMVER-MINOR)** **crypto**: add SubtleCrypto.supports feature detection in Web Cryptography (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`a55382214f`](nodejs/node@a55382214f)] - **(SEMVER-MINOR)** **crypto**: support ML-DSA in Web Cryptography (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`c38988c860`](nodejs/node@c38988c860)] - **crypto**: fix EVPKeyCtxPointer::publicCheck() (Tobias Nießen) [#&#8203;59471](nodejs/node#59471)
- \[[`61c3bcdc56`](nodejs/node@61c3bcdc56)] - **(SEMVER-MINOR)** **crypto**: support ML-KEM KeyObject (Filip Skokan) [#&#8203;59461](nodejs/node#59461)
- \[[`0821b446fb`](nodejs/node@0821b446fb)] - **deps**: update undici to 7.14.0 (Node.js GitHub Bot) [#&#8203;59507](nodejs/node#59507)
- \[[`b3af17c065`](nodejs/node@b3af17c065)] - **deps**: V8: cherry-pick [`7b91e3e`](nodejs/node@7b91e3e2cbaf) (Milad Fa) [#&#8203;59485](nodejs/node#59485)
- \[[`9b69baf146`](nodejs/node@9b69baf146)] - **deps**: V8: cherry-pick [`59d52e3`](nodejs/node@59d52e311bb1) (Milad Fa) [#&#8203;59485](nodejs/node#59485)
- \[[`b4f202c2f1`](nodejs/node@b4f202c2f1)] - **doc**: improve `sqlite.backup()` progress/fulfillment documentation (René) [#&#8203;59598](nodejs/node#59598)
- \[[`40b217a2f9`](nodejs/node@40b217a2f9)] - **doc**: clarify experimental platform vulnerability policy (Matteo Collina) [#&#8203;59591](nodejs/node#59591)
- \[[`cf84fffea5`](nodejs/node@cf84fffea5)] - **doc**: link to `TypedArray.from()` in signature (Aviv Keller) [#&#8203;59226](nodejs/node#59226)
- \[[`4bf6ed0bf5`](nodejs/node@4bf6ed0bf5)] - **doc**: fix typos in `environment_variables.md` (PhistucK) [#&#8203;59536](nodejs/node#59536)
- \[[`1784c35a49`](nodejs/node@1784c35a49)] - **doc**: add security incident reponse plan (Rafael Gonzaga) [#&#8203;59470](nodejs/node#59470)
- \[[`b962560240`](nodejs/node@b962560240)] - **doc**: clarify maxRSS unit in `process.resourceUsage()` (Alex Yang) [#&#8203;59511](nodejs/node#59511)
- \[[`e6a6cdb9df`](nodejs/node@e6a6cdb9df)] - **doc**: add missing Zstd strategy constants (RANDRIAMANANTENA Narindra Tiana Annaick) [#&#8203;59312](nodejs/node#59312)
- \[[`a6a31cb467`](nodejs/node@a6a31cb467)] - **(SEMVER-MINOR)** **doc**: compress Web Cryptography Algorithm matrix (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`8f8960cfcb`](nodejs/node@8f8960cfcb)] - **doc**: fix the version tls.DEFAULT\_CIPHERS was added (Allon Murienik) [#&#8203;59247](nodejs/node#59247)
- \[[`9e76089f1a`](nodejs/node@9e76089f1a)] - **doc**: clarify glob's exclude option behavior (hotpineapple) [#&#8203;59245](nodejs/node#59245)
- \[[`dd5f835af7`](nodejs/node@dd5f835af7)] - **doc**: add RafaelGSS as performance strategic lead (Rafael Gonzaga) [#&#8203;59445](nodejs/node#59445)
- \[[`2b7a7a525e`](nodejs/node@2b7a7a525e)] - **doc,crypto**: add supported asymmetric key types section (Filip Skokan) [#&#8203;59492](nodejs/node#59492)
- \[[`2fafe4c3bb`](nodejs/node@2fafe4c3bb)] - **esm**: link modules synchronously when no async loader hooks are used (Joyee Cheung) [#&#8203;59519](nodejs/node#59519)
- \[[`5347c4997a`](nodejs/node@5347c4997a)] - **esm**: show race error message for inner module job race (Joyee Cheung) [#&#8203;59519](nodejs/node#59519)
- \[[`b56d8af2fe`](nodejs/node@b56d8af2fe)] - **esm**: sync-ify module translation (Joyee Cheung) [#&#8203;59453](nodejs/node#59453)
- \[[`b4a23d6a69`](nodejs/node@b4a23d6a69)] - **http**: trim off brackets from IPv6 addresses with string operations (Krishnadas PC) [#&#8203;59420](nodejs/node#59420)
- \[[`6ae202fcdf`](nodejs/node@6ae202fcdf)] - **(SEMVER-MINOR)** **http**: add Agent.agentKeepAliveTimeoutBuffer option (Haram Jeong) [#&#8203;59315](nodejs/node#59315)
- \[[`dafee05358`](nodejs/node@dafee05358)] - **(SEMVER-MINOR)** **http2**: add support for raw header arrays in h2Stream.respond() (Tim Perry) [#&#8203;59455](nodejs/node#59455)
- \[[`b7ea39d860`](nodejs/node@b7ea39d860)] - **http2**: report sent headers object in client stream dcs (Darshan Sen) [#&#8203;59419](nodejs/node#59419)
- \[[`ebe9272dae`](nodejs/node@ebe9272dae)] - **inspector**: initial support websocket inspection (Shima Ryuhei) [#&#8203;59404](nodejs/node#59404)
- \[[`b35041c7dc`](nodejs/node@b35041c7dc)] - **inspector**: prevent propagation of promise hooks to noPromise hooks (Shima Ryuhei) [#&#8203;58841](nodejs/node#58841)
- \[[`fe7176d7c6`](nodejs/node@fe7176d7c6)] - **lib**: do not modify prototype deprecated asyncResource (encore) (Szymon Łągiewka) [#&#8203;59518](nodejs/node#59518)
- \[[`93fc80a1e2`](nodejs/node@93fc80a1e2)] - **(SEMVER-MINOR)** **lib**: refactor kSupportedAlgorithms (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`9a12f71ad9`](nodejs/node@9a12f71ad9)] - **lib**: simplify IPv6 checks in isLoopback() (Krishnadas) [#&#8203;59375](nodejs/node#59375)
- \[[`566fb04c82`](nodejs/node@566fb04c82)] - **meta**: update devcontainer to the latest schema (Aviv Keller) [#&#8203;54347](nodejs/node#54347)
- \[[`389a24bbff`](nodejs/node@389a24bbff)] - **module**: allow overriding linked requests for a ModuleWrap (Chengzhong Wu) [#&#8203;59527](nodejs/node#59527)
- \[[`7880978fe3`](nodejs/node@7880978fe3)] - **module**: correctly detect top-level await in ambiguous contexts (Shima Ryuhei) [#&#8203;58646](nodejs/node#58646)
- \[[`99128d9244`](nodejs/node@99128d9244)] - **node-api**: link to other programming language bindings (Chengzhong Wu) [#&#8203;59516](nodejs/node#59516)
- \[[`65c870e6cb`](nodejs/node@65c870e6cb)] - **node-api**: clarify enum value ABI stability (Chengzhong Wu) [#&#8203;59085](nodejs/node#59085)
- \[[`352d63541a`](nodejs/node@352d63541a)] - **sea**: implement execArgvExtension (Joyee Cheung) [#&#8203;59560](nodejs/node#59560)
- \[[`c6e3d5d98d`](nodejs/node@c6e3d5d98d)] - **(SEMVER-MINOR)** **sea**: support execArgv in sea config (Joyee Cheung) [#&#8203;59314](nodejs/node#59314)
- \[[`e7084df4db`](nodejs/node@e7084df4db)] - **sqlite**: add sqlite-type symbol for DatabaseSync (Alex Yang) [#&#8203;59405](nodejs/node#59405)
- \[[`e2b6bdc640`](nodejs/node@e2b6bdc640)] - **sqlite**: handle ?NNN parameters as positional (Edy Silva) [#&#8203;59350](nodejs/node#59350)
- \[[`99e4a12731`](nodejs/node@99e4a12731)] - **sqlite**: avoid useless call to FromMaybe() (Tobias Nießen) [#&#8203;59490](nodejs/node#59490)
- \[[`dfd4962e5f`](nodejs/node@dfd4962e5f)] - **src**: enforce assumptions in FIXED\_ONE\_BYTE\_STRING (Tobias Nießen) [#&#8203;58155](nodejs/node#58155)
- \[[`93a368df04`](nodejs/node@93a368df04)] - **src**: use simdjson to parse --snapshot-config (Joyee Cheung) [#&#8203;59473](nodejs/node#59473)
- \[[`716750fcf8`](nodejs/node@716750fcf8)] - **src**: fix order of CHECK\_NOT\_NULL/dereference (Tobias Nießen) [#&#8203;59487](nodejs/node#59487)
- \[[`44a8ecf8d4`](nodejs/node@44a8ecf8d4)] - **src**: assert memory calc for max-old-space-size-percentage (Asaf Federman) [#&#8203;59460](nodejs/node#59460)
- \[[`3462b46fca`](nodejs/node@3462b46fca)] - **src**: use simdjson::pad (0hm☘️) [#&#8203;59391](nodejs/node#59391)
- \[[`3e1551d845`](nodejs/node@3e1551d845)] - **src**: move shared\_ptr objects in KeyObjectData (Tobias Nießen) [#&#8203;59472](nodejs/node#59472)
- \[[`c022c1f85a`](nodejs/node@c022c1f85a)] - **src**: add internal GetOptionsAsFlags (Pietro Marchini) [#&#8203;59138](nodejs/node#59138)
- \[[`c0f08454a3`](nodejs/node@c0f08454a3)] - **src**: iterate metadata version entries with std::array (Chengzhong Wu) [#&#8203;57866](nodejs/node#57866)
- \[[`f87836f3ae`](nodejs/node@f87836f3ae)] - **src**: internalize `v8::ConvertableToTraceFormat` in traces (Chengzhong Wu) [#&#8203;57866](nodejs/node#57866)
- \[[`852b8e46d8`](nodejs/node@852b8e46d8)] - **src**: remove duplicate assignment of `O_EXCL` in node\_constants.cc (Daniel Osvaldo R) [#&#8203;59049](nodejs/node#59049)
- \[[`64ffde608f`](nodejs/node@64ffde608f)] - **src**: add Intel CET properties to large\_pages.S (tjuhaszrh) [#&#8203;59363](nodejs/node#59363)
- \[[`823dce32ec`](nodejs/node@823dce32ec)] - **src**: update OpenSSL pqc checks (Filip Skokan) [#&#8203;59436](nodejs/node#59436)
- \[[`8dc6f5b696`](nodejs/node@8dc6f5b696)] - **(SEMVER-MINOR)** **stream**: add brotli support to CompressionStream and DecompressionStream (Matthew Aitken) [#&#8203;59464](nodejs/node#59464)
- \[[`b2b8383755`](nodejs/node@b2b8383755)] - **test**: use mustSucceed in test-repl-tab-complete-import (Sohyeon Kim) [#&#8203;59368](nodejs/node#59368)
- \[[`e3ad5cc2c6`](nodejs/node@e3ad5cc2c6)] - **test**: skip sea tests on Linux ppc64le (Richard Lau) [#&#8203;59563](nodejs/node#59563)
- \[[`f78f47ca5a`](nodejs/node@f78f47ca5a)] - **test**: support standalone env comment in tests (Pietro Marchini) [#&#8203;59546](nodejs/node#59546)
- \[[`0e8bc2c7ac`](nodejs/node@0e8bc2c7ac)] - **test**: rename test-net-server-drop-connections-in-cluster.js to -http- (Meghan Denny) [#&#8203;59532](nodejs/node#59532)
- \[[`ed339580af`](nodejs/node@ed339580af)] - **test**: lazy-load internalTTy (Pietro Marchini) [#&#8203;59517](nodejs/node#59517)
- \[[`fe86bc6da8`](nodejs/node@fe86bc6da8)] - **test**: fix `test-setproctitle` status when `ps` is not available (Antoine du Hamel) [#&#8203;59523](nodejs/node#59523)
- \[[`e517792973`](nodejs/node@e517792973)] - **test**: add parseTestMetadata support (Pietro Marchini) [#&#8203;59503](nodejs/node#59503)
- \[[`31092972d6`](nodejs/node@31092972d6)] - **test**: update WPT for WebCryptoAPI to [`ff26d9b`](nodejs/node@ff26d9b307) (Node.js GitHub Bot) [#&#8203;59497](nodejs/node#59497)
- \[[`16afd103cc`](nodejs/node@16afd103cc)] - **(SEMVER-MINOR)** **test**: add Web Cryptography wrap/unwrap vectors (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`5598baf34e`](nodejs/node@5598baf34e)] - **(SEMVER-MINOR)** **test**: cleanup test-webcrypto-supports (Filip Skokan) [#&#8203;59365](nodejs/node#59365)
- \[[`e7809d6ddb`](nodejs/node@e7809d6ddb)] - **test**: make test-debug-process locale-independent (BCD1me) [#&#8203;59254](nodejs/node#59254)
- \[[`ca7856e73c`](nodejs/node@ca7856e73c)] - **test**: mark test-wasi-pthread as flaky (Joyee Cheung) [#&#8203;59488](nodejs/node#59488)
- \[[`0ecd82197f`](nodejs/node@0ecd82197f)] - **test**: split test-wasi.js (Joyee Cheung) [#&#8203;59488](nodejs/node#59488)
- \[[`0930c218d6`](nodejs/node@0930c218d6)] - **test**: deflake connection refused proxy tests (Joyee Cheung) [#&#8203;59476](nodejs/node#59476)
- \[[`7f457f886a`](nodejs/node@7f457f886a)] - **test**: use case-insensitive path checking on Windows in fs.cpSync tests (Joyee Cheung) [#&#8203;59475](nodejs/node#59475)
- \[[`37809115f9`](nodejs/node@37809115f9)] - **test**: add missing hasPostData in test-inspector-emit-protocol-event (Shima Ryuhei) [#&#8203;59412](nodejs/node#59412)
- \[[`f4722b1672`](nodejs/node@f4722b1672)] - **test**: refactor error checks to use assert.ifError/mustSucceed (Sohyeon Kim) [#&#8203;59424](nodejs/node#59424)
- \[[`9ff71a672d`](nodejs/node@9ff71a672d)] - **test**: fix typos (Lee Jiho) [#&#8203;59330](nodejs/node#59330)
- \[[`9a7700da62`](nodejs/node@9a7700da62)] - **test**: skip test-watch-mode inspect when no inspector (James M Snell) [#&#8203;59440](nodejs/node#59440)
- \[[`e964c4334e`](nodejs/node@e964c4334e)] - **test\_runner**: do not error when getting `fullName` of root context (René) [#&#8203;59377](nodejs/node#59377)
- \[[`e076f7857c`](nodejs/node@e076f7857c)] - **test\_runner**: add option to rerun only failed tests (Moshe Atlow) [#&#8203;59443](nodejs/node#59443)
- \[[`eb8b1939a4`](nodejs/node@eb8b1939a4)] - **test\_runner**: fix isSkipped check in junit (Sungwon) [#&#8203;59414](nodejs/node#59414)
- \[[`4e02ea1c52`](nodejs/node@4e02ea1c52)] - **tools**: update gyp-next to 0.20.3 (Node.js GitHub Bot) [#&#8203;59603](nodejs/node#59603)
- \[[`99da7fbe11`](nodejs/node@99da7fbe11)] - **tools**: avoid parsing test files twice (Pietro Marchini) [#&#8203;59526](nodejs/node#59526)
- \[[`9a6a8e319b`](nodejs/node@9a6a8e319b)] - **tools**: update coverage GitHub Actions to fixed version (Rich Trott) [#&#8203;59512](nodejs/node#59512)
- \[[`8d28236aff`](nodejs/node@8d28236aff)] - **tools**: fix return value of try\_check\_compiler (theanarkh) [#&#8203;59434](nodejs/node#59434)
- \[[`52ab64ec3a`](nodejs/node@52ab64ec3a)] - **tools**: bump [@&#8203;eslint/plugin-kit](https://github.com/eslint/plugin-kit) from 0.3.3 to 0.3.4 in /tools/eslint (dependabot\[bot]) [#&#8203;59271](nodejs/node#59271)
- \[[`baa22893bb`](nodejs/node@baa22893bb)] - **typings**: add missing URLBinding methods (성우현 | Woohyun Sung) [#&#8203;59468](nodejs/node#59468)
- \[[`b68e0d1eca`](nodejs/node@b68e0d1eca)] - **util**: fix error's namespaced node\_modules highlighting using inspect (Ruben Bridgewater) [#&#8203;59446](nodejs/node#59446)
- \[[`15ae21b88a`](nodejs/node@15ae21b88a)] - **util**: add some additional error classes to `wellKnownPrototypes` (Mark S. Miller) [#&#8203;59456](nodejs/node#59456)
- \[[`c38b7cfa35`](nodejs/node@c38b7cfa35)] - **worker**: fix worker name with \0 (theanarkh) [#&#8203;59214](nodejs/node#59214)
- \[[`f54ace694a`](nodejs/node@f54ace694a)] - **worker**: add worker name to report (theanarkh) [#&#8203;58935](nodejs/node#58935)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS44Ni4wIiwidXBkYXRlZEluVmVyIjoiNDEuODYuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
@richardlau richardlau added the backport-requested-v22.x PRs awaiting manual backport to the v22.x-staging branch. label Sep 19, 2025
@richardlau
Copy link
Member

This doesn't land cleanly on v22.x-staging so a manual backport will be necessary if this is to be released there. It probably needs to be backported together with the proxy stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport-requested-v22.x PRs awaiting manual backport to the v22.x-staging branch. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.