Skip to content

Conversation

JinhyeokFang
Copy link
Contributor

Description

Optimize checkIsHttpToken performance by using a pre-computed lookup table for strings shorter than 10 characters instead of regex

Benchmark Results

Shows significant performance improvements for short strings, with minimal impact on longer strings:

http/check_is_http_token.js n=1000000 key=':'                                                                         ***    188.25 %       ±1.05% ±1.41% ±1.86%
http/check_is_http_token.js n=1000000 key=':alternate-protocol'                                                       ***     -3.76 %       ±0.30% ±0.40% ±0.52%
http/check_is_http_token.js n=1000000 key='((((())))'                                                                 ***    188.71 %       ±1.01% ±1.35% ±1.79%
http/check_is_http_token.js n=1000000 key='@@'                                                                        ***    187.33 %       ±2.87% ±3.86% ±5.12%
http/check_is_http_token.js n=1000000 key='中文呢'                                                                       ***    108.16 %       ±0.91% ±1.23% ±1.61%
http/check_is_http_token.js n=1000000 key='Accept-Ranges'                                                             ***     -2.18 %       ±0.73% ±0.97% ±1.27%
http/check_is_http_token.js n=1000000 key='alt-svc'                                                                   ***     83.63 %       ±0.46% ±0.61% ±0.80%
http/check_is_http_token.js n=1000000 key='alternate-protocol:'                                                         *     -1.31 %       ±1.19% ±1.61% ±2.13%
http/check_is_http_token.js n=1000000 key='alternate-protocol'                                                        ***     -2.28 %       ±0.45% ±0.60% ±0.79%
http/check_is_http_token.js n=1000000 key='Cache-Control'                                                             ***     -2.47 %       ±0.34% ±0.46% ±0.60%
http/check_is_http_token.js n=1000000 key='Connection'                                                                ***     -1.86 %       ±0.52% ±0.69% ±0.91%
http/check_is_http_token.js n=1000000 key='Content-Encoding'                                                          ***     -2.23 %       ±0.65% ±0.86% ±1.12%
http/check_is_http_token.js n=1000000 key='content-length'                                                            ***     -2.61 %       ±0.98% ±1.32% ±1.74%
http/check_is_http_token.js n=1000000 key='Content-Location'                                                          ***     -2.24 %       ±0.44% ±0.58% ±0.76%
http/check_is_http_token.js n=1000000 key='content-type'                                                              ***     -1.34 %       ±0.37% ±0.49% ±0.64%
http/check_is_http_token.js n=1000000 key='Content-Type'                                                              ***     -1.45 %       ±0.31% ±0.42% ±0.54%
http/check_is_http_token.js n=1000000 key='date'                                                                      ***    145.58 %       ±0.77% ±1.03% ±1.34%
http/check_is_http_token.js n=1000000 key='ETag'                                                                      ***    145.77 %       ±0.56% ±0.75% ±0.98%
http/check_is_http_token.js n=1000000 key='Expires'                                                                   ***     83.44 %       ±0.45% ±0.60% ±0.78%
http/check_is_http_token.js n=1000000 key='Keep-Alive'                                                                ***     -1.36 %       ±0.41% ±0.55% ±0.71%
http/check_is_http_token.js n=1000000 key='Last-Modified'                                                             ***     -2.43 %       ±0.38% ±0.51% ±0.67%
http/check_is_http_token.js n=1000000 key='location'                                                                  ***     71.30 %       ±1.22% ±1.64% ±2.16%
http/check_is_http_token.js n=1000000 key='server'                                                                    ***     99.77 %       ±0.50% ±0.66% ±0.86%
http/check_is_http_token.js n=1000000 key='Server'                                                                    ***     99.28 %       ±0.53% ±0.71% ±0.92%
http/check_is_http_token.js n=1000000 key='status'                                                                    ***     98.86 %       ±0.57% ±0.76% ±0.99%
http/check_is_http_token.js n=1000000 key='TCN'                                                                       ***    224.62 %       ±1.33% ±1.78% ±2.34%
http/check_is_http_token.js n=1000000 key='Transfer-Encoding'                                                         ***     -1.98 %       ±0.48% ±0.64% ±0.84%
http/check_is_http_token.js n=1000000 key='Vary'                                                                      ***    145.11 %       ±0.85% ±1.13% ±1.49%
http/check_is_http_token.js n=1000000 key='version'                                                                   ***     83.58 %       ±0.46% ±0.61% ±0.80%
http/check_is_http_token.js n=1000000 key='x-frame-options'                                                           ***     -2.59 %       ±0.66% ±0.88% ±1.15%
http/check_is_http_token.js n=1000000 key='x-xss-protection'                                                          ***     -2.18 %       ±0.39% ±0.52% ±0.68%

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/net

