FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

url: speed up URLSearchParams by anonrig · Pull Request #65363 · nodejs/node · GitHub

/ node Public

url: speed up URLSearchParams - #65363

Merged
nodejs-github-bot merged 2 commits into
nodejs:mainfrom
anonrig:cursor/url-searchparams-performance-603e
Aug 22, 2026
Merged

url: speed up URLSearchParams#65363
nodejs-github-bot merged 2 commits into
nodejs:mainfrom
anonrig:cursor/url-searchparams-performance-603e

Conversation

anonrig commented Aug 18, 2026
edited
Loading

Copy link
Copy Markdown
Member

This speeds up WHATWG URLSearchParams without changing observable behavior.

Independent of the new URL() parse PR (#65361).

What changed

  • Parse: walk & / = with indexOf instead of a per-character state machine. When the input has no + or %, each component is a slice of the original string. Percent-decoding still runs only when a complete %HH sequence exists, so lone % and fake sequences like %© stay intact.
  • USVString: skip `${value}` when the value is already a string (constructor, append/get/set/has/delete).
  • Serialize: cache toString() until the list mutates; join encoded pairs instead of repeated +=.
  • Tests: test/parallel/test-whatwg-url-searchparams-fast-path.js covers leading ?, empty pairs, + / percent-decoding, invalid %, mutation cache invalidation, copy constructor isolation, record/sequence init, unpaired surrogates, and fake percent-encoding.

Tests

  • All test/parallel/test-whatwg-url-custom-searchparams*.js plus the new fast-path file
  • WPT test/wpt/test-url.js: 5107 passed, 0 unexpected failures

Local benches

Same binary family, both run with --no-node-snapshot (new JS is not in the V8 snapshot). Rates in ops/s:

Benchmark Before After
new URLSearchParams(string) noencode ~6.9M ~7.3M
new URLSearchParams(string) encodemany 6.9M 7.5M
new URLSearchParams(iterable) 9.9M 10.3M
toString() noencode (repeated) 7.7M ~213M
toString() encodemany (repeated) 4.9M ~200M
get() ~75M ~85M
has() ~52M ~59M

The large toString() jump is the serialization cache: the common “build params, stringify many times / read URL.href” path no longer re-encodes an unchanged list.

Ada already has a C url_search_params API. This keeps the implementation in JS to avoid a JS/C++ call on every get/append.

Assisted-by: Cursor

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/url

nodejs-github-bot added needs-ci PRs that need a full CI run. whatwg-url Issues and PRs related to the WHATWG URL implementation. labels Aug 18, 2026

codecov Bot commented Aug 18, 2026
edited
Loading

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.11%. Comparing base (f83e7df) to head (eb812ac).
⚠️ Report is 133 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #65363      +/-   ##
==========================================
- Coverage   90.31%   90.11%   -0.20%     
==========================================
  Files         751      752       +1     
  Lines      249956   251862    +1906     
  Branches    47204    47356     +152     
==========================================
+ Hits       225745   226969    +1224     
- Misses      15612    16235     +623     
- Partials     8599     8658      +59     
Files with missing lines Coverage Δ
lib/internal/url.js 93.24% <100.00%> (-0.04%) ⬇️

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

jasnell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

AI agents are not permitted to use Signed-off-by

cursor Bot force-pushed the cursor/url-searchparams-performance-603e branch from 1423a66 to e18874e Compare August 18, 2026 11:39

anonrig commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

Removed the Signed-off-by trailer from the commit(s). An AI agent cannot attest the DCO.

cursor Bot force-pushed the cursor/url-searchparams-performance-603e branch from e18874e to 9863db8 Compare August 18, 2026 12:49
Parse query strings with indexOf instead of a per-character state
machine, skip ToString when values are already strings, cache
toString() until the list mutates, and join serialized pairs.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
Leave lone '%' and non-hex percent sequences intact so serialization
matches the previous parser, and use native indexOf/slice/push on
the query-string hot path.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
cursor Bot force-pushed the cursor/url-searchparams-performance-603e branch 3 times, most recently from 18331fb to eb812ac Compare August 18, 2026 18:43
Comment thread lib/internal/url.js
}
const out = [];
// Native indexOf/slice/push outperform primordials on this tight loop.
const encoded = qs.indexOf('+', i) !== -1 || qs.indexOf('%', i) !== -1;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

nit:

