Skip to content

Commit 3bb3f8c

Browse files
committed
url: improve URLSearchParams creation performance
1 parent 1640aeb commit 3bb3f8c

File tree

1 file changed

+14
-24
lines changed

1 file changed

+14
-24
lines changed

lib/internal/url.js

+14-24
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const {
44
Array,
5+
ArrayIsArray,
56
ArrayPrototypeJoin,
67
ArrayPrototypeMap,
78
ArrayPrototypePush,
@@ -150,52 +151,44 @@ function isURLSearchParams(self) {
150151
}
151152

152153
class URLSearchParams {
154+
[searchParams] = [];
155+
156+
// "associated url object"
157+
[context] = null;
158+
153159
// URL Standard says the default value is '', but as undefined and '' have
154160
// the same result, undefined is used to prevent unnecessary parsing.
155161
// Default parameter is necessary to keep URLSearchParams.length === 0 in
156162
// accordance with Web IDL spec.
157163
constructor(init = undefined) {
158-
if (init === null || init === undefined) {
159-
this[searchParams] = [];
164+
if (init == null) {
165+
// Do nothing
160166
} else if (typeof init === 'object' || typeof init === 'function') {
161167
const method = init[SymbolIterator];
162168
if (method === this[SymbolIterator]) {
163169
// While the spec does not have this branch, we can use it as a
164170
// shortcut to avoid having to go through the costly generic iterator.
165171
const childParams = init[searchParams];
166172
this[searchParams] = childParams.slice();
167-
} else if (method !== null && method !== undefined) {
173+
} else if (method != null) {
168174
if (typeof method !== 'function') {
169175
throw new ERR_ARG_NOT_ITERABLE('Query pairs');
170176
}
171177

172178
// Sequence<sequence<USVString>>
173-
// Note: per spec we have to first exhaust the lists then process them
174-
const pairs = [];
175179
for (const pair of init) {
176-
if ((typeof pair !== 'object' && typeof pair !== 'function') ||
177-
pair === null ||
178-
typeof pair[SymbolIterator] !== 'function') {
180+
// If innerSequence's size is not 2, then throw a TypeError.
181+
if (pair == null || !ArrayIsArray(pair) || pair.length !== 2) {
179182
throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]');
180183
}
181-
const convertedPair = [];
182-
for (const element of pair)
183-
ArrayPrototypePush(convertedPair, toUSVString(element));
184-
ArrayPrototypePush(pairs, convertedPair);
185-
}
186184

187-
this[searchParams] = [];
188-
for (const pair of pairs) {
189-
if (pair.length !== 2) {
190-
throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]');
191-
}
192-
ArrayPrototypePush(this[searchParams], pair[0], pair[1]);
185+
// Append (innerSequence[0], innerSequence[1]) to querys list.
186+
ArrayPrototypePush(this[searchParams], toUSVString(pair[0]), toUSVString(pair[1]));
193187
}
194188
} else {
195189
// Record<USVString, USVString>
196190
// Need to use reflection APIs for full spec compliance.
197191
const visited = {};
198-
this[searchParams] = [];
199192
const keys = ReflectOwnKeys(init);
200193
for (let i = 0; i < keys.length; i++) {
201194
const key = keys[i];
@@ -217,13 +210,10 @@ class URLSearchParams {
217210
}
218211
}
219212
} else {
220-
// USVString
213+
// https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
221214
init = toUSVString(init);
222215
this[searchParams] = init ? parseParams(init) : [];
223216
}
224-
225-
// "associated url object"
226-
this[context] = null;
227217
}
228218

229219
[inspect.custom](recurseTimes, ctx) {

0 commit comments

Comments
 (0)