Skip to content

Commit c8b2218

Browse files
aduh95targos
authored andcommitted
url: refactor to use more primordials
PR-URL: #36316 Reviewed-By: Rich Trott <[email protected]>
1 parent 9ae2a27 commit c8b2218

File tree

1 file changed

+89
-59
lines changed

1 file changed

+89
-59
lines changed

lib/internal/url.js

+89-59
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
const {
44
Array,
5+
ArrayPrototypeJoin,
6+
ArrayPrototypeMap,
7+
ArrayPrototypePush,
8+
ArrayPrototypeReduce,
9+
ArrayPrototypeSlice,
10+
FunctionPrototypeBind,
511
Int8Array,
612
Number,
713
ObjectCreate,
@@ -10,9 +16,17 @@ const {
1016
ObjectGetOwnPropertySymbols,
1117
ObjectGetPrototypeOf,
1218
ObjectKeys,
19+
ReflectApply,
1320
ReflectGetOwnPropertyDescriptor,
1421
ReflectOwnKeys,
22+
RegExpPrototypeExec,
1523
String,
24+
StringPrototypeCharCodeAt,
25+
StringPrototypeIncludes,
26+
StringPrototypeReplace,
27+
StringPrototypeSlice,
28+
StringPrototypeSplit,
29+
StringPrototypeStartsWith,
1630
Symbol,
1731
SymbolIterator,
1832
SymbolToStringTag,
@@ -101,7 +115,7 @@ function toUSVString(val) {
101115
const str = `${val}`;
102116
// As of V8 5.5, `str.search()` (and `unpairedSurrogateRe[@@search]()`) are
103117
// slower than `unpairedSurrogateRe.exec()`.
104-
const match = unpairedSurrogateRe.exec(str);
118+
const match = RegExpPrototypeExec(unpairedSurrogateRe, str);
105119
if (!match)
106120
return str;
107121
return _toUSVString(str, match.index);
@@ -166,16 +180,16 @@ class URLSearchParams {
166180
}
167181
const convertedPair = [];
168182
for (const element of pair)
169-
convertedPair.push(toUSVString(element));
170-
pairs.push(convertedPair);
183+
ArrayPrototypePush(convertedPair, toUSVString(element));
184+
ArrayPrototypePush(pairs, convertedPair);
171185
}
172186

173187
this[searchParams] = [];
174188
for (const pair of pairs) {
175189
if (pair.length !== 2) {
176190
throw new ERR_INVALID_TUPLE('Each query pair', '[name, value]');
177191
}
178-
this[searchParams].push(pair[0], pair[1]);
192+
ArrayPrototypePush(this[searchParams], pair[0], pair[1]);
179193
}
180194
} else {
181195
// Record<USVString, USVString>
@@ -221,16 +235,21 @@ class URLSearchParams {
221235
const list = this[searchParams];
222236
const output = [];
223237
for (let i = 0; i < list.length; i += 2)
224-
output.push(`${innerInspect(list[i])} => ${innerInspect(list[i + 1])}`);
238+
ArrayPrototypePush(
239+
output,
240+
`${innerInspect(list[i])} => ${innerInspect(list[i + 1])}`);
225241

226-
const length = output.reduce(
242+
const length = ArrayPrototypeReduce(
243+
output,
227244
(prev, cur) => prev + removeColors(cur).length + separator.length,
228245
-separator.length
229246
);
230247
if (length > ctx.breakLength) {
231-
return `${this.constructor.name} {\n ${output.join(',\n ')} }`;
248+
return `${this.constructor.name} {\n` +
249+
` ${ArrayPrototypeJoin(output, ',\n ')} }`;
232250
} else if (output.length) {
233-
return `${this.constructor.name} { ${output.join(separator)} }`;
251+
return `${this.constructor.name} { ` +
252+
`${ArrayPrototypeJoin(output, separator)} }`;
234253
}
235254
return `${this.constructor.name} {}`;
236255
}
@@ -290,9 +309,9 @@ function onParsePortComplete(flags, protocol, username, password,
290309

291310
function onParseHostComplete(flags, protocol, username, password,
292311
host, port, path, query, fragment) {
293-
onParseHostnameComplete.apply(this, arguments);
312+
ReflectApply(onParseHostnameComplete, this, arguments);
294313
if (port !== null || ((flags & URL_FLAGS_IS_DEFAULT_SCHEME_PORT) !== 0))
295-
onParsePortComplete.apply(this, arguments);
314+
ReflectApply(onParsePortComplete, this, arguments);
296315
}
297316

298317
function onParsePathComplete(flags, protocol, username, password,
@@ -332,8 +351,8 @@ class URL {
332351
base_context = new URL(base)[context];
333352
}
334353
this[context] = new URLContext();
335-
parse(input, -1, base_context, undefined, onParseComplete.bind(this),
336-
onParseError);
354+
parse(input, -1, base_context, undefined,
355+
FunctionPrototypeBind(onParseComplete, this), onParseError);
337356
}
338357

339358
get [special]() {
@@ -454,8 +473,8 @@ ObjectDefineProperties(URL.prototype, {
454473
set(input) {
455474
// toUSVString is not needed.
456475
input = `${input}`;
457-
parse(input, -1, undefined, undefined, onParseComplete.bind(this),
458-
onParseError);
476+
parse(input, -1, undefined, undefined,
477+
FunctionPrototypeBind(onParseComplete, this), onParseError);
459478
}
460479
},
461480
origin: { // readonly
@@ -502,7 +521,7 @@ ObjectDefineProperties(URL.prototype, {
502521
return;
503522
}
504523
parse(scheme, kSchemeStart, null, ctx,
505-
onParseProtocolComplete.bind(this));
524+
FunctionPrototypeBind(onParseProtocolComplete, this));
506525
}
507526
},
508527
username: {
@@ -565,7 +584,8 @@ ObjectDefineProperties(URL.prototype, {
565584
// Cannot set the host if cannot-be-base is set
566585
return;
567586
}
568-
parse(host, kHost, null, ctx, onParseHostComplete.bind(this));
587+
parse(host, kHost, null, ctx,
588+
FunctionPrototypeBind(onParseHostComplete, this));
569589
}
570590
},
571591
hostname: {
@@ -602,7 +622,8 @@ ObjectDefineProperties(URL.prototype, {
602622
ctx.port = null;
603623
return;
604624
}
605-
parse(port, kPort, null, ctx, onParsePortComplete.bind(this));
625+
parse(port, kPort, null, ctx,
626+
FunctionPrototypeBind(onParsePortComplete, this));
606627
}
607628
},
608629
pathname: {
@@ -614,7 +635,7 @@ ObjectDefineProperties(URL.prototype, {
614635
return ctx.path[0];
615636
if (ctx.path.length === 0)
616637
return '';
617-
return `/${ctx.path.join('/')}`;
638+
return `/${ArrayPrototypeJoin(ctx.path, '/')}`;
618639
},
619640
set(path) {
620641
// toUSVString is not needed.
@@ -641,11 +662,12 @@ ObjectDefineProperties(URL.prototype, {
641662
ctx.query = null;
642663
ctx.flags &= ~URL_FLAGS_HAS_QUERY;
643664
} else {
644-
if (search[0] === '?') search = search.slice(1);
665+
if (search[0] === '?') search = StringPrototypeSlice(search, 1);
645666
ctx.query = '';
646667
ctx.flags |= URL_FLAGS_HAS_QUERY;
647668
if (search) {
648-
parse(search, kQuery, null, ctx, onParseSearchComplete.bind(this));
669+
parse(search, kQuery, null, ctx,
670+
FunctionPrototypeBind(onParseSearchComplete, this));
649671
}
650672
}
651673
initSearchParams(this[searchParams], search);
@@ -676,10 +698,11 @@ ObjectDefineProperties(URL.prototype, {
676698
ctx.flags &= ~URL_FLAGS_HAS_FRAGMENT;
677699
return;
678700
}
679-
if (hash[0] === '#') hash = hash.slice(1);
701+
if (hash[0] === '#') hash = StringPrototypeSlice(hash, 1);
680702
ctx.fragment = '';
681703
ctx.flags |= URL_FLAGS_HAS_FRAGMENT;
682-
parse(hash, kFragment, null, ctx, onParseHashComplete.bind(this));
704+
parse(hash, kFragment, null, ctx,
705+
FunctionPrototypeBind(onParseHashComplete, this));
683706
}
684707
},
685708
toJSON: {
@@ -728,7 +751,7 @@ function parseParams(qs) {
728751
let encodeCheck = 0;
729752
let i;
730753
for (i = 0; i < qs.length; ++i) {
731-
const code = qs.charCodeAt(i);
754+
const code = StringPrototypeCharCodeAt(qs, i);
732755

733756
// Try matching key/value pair separator
734757
if (code === CHAR_AMPERSAND) {
@@ -776,7 +799,7 @@ function parseParams(qs) {
776799
// Handle + and percent decoding.
777800
if (code === CHAR_PLUS) {
778801
if (lastPos < i)
779-
buf += qs.slice(lastPos, i);
802+
buf += StringPrototypeSlice(qs, lastPos, i);
780803
buf += ' ';
781804
lastPos = i + 1;
782805
} else if (!encoded) {
@@ -804,14 +827,14 @@ function parseParams(qs) {
804827
return out;
805828

806829
if (lastPos < i)
807-
buf += qs.slice(lastPos, i);
830+
buf += StringPrototypeSlice(qs, lastPos, i);
808831
if (encoded)
809832
buf = querystring.unescape(buf);
810-
out.push(buf);
833+
ArrayPrototypePush(out, buf);
811834

812835
// If `buf` is the key, add an empty value.
813836
if (!seenSep)
814-
out.push('');
837+
ArrayPrototypePush(out, '');
815838

816839
return out;
817840
}
@@ -925,7 +948,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', {
925948

926949
name = toUSVString(name);
927950
value = toUSVString(value);
928-
this[searchParams].push(name, value);
951+
ArrayPrototypePush(this[searchParams], name, value);
929952
update(this[context], this);
930953
},
931954

@@ -1039,7 +1062,7 @@ defineIDLClass(URLSearchParams.prototype, 'URLSearchParams', {
10391062
// Otherwise, append a new name-value pair whose name is `name` and value
10401063
// is `value`, to `list`.
10411064
if (!found) {
1042-
list.push(name, value);
1065+
ArrayPrototypePush(list, name, value);
10431066
}
10441067

10451068
update(this[context], this);
@@ -1225,24 +1248,28 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParams Iterator', {
12251248
kind,
12261249
index
12271250
} = this[context];
1228-
const output = target[searchParams].slice(index).reduce((prev, cur, i) => {
1229-
const key = i % 2 === 0;
1230-
if (kind === 'key' && key) {
1231-
prev.push(cur);
1232-
} else if (kind === 'value' && !key) {
1233-
prev.push(cur);
1234-
} else if (kind === 'key+value' && !key) {
1235-
prev.push([target[searchParams][index + i - 1], cur]);
1236-
}
1237-
return prev;
1238-
}, []);
1251+
const output = ArrayPrototypeReduce(
1252+
ArrayPrototypeSlice(target[searchParams], index),
1253+
(prev, cur, i) => {
1254+
const key = i % 2 === 0;
1255+
if (kind === 'key' && key) {
1256+
ArrayPrototypePush(prev, cur);
1257+
} else if (kind === 'value' && !key) {
1258+
ArrayPrototypePush(prev, cur);
1259+
} else if (kind === 'key+value' && !key) {
1260+
ArrayPrototypePush(prev, [target[searchParams][index + i - 1], cur]);
1261+
}
1262+
return prev;
1263+
},
1264+
[]
1265+
);
12391266
const breakLn = inspect(output, innerOpts).includes('\n');
1240-
const outputStrs = output.map((p) => inspect(p, innerOpts));
1267+
const outputStrs = ArrayPrototypeMap(output, (p) => inspect(p, innerOpts));
12411268
let outputStr;
12421269
if (breakLn) {
1243-
outputStr = `\n ${outputStrs.join(',\n ')}`;
1270+
outputStr = `\n ${ArrayPrototypeJoin(outputStrs, ',\n ')}`;
12441271
} else {
1245-
outputStr = ` ${outputStrs.join(', ')}`;
1272+
outputStr = ` ${ArrayPrototypeJoin(outputStrs, ', ')}`;
12461273
}
12471274
return `${this[SymbolToStringTag]} {${outputStr} }`;
12481275
}
@@ -1270,8 +1297,9 @@ function domainToUnicode(domain) {
12701297
function urlToOptions(url) {
12711298
const options = {
12721299
protocol: url.protocol,
1273-
hostname: typeof url.hostname === 'string' && url.hostname.startsWith('[') ?
1274-
url.hostname.slice(1, -1) :
1300+
hostname: typeof url.hostname === 'string' &&
1301+
StringPrototypeStartsWith(url.hostname, '[') ?
1302+
StringPrototypeSlice(url.hostname, 1, -1) :
12751303
url.hostname,
12761304
hash: url.hash,
12771305
search: url.search,
@@ -1371,25 +1399,25 @@ const carriageReturnRegEx = /\r/g;
13711399
const tabRegEx = /\t/g;
13721400

13731401
function encodePathChars(filepath) {
1374-
if (filepath.includes('%'))
1375-
filepath = filepath.replace(percentRegEx, '%25');
1402+
if (StringPrototypeIncludes(filepath, '%'))
1403+
filepath = StringPrototypeReplace(filepath, percentRegEx, '%25');
13761404
// In posix, backslash is a valid character in paths:
1377-
if (!isWindows && filepath.includes('\\'))
1378-
filepath = filepath.replace(backslashRegEx, '%5C');
1379-
if (filepath.includes('\n'))
1380-
filepath = filepath.replace(newlineRegEx, '%0A');
1381-
if (filepath.includes('\r'))
1382-
filepath = filepath.replace(carriageReturnRegEx, '%0D');
1383-
if (filepath.includes('\t'))
1384-
filepath = filepath.replace(tabRegEx, '%09');
1405+
if (!isWindows && StringPrototypeIncludes(filepath, '\\'))
1406+
filepath = StringPrototypeReplace(filepath, backslashRegEx, '%5C');
1407+
if (StringPrototypeIncludes(filepath, '\n'))
1408+
filepath = StringPrototypeReplace(filepath, newlineRegEx, '%0A');
1409+
if (StringPrototypeIncludes(filepath, '\r'))
1410+
filepath = StringPrototypeReplace(filepath, carriageReturnRegEx, '%0D');
1411+
if (StringPrototypeIncludes(filepath, '\t'))
1412+
filepath = StringPrototypeReplace(filepath, tabRegEx, '%09');
13851413
return filepath;
13861414
}
13871415

13881416
function pathToFileURL(filepath) {
13891417
const outURL = new URL('file://');
1390-
if (isWindows && filepath.startsWith('\\\\')) {
1418+
if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) {
13911419
// UNC path format: \\server\share\resource
1392-
const paths = filepath.split('\\');
1420+
const paths = StringPrototypeSplit(filepath, '\\');
13931421
if (paths.length <= 3) {
13941422
throw new ERR_INVALID_ARG_VALUE(
13951423
'filepath',
@@ -1406,11 +1434,13 @@ function pathToFileURL(filepath) {
14061434
);
14071435
}
14081436
outURL.hostname = domainToASCII(hostname);
1409-
outURL.pathname = encodePathChars(paths.slice(3).join('/'));
1437+
outURL.pathname = encodePathChars(
1438+
ArrayPrototypeJoin(ArrayPrototypeSlice(paths, 3), '/'));
14101439
} else {
14111440
let resolved = path.resolve(filepath);
14121441
// path.resolve strips trailing slashes so we must add them back
1413-
const filePathLast = filepath.charCodeAt(filepath.length - 1);
1442+
const filePathLast = StringPrototypeCharCodeAt(filepath,
1443+
filepath.length - 1);
14141444
if ((filePathLast === CHAR_FORWARD_SLASH ||
14151445
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
14161446
resolved[resolved.length - 1] !== path.sep)

0 commit comments

Comments
 (0)