Suggested change
const encoded = qs.indexOf('+', i) !== -1 || qs.indexOf('%', i) !== -1;
const hasPlus = qs.indexOf('+', i) !== -1;
const hasPercent = qs.indexOf('%', i) !== -1;
const encoded = hasPlus || hasPercent;

Comment on lines +38 to +40
}

{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

We can add edge case for fast path change
?, &&&, a=%2F%20b, a=%E2%82%AC, a=%c3%28

Suggested change
}
{
}
{
const params = new URLSearchParams('?');
assert.deepStrictEqual([...params], []);
assert.strictEqual(params.toString(), '');
}
{
const params = new URLSearchParams('&&&');
assert.deepStrictEqual([...params], []);
assert.strictEqual(params.toString(), '');
}
{
const params = new URLSearchParams('a=%2F%20b');
assert.strictEqual(params.get('a'), '/ b');
assert.strictEqual(params.toString(), 'a=%2F+b');
}
{
const params = new URLSearchParams('a=%E2%82%AC');
assert.strictEqual(params.get('a'), '€');
assert.strictEqual(params.toString(), 'a=%E2%82%AC');
}
{
const params = new URLSearchParams('a=%c3%28');
assert.strictEqual(params.get('a'), '%c3%28');
assert.strictEqual(params.toString(), 'a=%25c3%2528');
}
{

mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

lgtm

mcollina added request-ci Add this label to start a Jenkins CI on a PR. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Aug 21, 2026
github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 21, 2026

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator

gurgunday left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Lgtm

mcollina added the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 21, 2026

mohamedelhalosy2023-stack left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

ه

nodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Aug 21, 2026

Copy link
Copy Markdown
Collaborator
Commit Queue failed
- Loading data for nodejs/node/pull/65363
✔  Done loading data for nodejs/node/pull/65363
----------------------------------- PR info ------------------------------------
Title      url: speed up URLSearchParams (#65363)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     anonrig:cursor/url-searchparams-performance-603e -> nodejs:main
Labels     whatwg-url, needs-ci, commit-queue, commit-queue-squash
Commits    2
 - url: speed up URLSearchParams
 - url: only percent-decode complete %HH sequences
Committers 1
 - Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: https://github.com/nodejs/node/pull/65363
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Aviv Keller <me@aviv.sh>
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/65363
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Aviv Keller <me@aviv.sh>
--------------------------------------------------------------------------------
   ℹ  This PR was created on Tue, 18 Aug 2026 01:38:00 GMT
   ✔  Approvals: 3
   ✔  - Matteo Collina (@mcollina) (TSC): https://github.com/nodejs/node/pull/65363#pullrequestreview-4988761883
   ✔  - Gürgün Dayıoğlu (@gurgunday): https://github.com/nodejs/node/pull/65363#pullrequestreview-4996082466
   ✔  - Aviv Keller (@avivkeller): https://github.com/nodejs/node/pull/65363#pullrequestreview-4996124171
   ✘  GitHub CI is still running
   ℹ  Last Full PR CI on 2026-08-21T15:26:43Z: https://ci.nodejs.org/job/node-test-pull-request/76158/
- Querying data for job/node-test-pull-request/76158/
✔  Build data downloaded
   ✘  Last Jenkins CI still running
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/32519106371

This comment was marked as spam.

Copy link
Copy Markdown
Collaborator

anonrig added commit-queue Add this label to land a pull request using GitHub Actions. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. labels Aug 22, 2026
nodejs-github-bot merged commit 4b3bba5 into nodejs:main Aug 22, 2026
100 of 102 checks passed

Copy link
Copy Markdown
Collaborator

Landed in 4b3bba5

nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Aug 22, 2026
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
Parse query strings with indexOf instead of a per-character state
machine, skip ToString when values are already strings, cache
toString() until the list mutates, and join serialized pairs.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
PR-URL: #65363
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Aviv Keller <me@aviv.sh>
aduh95 pushed a commit that referenced this pull request Aug 25, 2026
Parse query strings with indexOf instead of a per-character state
machine, skip ToString when values are already strings, cache
toString() until the list mutates, and join serialized pairs.

Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: Cursor
PR-URL: #65363
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Aviv Keller <me@aviv.sh>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. needs-ci PRs that need a full CI run. whatwg-url Issues and PRs related to the WHATWG URL implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants


Back | FazBrowse Home | New Git URL