@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 Sep 9, 2025
Copy link

codecov bot commented Sep 9, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.30%. Comparing base (861d624) to head (b1f8b70).
⚠️ Report is 33 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #59832      +/-   ##
==========================================
+ Coverage   88.26%   88.30%   +0.03%     
==========================================
  Files         701      701              
  Lines      206774   206810      +36     
  Branches    39778    39780       +2     
==========================================
+ Hits       182514   182622     +108     
+ Misses      16298    16210      -88     
- Partials     7962     7978      +16     
Files with missing lines Coverage Δ
lib/_http_common.js 100.00% <100.00%> (ø)

... and 40 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.

Use lookup table instead of regex for strings shorter than 10
characters to improve performance for common short header names
while maintaining compatibility.
Copy link
Contributor

@Ethan-Arrowood Ethan-Arrowood left a comment

Choose a reason for hiding this comment

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

I like it! Before we merge let's run benchmarks and be sure

@daeyeon daeyeon added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. labels Sep 12, 2025
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Sep 12, 2025
@nodejs-github-bot
Copy link
Collaborator

@daeyeon
Copy link
Member

daeyeon commented Sep 13, 2025

Benchmark CI: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1734/console

08:39:30 http/check_is_http_token.js n=1000000 key=':'                                                            ***    224.81 %       ±8.27% ±11.01% ±14.33%
08:39:30 http/check_is_http_token.js n=1000000 key=':alternate-protocol'                                                  -3.25 %       ±5.76%  ±7.67%  ±9.98%
08:39:30 http/check_is_http_token.js n=1000000 key='((((())))'                                                    ***    236.05 %      ±15.19% ±20.37% ±26.86%
08:39:30 http/check_is_http_token.js n=1000000 key='@@'                                                           ***    220.11 %       ±7.32%  ±9.77% ±12.77%
08:39:30 http/check_is_http_token.js n=1000000 key='Accept-Ranges'                                                        -0.35 %       ±3.43%  ±4.56%  ±5.93%
08:39:30 http/check_is_http_token.js n=1000000 key='alt-svc'                                                      ***     65.58 %       ±5.11%  ±6.83%  ±8.94%
08:39:30 http/check_is_http_token.js n=1000000 key='alternate-protocol:'                                            *     -2.01 %       ±1.79%  ±2.38%  ±3.10%
08:39:30 http/check_is_http_token.js n=1000000 key='alternate-protocol'                                                    1.43 %       ±2.28%  ±3.04%  ±3.96%
08:39:30 http/check_is_http_token.js n=1000000 key='Cache-Control'                                                        -0.14 %       ±3.11%  ±4.14%  ±5.39%
08:39:30 http/check_is_http_token.js n=1000000 key='Connection'                                                            1.48 %       ±2.74%  ±3.64%  ±4.75%
08:39:30 http/check_is_http_token.js n=1000000 key='Content-Encoding'                                                      1.61 %       ±2.93%  ±3.90%  ±5.08%
08:39:30 http/check_is_http_token.js n=1000000 key='content-length'                                                       -1.58 %       ±2.55%  ±3.39%  ±4.43%
08:39:30 http/check_is_http_token.js n=1000000 key='Content-Location'                                                      1.38 %       ±2.52%  ±3.35%  ±4.36%
08:39:30 http/check_is_http_token.js n=1000000 key='content-type'                                                         -0.38 %       ±3.37%  ±4.48%  ±5.84%
08:39:30 http/check_is_http_token.js n=1000000 key='Content-Type'                                                         -0.84 %       ±3.33%  ±4.43%  ±5.76%
08:39:30 http/check_is_http_token.js n=1000000 key='date'                                                         ***    155.93 %       ±6.71%  ±9.01% ±11.90%
08:39:30 http/check_is_http_token.js n=1000000 key='ETag'                                                         ***    167.04 %       ±4.69%  ±6.26%  ±8.19%
08:39:30 http/check_is_http_token.js n=1000000 key='Expires'                                                      ***     66.65 %       ±4.58%  ±6.10%  ±7.95%
08:39:30 http/check_is_http_token.js n=1000000 key='Keep-Alive'                                                           -1.91 %       ±2.57%  ±3.42%  ±4.45%
08:39:30 http/check_is_http_token.js n=1000000 key='Last-Modified'                                                        -1.97 %       ±2.76%  ±3.67%  ±4.77%
08:39:30 http/check_is_http_token.js n=1000000 key='location'                                                     ***     47.84 %       ±4.54%  ±6.07%  ±7.94%
08:39:30 http/check_is_http_token.js n=1000000 key='server'                                                       ***     75.46 %       ±4.14%  ±5.53%  ±7.24%
08:39:30 http/check_is_http_token.js n=1000000 key='Server'                                                       ***     79.92 %       ±5.56%  ±7.44%  ±9.77%
08:39:30 http/check_is_http_token.js n=1000000 key='status'                                                       ***     79.03 %       ±5.31%  ±7.10%  ±9.31%
08:39:30 http/check_is_http_token.js n=1000000 key='TCN'                                                          ***    215.88 %       ±6.17%  ±8.27% ±10.91%
08:39:30 http/check_is_http_token.js n=1000000 key='Transfer-Encoding'                                                    -0.99 %       ±2.16%  ±2.87%  ±3.74%
08:39:30 http/check_is_http_token.js n=1000000 key='Vary'                                                         ***    157.55 %       ±6.81%  ±9.11% ±11.98%
08:39:30 http/check_is_http_token.js n=1000000 key='version'                                                      ***     61.80 %       ±5.12%  ±6.85%  ±8.97%
08:39:30 http/check_is_http_token.js n=1000000 key='x-frame-options'                                                       0.11 %       ±2.85%  ±3.79%  ±4.93%
08:39:30 http/check_is_http_token.js n=1000000 key='x-xss-protection'                                                      2.38 %       ±2.85%  ±3.80%  ±4.94%
08:39:30 http/check_is_http_token.js n=1000000 key='中文呢'                                                       ***    135.25 %       ±5.50%  ±7.37%  ±9.68%

