Skip to content

Commit dc80660

Browse files
committed
url: offload URLSearchParams initialization
1 parent 69148f0 commit dc80660

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

lib/internal/url.js

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const FORWARD_SLASH = /\//g;
100100

101101
const context = Symbol('context');
102102
const searchParams = Symbol('query');
103+
const kDirty = Symbol('dirty');
103104

104105
const updateActions = {
105106
kProtocol: 0,
@@ -224,11 +225,12 @@ class URLSearchParams {
224225
} else {
225226
// USVString
226227
init = toUSVString(init);
227-
initSearchParams(this, init);
228+
this[searchParams] = init ? parseParams(init) : [];
228229
}
229230

230231
// "associated url object"
231232
this[context] = null;
233+
this[kDirty] = false;
232234
}
233235

234236
[inspect.custom](recurseTimes, ctx) {
@@ -545,6 +547,7 @@ class URL {
545547
input = `${input}`;
546548
this[context] = new URLContext();
547549
this.#onParseComplete = FunctionPrototypeBind(this.#onParseComplete, this);
550+
this.#onSearchUpdate = FunctionPrototypeBind(this.#onSearchUpdate, this);
548551

549552
if (base !== undefined) {
550553
base = `${base}`;
@@ -604,11 +607,34 @@ class URL {
604607
ctx.password = password;
605608
ctx.port = port;
606609
ctx.hash = hash;
607-
if (!this[searchParams]) { // Invoked from URL constructor
608-
this[searchParams] = new URLSearchParams();
610+
if (this[searchParams]) {
611+
// Update `kDirty` property to recalculate searchParams on access.
612+
// This is done to reduce the overhead of initializing the URL.
613+
this[searchParams][kDirty] = true;
614+
}
615+
};
616+
617+
#onSearchUpdate = (href, origin, protocol, hostname, pathname,
618+
search, username, password, port, hash) => {
619+
const ctx = this[context];
620+
ctx.href = href;
621+
ctx.origin = origin;
622+
ctx.protocol = protocol;
623+
ctx.hostname = hostname;
624+
ctx.pathname = pathname;
625+
ctx.search = search;
626+
ctx.username = username;
627+
ctx.password = password;
628+
ctx.port = port;
629+
ctx.hash = hash;
630+
631+
if (this[searchParams] == null) {
632+
this[searchParams] = new URLSearchParams(this[context].search);
609633
this[searchParams][context] = this;
634+
} else {
635+
this[searchParams][searchParams] = this[context].search ? parseParams(this[context].search) : [];
636+
this[searchParams][kDirty] = false;
610637
}
611-
initSearchParams(this[searchParams], ctx.search);
612638
};
613639

614640
toString() {
@@ -729,18 +755,25 @@ class URL {
729755
return this[context].search;
730756
}
731757

732-
set search(search) {
758+
set search(value) {
733759
if (!isURLThis(this))
734760
throw new ERR_INVALID_THIS('URL');
735-
search = toUSVString(search);
736-
updateUrl(this[context].href, updateActions.kSearch, search, this.#onParseComplete);
737-
initSearchParams(this[searchParams], this[context].search);
761+
updateUrl(this[context].href, updateActions.kSearch, toUSVString(value), this.#onSearchUpdate);
738762
}
739763

740764
// readonly
741765
get searchParams() {
742766
if (!isURLThis(this))
743767
throw new ERR_INVALID_THIS('URL');
768+
// Create URLSearchParams on demand to greatly improve the URL performance.
769+
if (this[searchParams] == null) {
770+
this[searchParams] = new URLSearchParams(this[context].search);
771+
this[searchParams][context] = this;
772+
} else if (this[searchParams][kDirty]) {
773+
const updated = this[context].search;
774+
this[searchParams][searchParams] = updated ? parseParams(updated) : [];
775+
this[searchParams][kDirty] = false;
776+
}
744777
return this[searchParams];
745778
}
746779

@@ -815,14 +848,6 @@ ObjectDefineProperties(URL, {
815848
revokeObjectURL: kEnumerableProperty,
816849
});
817850

818-
function initSearchParams(url, init) {
819-
if (!init) {
820-
url[searchParams] = [];
821-
return;
822-
}
823-
url[searchParams] = parseParams(init);
824-
}
825-
826851
// application/x-www-form-urlencoded parser
827852
// Ref: https://url.spec.whatwg.org/#concept-urlencoded-parser
828853
function parseParams(qs) {

0 commit comments

Comments
 (0)