url: optimize URLSearchParams set/delete duplicate handling

PR-URL: https://github.com/nodejs/node/pull/62266
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
This commit is contained in:
Gürgün Dayıoğlu authored and GitHub committed 2026-04-26 09:04:48 +00:00
1 parent 44f9fc3643
commit c20269679e
2 files changed
+78 -14

No files matched your search

@@ -0,0 +1,43 @@
'use strict';
const common = require('../common.js');
const bench = common.createBenchmark(main, {
method: ['set', 'delete'],
type: ['unique', 'duplicates'],
count: [10, 1000],
n: [1e4],
});
function buildSeed(type, count) {
const parts = new Array(count);
if (type === 'duplicates') {
for (let i = 0; i < count; i++) {
parts[i] = `dup=${i}`;
}
} else {
for (let i = 0; i < count; i++) {
parts[i] = `k${i}=${i}`;
}
}
return new URLSearchParams(parts.join('&'));
}
function main({ method, type, count, n }) {
const seed = buildSeed(type, count);
const key = type === 'duplicates' ? 'dup' : 'k0';
const mutate = method === 'set' ?
(params) => params.set(key, 'updated') :
(params) => params.delete(key);
for (let i = 0; i < 1e3; i++) {
mutate(new URLSearchParams(seed));
}
bench.start();
for (let i = 0; i < n; i++) {
mutate(new URLSearchParams(seed));
}
bench.end(n);
}
+35 -14
View File
@@ -495,26 +495,37 @@ class URLSearchParams {
const list = this.#searchParams;
name = StringPrototypeToWellFormed(`${name}`);
const { length } = list;
let write = 0;
if (value !== undefined) {
value = StringPrototypeToWellFormed(`${value}`);
for (let i = 0; i < list.length;) {
for (let i = 0; i < length; i += 2) {
if (list[i] === name && list[i + 1] === value) {
list.splice(i, 2);
} else {
i += 2;
continue;
}
if (write !== i) {
list[write] = list[i];
list[write + 1] = list[i + 1];
}
write += 2;
}
} else {
for (let i = 0; i < list.length;) {
for (let i = 0; i < length; i += 2) {
if (list[i] === name) {
list.splice(i, 2);
} else {
i += 2;
continue;
}
if (write !== i) {
list[write] = list[i];
list[write + 1] = list[i + 1];
}
write += 2;
}
}
if (write !== length)
list.length = write;
if (this.#context) {
setURLSearchParamsModified(this.#context);
}
@@ -594,24 +605,34 @@ class URLSearchParams {
const list = this.#searchParams;
name = StringPrototypeToWellFormed(`${name}`);
value = StringPrototypeToWellFormed(`${value}`);
const { length } = list;
// If there are any name-value pairs whose name is `name`, in `list`, set
// the value of the first such name-value pair to `value` and remove the
// others.
let found = false;
for (let i = 0; i < list.length;) {
let write = 0;
for (let i = 0; i < length; i += 2) {
const cur = list[i];
let keep = true;
if (cur === name) {
if (!found) {
list[i + 1] = value;
list[write] = cur;
list[write + 1] = value;
found = true;
i += 2;
} else {
list.splice(i, 2);
keep = false;
}
} else {
i += 2;
} else if (write !== i) {
list[write] = cur;
list[write + 1] = list[i + 1];
}
if (keep)
write += 2;
}
if (found && write !== length) {
list.length = write;
}
// Otherwise, append a new name-value pair whose name is `name` and value