@BridgeAR BridgeAR added the commit-queue Add this label to land a pull request using GitHub Actions. label Sep 14, 2025
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Sep 14, 2025
@nodejs-github-bot nodejs-github-bot merged commit c8c6bfa into nodejs:main Sep 14, 2025
64 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in c8c6bfa

@jasnell
Copy link
Member

jasnell commented Sep 14, 2025

FWIW, you can likely get a bit more of a performance improvement out of this with a few additional tweaks:

const packedValidChars = [
  0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0-31
  0x5f036600, 0xffc07fff, 0xffffffff, 0xe3ffffff, // 32-127 (4 groups of 32)
];

function checkIsHttpToken(val) {
  const len = val.length;
  if (len > 10) return tokenRegExp.test(val);
  if (len === 0) return false;

  for (let i = 0; i < len; i++) {
    const c = val.charCodeAt(i);
    if (c >= 128) return false;
    if ((packedValidChars[c >>> 5] & (1 << (c & 31))) === 0) return false;
  }

  return true;
}
http/check_is_http_token.js n=1000000 key=':'                          ***    118.92 %       ±9.20% ±12.36% ±16.32%
http/check_is_http_token.js n=1000000 key=':alternate-protocol'         **      8.43 %       ±4.92%  ±6.55%  ±8.53%
http/check_is_http_token.js n=1000000 key='((((())))'                  ***    115.60 %       ±6.72%  ±8.97% ±11.72%
http/check_is_http_token.js n=1000000 key='@@'                         ***    113.27 %      ±10.04% ±13.46% ±17.73%
http/check_is_http_token.js n=1000000 key='Accept-Ranges'                      -3.22 %       ±3.38%  ±4.50%  ±5.86%
http/check_is_http_token.js n=1000000 key='alt-svc'                    ***    329.85 %      ±14.15% ±19.03% ±25.19%
http/check_is_http_token.js n=1000000 key='alternate-protocol:'        ***     14.11 %       ±3.20%  ±4.26%  ±5.54%
http/check_is_http_token.js n=1000000 key='alternate-protocol'           *     -5.02 %       ±4.79%  ±6.39%  ±8.34%
http/check_is_http_token.js n=1000000 key='Cache-Control'               **     -5.27 %       ±3.92%  ±5.22%  ±6.79%
http/check_is_http_token.js n=1000000 key='Connection'                 ***    354.04 %      ±18.15% ±24.43% ±32.38%
http/check_is_http_token.js n=1000000 key='Content-Encoding'                   -2.51 %       ±3.02%  ±4.02%  ±5.23%
http/check_is_http_token.js n=1000000 key='content-length'              **     -5.36 %       ±3.55%  ±4.73%  ±6.16%
http/check_is_http_token.js n=1000000 key='Content-Location'                   -1.73 %       ±3.35%  ±4.46%  ±5.80%
http/check_is_http_token.js n=1000000 key='content-type'                        3.93 %       ±4.22%  ±5.62%  ±7.31%
http/check_is_http_token.js n=1000000 key='Content-Type'                       -0.67 %       ±3.92%  ±5.22%  ±6.79%
http/check_is_http_token.js n=1000000 key='date'                       ***    284.10 %      ±11.09% ±14.89% ±19.65%
http/check_is_http_token.js n=1000000 key='ETag'                       ***    280.51 %      ±15.62% ±21.01% ±27.83%
http/check_is_http_token.js n=1000000 key='Expires'                    ***    333.47 %      ±15.22% ±20.47% ±27.07%
http/check_is_http_token.js n=1000000 key='Keep-Alive'                 ***    354.42 %      ±15.04% ±20.22% ±26.74%
http/check_is_http_token.js n=1000000 key='Last-Modified'                      -0.61 %       ±4.28%  ±5.70%  ±7.43%
http/check_is_http_token.js n=1000000 key='location'                   ***    344.17 %      ±20.91% ±28.15% ±37.31%
http/check_is_http_token.js n=1000000 key='server'                     ***    286.48 %      ±20.73% ±27.92% ±37.03%
http/check_is_http_token.js n=1000000 key='Server'                     ***    303.34 %      ±19.30% ±25.98% ±34.42%
http/check_is_http_token.js n=1000000 key='status'                     ***    325.70 %      ±15.30% ±20.57% ±27.23%
http/check_is_http_token.js n=1000000 key='TCN'                        ***    267.06 %      ±15.14% ±20.36% ±26.96%
http/check_is_http_token.js n=1000000 key='Transfer-Encoding'           **     -4.72 %       ±3.52%  ±4.69%  ±6.12%
http/check_is_http_token.js n=1000000 key='Vary'                       ***    291.85 %      ±10.86% ±14.61% ±19.34%
http/check_is_http_token.js n=1000000 key='version'                    ***    307.96 %      ±18.18% ±24.46% ±32.39%
http/check_is_http_token.js n=1000000 key='x-frame-options'             **     -3.96 %       ±2.88%  ±3.84%  ±4.99%
http/check_is_http_token.js n=1000000 key='x-xss-protection'                   -2.14 %       ±3.06%  ±4.07%  ±5.30%
http/check_is_http_token.js n=1000000 key='中文呢'                     ***    181.91 %      ±10.54% ±14.15% ±18.66%

