Skip to content

Commit c79e1b7

Browse files
anonrigdanielleadams
authored andcommitted
url: offload URLSearchParams initialization
PR-URL: #46867 Backport-PR-URL: #48345 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Filip Skokan <panva.ip@gmail.com>
1 parent 3db235b commit c79e1b7

File tree

4 files changed

+50
-53
lines changed

4 files changed

+50
-53
lines changed

lib/_http_client.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const {
6363
const Agent = require('_http_agent');
6464
const { Buffer } = require('buffer');
6565
const { defaultTriggerAsyncIdScope } = require('internal/async_hooks');
66-
const { URL, urlToHttpOptions, searchParamsSymbol } = require('internal/url');
66+
const { URL, urlToHttpOptions, isURL } = require('internal/url');
6767
const {
6868
kOutHeaders,
6969
kNeedDrain,
@@ -138,8 +138,7 @@ function ClientRequest(input, options, cb) {
138138
if (typeof input === 'string') {
139139
const urlStr = input;
140140
input = urlToHttpOptions(new URL(urlStr));
141-
} else if (input && input[searchParamsSymbol] &&
142-
input[searchParamsSymbol][searchParamsSymbol]) {
141+
} else if (isURL(input)) {
143142
// url.URL instance
144143
input = urlToHttpOptions(input);
145144
} else {

lib/https.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const { ClientRequest } = require('_http_client');
5252
let debug = require('internal/util/debuglog').debuglog('https', (fn) => {
5353
debug = fn;
5454
});
55-
const { URL, urlToHttpOptions, searchParamsSymbol } = require('internal/url');
55+
const { URL, urlToHttpOptions, isURL } = require('internal/url');
5656

5757
function Server(opts, requestListener) {
5858
if (!(this instanceof Server)) return new Server(opts, requestListener);
@@ -344,9 +344,7 @@ function request(...args) {
344344
if (typeof args[0] === 'string') {
345345
const urlStr = ArrayPrototypeShift(args);
346346
options = urlToHttpOptions(new URL(urlStr));
347-
} else if (args[0] && args[0][searchParamsSymbol] &&
348-
args[0][searchParamsSymbol][searchParamsSymbol]) {
349-
// url.URL instance
347+
} else if (isURL(args[0])) {
350348
options = urlToHttpOptions(ArrayPrototypeShift(args));
351349
}
352350

lib/internal/url.js

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class URLSearchParams {
250250
} else {
251251
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
252252
init = toUSVString(init);
253-
initSearchParams(this, init);
253+
this[searchParams] = init ? parseParams(init) : [];
254254
}
255255
}
256256

@@ -557,7 +557,7 @@ ObjectDefineProperties(URLSearchParams.prototype, {
557557
},
558558
});
559559

560-
function isURLThis(self) {
560+
function isURL(self) {
561561
return self != null && ObjectPrototypeHasOwnProperty(self, context);
562562
}
563563

@@ -625,160 +625,161 @@ class URL {
625625
ctx.password = password;
626626
ctx.port = port;
627627
ctx.hash = hash;
628-
if (!this[searchParams]) { // Invoked from URL constructor
629-
this[searchParams] = new URLSearchParams();
630-
this[searchParams][context] = this;
628+
if (this[searchParams]) {
629+
this[searchParams][searchParams] = parseParams(search);
631630
}
632-
initSearchParams(this[searchParams], ctx.search);
633631
};
634632

635633
toString() {
636-
if (!isURLThis(this))
634+
if (!isURL(this))
637635
throw new ERR_INVALID_THIS('URL');
638636
return this[context].href;
639637
}
640638

641639
get href() {
642-
if (!isURLThis(this))
640+
if (!isURL(this))
643641
throw new ERR_INVALID_THIS('URL');
644642
return this[context].href;
645643
}
646644

647645
set href(value) {
648-
if (!isURLThis(this))
646+
if (!isURL(this))
649647
throw new ERR_INVALID_THIS('URL');
650648
const valid = updateUrl(this[context].href, updateActions.kHref, `${value}`, this.#onParseComplete);
651649
if (!valid) { throw ERR_INVALID_URL(`${value}`); }
652650
}
653651

654652
// readonly
655653
get origin() {
656-
if (!isURLThis(this))
654+
if (!isURL(this))
657655
throw new ERR_INVALID_THIS('URL');
658656
return this[context].origin;
659657
}
660658

661659
get protocol() {
662-
if (!isURLThis(this))
660+
if (!isURL(this))
663661
throw new ERR_INVALID_THIS('URL');
664662
return this[context].protocol;
665663
}
666664

667665
set protocol(value) {
668-
if (!isURLThis(this))
666+
if (!isURL(this))
669667
throw new ERR_INVALID_THIS('URL');
670668
updateUrl(this[context].href, updateActions.kProtocol, `${value}`, this.#onParseComplete);
671669
}
672670

673671
get username() {
674-
if (!isURLThis(this))
672+
if (!isURL(this))
675673
throw new ERR_INVALID_THIS('URL');
676674
return this[context].username;
677675
}
678676

679677
set username(value) {
680-
if (!isURLThis(this))
678+
if (!isURL(this))
681679
throw new ERR_INVALID_THIS('URL');
682680
updateUrl(this[context].href, updateActions.kUsername, `${value}`, this.#onParseComplete);
683681
}
684682

685683
get password() {
686-
if (!isURLThis(this))
684+
if (!isURL(this))
687685
throw new ERR_INVALID_THIS('URL');
688686
return this[context].password;
689687
}
690688

691689
set password(value) {
692-
if (!isURLThis(this))
690+
if (!isURL(this))
693691
throw new ERR_INVALID_THIS('URL');
694692
updateUrl(this[context].href, updateActions.kPassword, `${value}`, this.#onParseComplete);
695693
}
696694

697695
get host() {
698-
if (!isURLThis(this))
696+
if (!isURL(this))
699697
throw new ERR_INVALID_THIS('URL');
700698
const port = this[context].port;
701699
const suffix = port.length > 0 ? `:${port}` : '';
702700
return this[context].hostname + suffix;
703701
}
704702

705703
set host(value) {
706-
if (!isURLThis(this))
704+
if (!isURL(this))
707705
throw new ERR_INVALID_THIS('URL');
708706
updateUrl(this[context].href, updateActions.kHost, `${value}`, this.#onParseComplete);
709707
}
710708

711709
get hostname() {
712-
if (!isURLThis(this))
710+
if (!isURL(this))
713711
throw new ERR_INVALID_THIS('URL');
714712
return this[context].hostname;
715713
}
716714

717715
set hostname(value) {
718-
if (!isURLThis(this))
716+
if (!isURL(this))
719717
throw new ERR_INVALID_THIS('URL');
720718
updateUrl(this[context].href, updateActions.kHostname, `${value}`, this.#onParseComplete);
721719
}
722720

723721
get port() {
724-
if (!isURLThis(this))
722+
if (!isURL(this))
725723
throw new ERR_INVALID_THIS('URL');
726724
return this[context].port;
727725
}
728726

729727
set port(value) {
730-
if (!isURLThis(this))
728+
if (!isURL(this))
731729
throw new ERR_INVALID_THIS('URL');
732730
updateUrl(this[context].href, updateActions.kPort, `${value}`, this.#onParseComplete);
733731
}
734732

735733
get pathname() {
736-
if (!isURLThis(this))
734+
if (!isURL(this))
737735
throw new ERR_INVALID_THIS('URL');
738736
return this[context].pathname;
739737
}
740738

741739
set pathname(value) {
742-
if (!isURLThis(this))
740+
if (!isURL(this))
743741
throw new ERR_INVALID_THIS('URL');
744742
updateUrl(this[context].href, updateActions.kPathname, `${value}`, this.#onParseComplete);
745743
}
746744

747745
get search() {
748-
if (!isURLThis(this))
746+
if (!isURL(this))
749747
throw new ERR_INVALID_THIS('URL');
750748
return this[context].search;
751749
}
752750

753-
set search(search) {
754-
if (!isURLThis(this))
751+
set search(value) {
752+
if (!isURL(this))
755753
throw new ERR_INVALID_THIS('URL');
756-
search = toUSVString(search);
757-
updateUrl(this[context].href, updateActions.kSearch, search, this.#onParseComplete);
758-
initSearchParams(this[searchParams], this[context].search);
754+
updateUrl(this[context].href, updateActions.kSearch, toUSVString(value), this.#onParseComplete);
759755
}
760756

761757
// readonly
762758
get searchParams() {
763-
if (!isURLThis(this))
759+
if (!isURL(this))
764760
throw new ERR_INVALID_THIS('URL');
761+
// Create URLSearchParams on demand to greatly improve the URL performance.
762+
if (this[searchParams] == null) {
763+
this[searchParams] = new URLSearchParams(this[context].search);
764+
this[searchParams][context] = this;
765+
}
765766
return this[searchParams];
766767
}
767768

768769
get hash() {
769-
if (!isURLThis(this))
770+
if (!isURL(this))
770771
throw new ERR_INVALID_THIS('URL');
771772
return this[context].hash;
772773
}
773774

774775
set hash(value) {
775-
if (!isURLThis(this))
776+
if (!isURL(this))
776777
throw new ERR_INVALID_THIS('URL');
777778
updateUrl(this[context].href, updateActions.kHash, `${value}`, this.#onParseComplete);
778779
}
779780

780781
toJSON() {
781-
if (!isURLThis(this))
782+
if (!isURL(this))
782783
throw new ERR_INVALID_THIS('URL');
783784
return this[context].href;
784785
}
@@ -836,14 +837,6 @@ ObjectDefineProperties(URL, {
836837
revokeObjectURL: kEnumerableProperty,
837838
});
838839

839-
function initSearchParams(url, init) {
840-
if (!init) {
841-
url[searchParams] = [];
842-
return;
843-
}
844-
url[searchParams] = parseParams(init);
845-
}
846-
847840
// application/x-www-form-urlencoded parser
848841
// Ref: https://url.spec.whatwg.org/#concept-urlencoded-parser
849842
function parseParams(qs) {
@@ -1168,9 +1161,9 @@ function urlToHttpOptions(url) {
11681161
__proto__: null,
11691162
...url, // In case the url object was extended by the user.
11701163
protocol: url.protocol,
1171-
hostname: typeof url.hostname === 'string' && StringPrototypeStartsWith(hostname, '[') ?
1172-
StringPrototypeSlice(hostname, 1, -1) :
1173-
hostname,
1164+
hostname: url.hostname && StringPrototypeStartsWith(url.hostname, '[') ?
1165+
StringPrototypeSlice(url.hostname, 1, -1) :
1166+
url.hostname,
11741167
hash: url.hash,
11751168
search: search,
11761169
pathname: pathname,
@@ -1339,6 +1332,6 @@ module.exports = {
13391332
domainToASCII,
13401333
domainToUnicode,
13411334
urlToHttpOptions,
1342-
searchParamsSymbol: searchParams,
13431335
encodeStr,
1336+
isURL,
13441337
};

test/parallel/test-whatwg-url-properties.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ const { URL, URLSearchParams, format } = require('url');
7373
assert.strictEqual(params.size, 3);
7474
}
7575

76+
{
77+
const u = new URL('https://abc.com/?q=old');
78+
const s = u.searchParams;
79+
u.href = 'http://abc.com/?q=new';
80+
assert.strictEqual(s.get('q'), 'new');
81+
}
82+
7683
function stringifyName(name) {
7784
if (typeof name === 'symbol') {
7885
const { description } = name;

0 commit comments

Comments
 (0)