Uh oh!
There was an error while loading. Please reload this page.
url: speed up URLSearchParams - #65363
Conversation
nodejs-github-bot
commented
Aug 18, 2026
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 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
🚀 New features to boost your workflow:
|
jasnell
left a comment
There was a problem hiding this comment.
AI agents are not permitted to use Signed-off-by
1423a66 to
e18874eCompareanonrig
commented
Aug 18, 2026
Removed the |
e18874e to
9863db8CompareParse 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
18331fb to
eb812acCompare| } | ||
| const out = []; | ||
| // Native indexOf/slice/push outperform primordials on this tight loop. | ||
| const encoded = qs.indexOf('+', i) !== -1 || qs.indexOf('%', i) !== -1; |
There was a problem hiding this comment.
nit:
| constencoded=qs.indexOf('+',i)!==-1||qs.indexOf('%',i)!==-1; | |
| consthasPlus=qs.indexOf('+',i)!==-1; | |
| consthasPercent=qs.indexOf('%',i)!==-1; | |
| constencoded=hasPlus||hasPercent; |
| } | ||
| { |
There was a problem hiding this comment.
We can add edge case for fast path change?, &&&, a=%2F%20b, a=%E2%82%AC, a=%c3%28
| } | |
| { | |
| } | |
| { | |
| constparams=newURLSearchParams('?'); | |
| assert.deepStrictEqual([...params],[]); | |
| assert.strictEqual(params.toString(),''); | |
| } | |
| { | |
| constparams=newURLSearchParams('&&&'); | |
| assert.deepStrictEqual([...params],[]); | |
| assert.strictEqual(params.toString(),''); | |
| } | |
| { | |
| constparams=newURLSearchParams('a=%2F%20b'); | |
| assert.strictEqual(params.get('a'),'/ b'); | |
| assert.strictEqual(params.toString(),'a=%2F+b'); | |
| } | |
| { | |
| constparams=newURLSearchParams('a=%E2%82%AC'); | |
| assert.strictEqual(params.get('a'),'€'); | |
| assert.strictEqual(params.toString(),'a=%E2%82%AC'); | |
| } | |
| { | |
| constparams=newURLSearchParams('a=%c3%28'); | |
| assert.strictEqual(params.get('a'),'%c3%28'); | |
| assert.strictEqual(params.toString(),'a=%25c3%2528'); | |
| } | |
| { |
This comment was marked as outdated.
This comment was marked as outdated.
nodejs-github-bot
commented
Aug 21, 2026
nodejs-github-bot
commented
Aug 21, 2026
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/.ncuhttps://github.com/nodejs/node/actions/runs/32519106371 |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
nodejs-github-bot
commented
Aug 22, 2026
Uh oh!
There was an error while loading. Please reload this page.
nodejs-github-bot
commented
Aug 22, 2026
Landed in 4b3bba5 |
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>
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>
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 speeds up WHATWG
URLSearchParamswithout changing observable behavior.Independent of the
new URL()parse PR (#65361).What changed
&/=withindexOfinstead 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%HHsequence exists, so lone%and fake sequences like%©stay intact.`${value}`when the value is already a string (constructor,append/get/set/has/delete).toString()until the list mutates; join encoded pairs instead of repeated+=.test/parallel/test-whatwg-url-searchparams-fast-path.jscovers leading?, empty pairs,+/ percent-decoding, invalid%, mutation cache invalidation, copy constructor isolation, record/sequence init, unpaired surrogates, and fake percent-encoding.Tests
test/parallel/test-whatwg-url-custom-searchparams*.jsplus the new fast-path filetest/wpt/test-url.js: 5107 passed, 0 unexpected failuresLocal benches
Same binary family, both run with
--no-node-snapshot(new JS is not in the V8 snapshot). Rates in ops/s:new URLSearchParams(string)noencodenew URLSearchParams(string)encodemanynew URLSearchParams(iterable)toString()noencode (repeated)toString()encodemany (repeated)get()has()The large
toString()jump is the serialization cache: the common “build params, stringify many times / readURL.href” path no longer re-encodes an unchanged list.Ada already has a C
url_search_paramsAPI. This keeps the implementation in JS to avoid a JS/C++ call on everyget/append.Assisted-by: Cursor