@JinhyeokFang
Copy link
Contributor Author

Thanks for the suggestion, @jasnell. That's a good idea. I'll open a new PR to get this implemented.

@JinhyeokFang
Copy link
Contributor Author

FWIW, you can likely get a bit more of a performance improvement out of this with a few additional tweaks:

const packedValidChars = [
  0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0-31               => 0-127
  0x5f036600, 0xffc07fff, 0xffffffff, 0xe3ffffff, // 32-127 (4 groups of 32)   => 128-255
];

function checkIsHttpToken(val) {
  const len = val.length;
  if (len > 10) return tokenRegExp.test(val);
  if (len === 0) return false;

  for (let i = 0; i < len; i++) {
    const c = val.charCodeAt(i);
    if (c >= 128) return false;
    if ((packedValidChars[c >>> 5] & (1 << (c & 31))) === 0) return false;
  }

  return true;
}

The packedValidChars array has its first four elements, which cover ASCII characters 0-127, initialized to 0.

Because of this, the check (packedValidChars[c >>> 5] & (1 << (c & 31))) === 0 will always evaluate to true for any character in that range. This causes the function to incorrectly return false for any valid input string.

The observed performance gain comes from this incorrect early return, not from a correctly implemented bitmask. The code as written would fail its tests.

@jasnell
Copy link
Member

jasnell commented Sep 17, 2025

doh! heh, nice catch. Looking back at it i was testing it on invalid inputs lol

@PandaWorker
Copy link

It seems like it's supposed to be

const packedValidChars = new Uint32Array([
  0x00000000, 0x03FF6CFA, 0xC7FFFFFE, 0x57FFFFFF, // 0-127
]);

function checkIsHttpToken(val: string): boolean {
  if (val.length === 0) return false;

  for (let i = 0; i < val.length; i++) {
    const code = val.charCodeAt(i);
    if (code >= 128) return false;

    const group = code >>> 5;
    const bitMask = 1 << (code & 31);
    if ((packedValidChars[group] & bitMask) === 0) {
      return false;
    }
  }
  return true;
}

const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;

function test(){
  for (let c = 0; c < 256; c++) {
    const char = String.fromCharCode(c);
    console.assert(checkIsHttpToken(char) === tokenRegExp.test(char), `char: ${char}`)
  }
}

test()

targos pushed a commit that referenced this pull request Sep 18, 2025
Use lookup table instead of regex for strings shorter than 10
characters to improve performance for common short header names
while maintaining compatibility.

PR-URL: #59832
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
targos pushed a commit that referenced this pull request Sep 24, 2025
Use lookup table instead of regex for strings shorter than 10
characters to improve performance for common short header names
while maintaining compatibility.

PR-URL: #59832
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Sep 26, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [node](https://nodejs.org) ([source](https://github.com/nodejs/node)) | minor | `24.8.0` -> `24.9.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.9.0`](https://github.com/nodejs/node/releases/tag/v24.9.0): 2025-09-25, Version 24.9.0 (Current), @&#8203;targos

[Compare Source](nodejs/node@v24.8.0...v24.9.0)

##### Notable Changes

- \[[`9b043a9096`](nodejs/node@9b043a9096)] - **(SEMVER-MINOR)** **http**: add shouldUpgradeCallback to let servers control HTTP upgrades (Tim Perry) [#&#8203;59824](nodejs/node#59824)
- \[[`a6456ab90a`](nodejs/node@a6456ab90a)] - **(SEMVER-MINOR)** **sqlite**: cleanup ERM support and export Session class (James M Snell) [#&#8203;58378](nodejs/node#58378)
- \[[`5563361d22`](nodejs/node@5563361d22)] - **(SEMVER-MINOR)** **sqlite**: add tagged template (0hm☘️) [#&#8203;58748](nodejs/node#58748)
- \[[`04013ee933`](nodejs/node@04013ee933)] - **(SEMVER-MINOR)** **worker**: add heap profile API (theanarkh) [#&#8203;59846](nodejs/node#59846)

##### Commits

- \[[`cbec4fd6de`](nodejs/node@cbec4fd6de)] - **benchmark**: calibrate config dgram multi-buffer (Bruno Rodrigues) [#&#8203;59696](nodejs/node#59696)
- \[[`9a4bbdc3c5`](nodejs/node@9a4bbdc3c5)] - **benchmark**: calibrate config cluster/echo.js (Nam Yooseong) [#&#8203;59836](nodejs/node#59836)
- \[[`0b284d86e8`](nodejs/node@0b284d86e8)] - **build**: add the missing macro definitions for OpenHarmony (hqzing) [#&#8203;59804](nodejs/node#59804)
- \[[`43e6e54d66`](nodejs/node@43e6e54d66)] - **build**: do not include custom ESLint rules testing in tarball (Antoine du Hamel) [#&#8203;59809](nodejs/node#59809)
- \[[`039ac19154`](nodejs/node@039ac19154)] - **crypto**: expose signatureAlgorithm on X509Certificate (Patrick Costa) [#&#8203;59235](nodejs/node#59235)
- \[[`647c332704`](nodejs/node@647c332704)] - **crypto**: use `return await` when returning Promises from async functions (Renegade334) [#&#8203;59841](nodejs/node#59841)
- \[[`8ed4587cf0`](nodejs/node@8ed4587cf0)] - **crypto**: use async functions for non-stub Promise-returning functions (Renegade334) [#&#8203;59841](nodejs/node#59841)
- \[[`bb051c56ef`](nodejs/node@bb051c56ef)] - **crypto**: avoid calls to `promise.catch()` (Renegade334) [#&#8203;59841](nodejs/node#59841)
- \[[`05e560dd25`](nodejs/node@05e560dd25)] - **deps**: update googletest to [`50b8600`](nodejs/node@50b8600) (Node.js GitHub Bot) [#&#8203;59955](nodejs/node#59955)
- \[[`fa40d3a785`](nodejs/node@fa40d3a785)] - **deps**: update archs files for openssl-3.5.3 (Node.js GitHub Bot) [#&#8203;59901](nodejs/node#59901)
- \[[`8c85570d18`](nodejs/node@8c85570d18)] - **deps**: upgrade openssl sources to openssl-3.5.3 (Node.js GitHub Bot) [#&#8203;59901](nodejs/node#59901)
- \[[`b71125664e`](nodejs/node@b71125664e)] - **deps**: update undici to 7.16.0 (Node.js GitHub Bot) [#&#8203;59830](nodejs/node#59830)
- \[[`dea5dd7077`](nodejs/node@dea5dd7077)] - **dgram**: restore buffer optimization in fixBufferList (Yoo) [#&#8203;59934](nodejs/node#59934)
- \[[`b0c1e67532`](nodejs/node@b0c1e67532)] - **diagnostics\_channel**: fix race condition with diagnostics\_channel and GC (Ugaitz Urien) [#&#8203;59910](nodejs/node#59910)
- \[[`0b37b594c3`](nodejs/node@0b37b594c3)] - **doc**: use "WebAssembly" instead of "Web Assembly" (Tobias Nießen) [#&#8203;59954](nodejs/node#59954)
- \[[`1e723f9c6b`](nodejs/node@1e723f9c6b)] - **doc**: fix typo in section on microtask order (Tobias Nießen) [#&#8203;59932](nodejs/node#59932)
- \[[`a28962a85c`](nodejs/node@a28962a85c)] - **doc**: update V8 fast API guidance (René) [#&#8203;58999](nodejs/node#58999)
- \[[`bd767c5d1b`](nodejs/node@bd767c5d1b)] - **doc**: add security escalation policy (Ulises Gascón) [#&#8203;59806](nodejs/node#59806)
- \[[`9df91e59e1`](nodejs/node@9df91e59e1)] - **doc**: type improvement of file `http.md` (yusheng chen) [#&#8203;58189](nodejs/node#58189)
- \[[`e4f571680b`](nodejs/node@e4f571680b)] - **doc**: deprecate closing `fs.Dir` on garbage collection (Livia Medeiros) [#&#8203;59839](nodejs/node#59839)
- \[[`e9cb986fa5`](nodejs/node@e9cb986fa5)] - **doc**: rephrase dynamic import() description (Nam Yooseong) [#&#8203;59224](nodejs/node#59224)
- \[[`026d4e33f7`](nodejs/node@026d4e33f7)] - **doc,crypto**: update subtle.generateKey and subtle.importKey (Filip Skokan) [#&#8203;59851](nodejs/node#59851)
- \[[`2b2591db52`](nodejs/node@2b2591db52)] - **esm**: make hasAsyncGraph non-enumerable (Joyee Cheung) [#&#8203;59905](nodejs/node#59905)
- \[[`993f05d323`](nodejs/node@993f05d323)] - **fs,win**: do not add a second trailing slash in readdir (Gerhard Stöbich) [#&#8203;59847](nodejs/node#59847)
- \[[`7aec53b607`](nodejs/node@7aec53b607)] - **(SEMVER-MINOR)** **http**: add shouldUpgradeCallback to let servers control HTTP upgrades (Tim Perry) [#&#8203;59824](nodejs/node#59824)
- \[[`83ae6102e7`](nodejs/node@83ae6102e7)] - **http**: optimize checkIsHttpToken for short strings (방진혁) [#&#8203;59832](nodejs/node#59832)
- \[[`6695067636`](nodejs/node@6695067636)] - **http,https**: handle IPv6 with proxies (Joyee Cheung) [#&#8203;59894](nodejs/node#59894)
- \[[`c5d910a0a9`](nodejs/node@c5d910a0a9)] - **http2**: fix allowHttp1+Upgrade, broken by shouldUpgradeCallback (Tim Perry) [#&#8203;59924](nodejs/node#59924)
- \[[`acada1fb82`](nodejs/node@acada1fb82)] - **inspector**: ensure adequate memory allocation for `Binary::toBase64` (René) [#&#8203;59870](nodejs/node#59870)
- \[[`396cc8ec65`](nodejs/node@396cc8ec65)] - **lib**: update inspect output format for subclasses (Miguel Marcondes Filho) [#&#8203;59687](nodejs/node#59687)
- \[[`fed1dac8de`](nodejs/node@fed1dac8de)] - **lib**: update isDeepStrictEqual to support options (Miguel Marcondes Filho) [#&#8203;59762](nodejs/node#59762)
- \[[`d785929fd7`](nodejs/node@d785929fd7)] - **lib**: add source map support for assert messages (Chengzhong Wu) [#&#8203;59751](nodejs/node#59751)
- \[[`ff13d1d61e`](nodejs/node@ff13d1d61e)] - **lib,src**: cache ModuleWrap.hasAsyncGraph (Chengzhong Wu) [#&#8203;59703](nodejs/node#59703)
- \[[`b200cd8470`](nodejs/node@b200cd8470)] - **lib,src**: refactor assert to load error source from memory (Chengzhong Wu) [#&#8203;59751](nodejs/node#59751)
- \[[`e94c57301b`](nodejs/node@e94c57301b)] - **meta**: add .npmrc with ignore-scripts=true (Joyee Cheung) [#&#8203;59914](nodejs/node#59914)
- \[[`728472a57b`](nodejs/node@728472a57b)] - **module**: only put directly require-d ESM into require.cache (Joyee Cheung) [#&#8203;59874](nodejs/node#59874)
- \[[`be48760b93`](nodejs/node@be48760b93)] - **node-api**: added SharedArrayBuffer api (Mert Can Altin) [#&#8203;59071](nodejs/node#59071)
- \[[`f006a14522`](nodejs/node@f006a14522)] - **node-api**: make napi\_delete\_reference use node\_api\_basic\_env (Jeetu Suthar) [#&#8203;59684](nodejs/node#59684)
- \[[`0f46c1c3b0`](nodejs/node@0f46c1c3b0)] - **repl**: fix cpu overhead pasting big strings to the REPL (Ruben Bridgewater) [#&#8203;59857](nodejs/node#59857)
- \[[`3eeb7b47ea`](nodejs/node@3eeb7b47ea)] - **sqlite**: fix crash session extension callbacks with workers (Bart Louwers) [#&#8203;59848](nodejs/node#59848)
- \[[`0fe53375ec`](nodejs/node@0fe53375ec)] - **(SEMVER-MINOR)** **sqlite**: cleanup ERM support and export Session class (James M Snell) [#&#8203;58378](nodejs/node#58378)
- \[[`9a3e58a007`](nodejs/node@9a3e58a007)] - **(SEMVER-MINOR)** **sqlite**: add tagged template (0hm☘️) [#&#8203;58748](nodejs/node#58748)
- \[[`f14ed5ab7b`](nodejs/node@f14ed5ab7b)] - **src**: simplify watchdog instantiations via `std::optional` (Anna Henningsen) [#&#8203;59960](nodejs/node#59960)
- \[[`e330f03f84`](nodejs/node@e330f03f84)] - **src**: update crypto objects to use DictionaryTemplate (James M Snell) [#&#8203;59942](nodejs/node#59942)
- \[[`69b5607cf4`](nodejs/node@69b5607cf4)] - **src**: simplify is\_callable by making it a concept (Tobias Nießen) [#&#8203;58169](nodejs/node#58169)
- \[[`86150f3401`](nodejs/node@86150f3401)] - **src**: rename private fields to follow naming convention (Moonki Choi) [#&#8203;59923](nodejs/node#59923)
- \[[`d17f299539`](nodejs/node@d17f299539)] - **src**: use DictionaryTemplate more in URLPattern (James M Snell) [#&#8203;59892](nodejs/node#59892)
- \[[`ac784912ac`](nodejs/node@ac784912ac)] - **src**: reduce the nearest parent package JSON cache size (Michael Smith) [#&#8203;59888](nodejs/node#59888)
- \[[`abecdcb536`](nodejs/node@abecdcb536)] - **src**: replace FIXED\_ONE\_BYTE\_STRING with Environment-cached strings (Moonki Choi) [#&#8203;59891](nodejs/node#59891)
- \[[`2bb152500b`](nodejs/node@2bb152500b)] - **src**: create strings in `FIXED_ONE_BYTE_STRING` as internalized (Anna Henningsen) [#&#8203;59826](nodejs/node#59826)
- \[[`03116a7cd8`](nodejs/node@03116a7cd8)] - **src**: remove `std::array` overload of `FIXED_ONE_BYTE_STRING` (Anna Henningsen) [#&#8203;59826](nodejs/node#59826)
- \[[`8a5325d6e3`](nodejs/node@8a5325d6e3)] - **src**: ensure `v8::Eternal` is empty before setting it (Anna Henningsen) [#&#8203;59825](nodejs/node#59825)
- \[[`f0c20ccd81`](nodejs/node@f0c20ccd81)] - **src**: remove unnecessary `Environment::GetCurrent()` calls (Moonki Choi) [#&#8203;59814](nodejs/node#59814)
- \[[`213188e491`](nodejs/node@213188e491)] - **stream**: use new AsyncResource instead of bind (Matteo Collina) [#&#8203;59867](nodejs/node#59867)
- \[[`ce8435b003`](nodejs/node@ce8435b003)] - **test**: testcase demonstrating issue 59541 (Eric Rannaud) [#&#8203;59801](nodejs/node#59801)
- \[[`8f32746142`](nodejs/node@8f32746142)] - **test**: guard write to proxy client if proxy connection is ended (Joyee Cheung) [#&#8203;59742](nodejs/node#59742)
- \[[`6790093fcb`](nodejs/node@6790093fcb)] - **tls**: load bundled and extra certificates off-thread (Joyee Cheung) [#&#8203;59856](nodejs/node#59856)
- \[[`f5d3f919d8`](nodejs/node@f5d3f919d8)] - **tls**: only do off-thread certificate loading on loading tls (Joyee Cheung) [#&#8203;59856](nodejs/node#59856)
- \[[`87bbaa23a0`](nodejs/node@87bbaa23a0)] - **tools**: fix `tools/make-v8.sh` for clang (Richard Lau) [#&#8203;59893](nodejs/node#59893)
- \[[`0d23fd525b`](nodejs/node@0d23fd525b)] - **tools**: skip test-internet workflow for draft MRs (Michaël Zasso) [#&#8203;59817](nodejs/node#59817)
- \[[`e17c73731a`](nodejs/node@e17c73731a)] - **tools**: copyedit `build-tarball.yml` (Antoine du Hamel) [#&#8203;59808](nodejs/node#59808)
- \[[`97c4e1bac9`](nodejs/node@97c4e1bac9)] - **typings**: remove unused imports (Nam Yooseong) [#&#8203;59880](nodejs/node#59880)
- \[[`8b29bbca76`](nodejs/node@8b29bbca76)] - **url**: replaced slice with at (Mikhail) [#&#8203;59181](nodejs/node#59181)
- \[[`6458867a6b`](nodejs/node@6458867a6b)] - **url**: add type checking to urlToHttpOptions() (simon-id) [#&#8203;59753](nodejs/node#59753)
- \[[`3c62b3886f`](nodejs/node@3c62b3886f)] - **util**: inspect objects with throwing Symbol.toStringTag (Ruben Bridgewater) [#&#8203;59860](nodejs/node#59860)
- \[[`6133a82875`](nodejs/node@6133a82875)] - **util**: fix debuglog.enabled not being present with callback logger (Ruben Bridgewater) [#&#8203;59858](nodejs/node#59858)
- \[[`9347ddddf4`](nodejs/node@9347ddddf4)] - **vm**: explain how to share promises between contexts w/ afterEvaluate (Eric Rannaud) [#&#8203;59801](nodejs/node#59801)
- \[[`44ce971619`](nodejs/node@44ce971619)] - **vm**: "afterEvaluate", evaluate() return a promise from the outer context (Eric Rannaud) [#&#8203;59801](nodejs/node#59801)
- \[[`6e586a1409`](nodejs/node@6e586a1409)] - **vm**: expose hasTopLevelAwait on SourceTextModule (Chengzhong Wu) [#&#8203;59865](nodejs/node#59865)
- \[[`49747a58a3`](nodejs/node@49747a58a3)] - **(SEMVER-MINOR)** **worker**: add heap profile API (theanarkh) [#&#8203;59846](nodejs/node#59846)
- \[[`b970c0bbc2`](nodejs/node@b970c0bbc2)] - **zlib**: reduce code duplication (jhofstee) [#&#8203;57810](nodejs/node#57810)
- \[[`9782ca2b1b`](nodejs/node@9782ca2b1b)] - **zlib**: implement fast path for crc32 (Gürgün Dayıoğlu) [#&#8203;59813](nodejs/node#59813)

</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:eyJjcmVhdGVkSW5WZXIiOiI0MS4xMzAuMCIsInVwZGF0ZWRJblZlciI6IjQxLjEzMC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
aduh95 pushed a commit that referenced this pull request Oct 7, 2025
Use lookup table instead of regex for strings shorter than 10
characters to improve performance for common short header names
while maintaining compatibility.

PR-URL: #59832
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. 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.

10 participants