Skip to content

Commit e460d16

Browse files
aduh95ruyadorno
authored andcommitted
url: refactor to use more primordials
PR-URL: #45966 Reviewed-By: Zeyu "Alex" Yang <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
1 parent 4440b3e commit e460d16

File tree

4 files changed

+59
-25
lines changed

4 files changed

+59
-25
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
const { fileURLToPath, pathToFileURL } = require('node:url');
4+
const isWindows = process.platform === 'win32';
5+
6+
const bench = common.createBenchmark(main, {
7+
input: isWindows ? [
8+
'file:///c/',
9+
] : [
10+
'file:///dev/null',
11+
'file:///dev/null?key=param&bool',
12+
'file:///dev/null?key=param&bool#hash',
13+
],
14+
method: isWindows ? [
15+
'fileURLToPath',
16+
] : [
17+
'fileURLToPath',
18+
'pathToFileURL',
19+
],
20+
n: [5e6],
21+
});
22+
23+
function main({ n, input, method }) {
24+
method = method === 'fileURLOrPath' ? fileURLToPath : pathToFileURL;
25+
bench.start();
26+
for (let i = 0; i < n; i++) {
27+
method(input);
28+
}
29+
bench.end(n);
30+
}

lib/internal/freeze_intrinsics.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const {
6161
Int32ArrayPrototype,
6262
Int8Array,
6363
Int8ArrayPrototype,
64+
IteratorPrototype,
6465
Map,
6566
MapPrototype,
6667
Number,
@@ -211,7 +212,7 @@ module.exports = function() {
211212

212213
// 27 Control Abstraction Objects
213214
// 27.1 Iteration
214-
ObjectGetPrototypeOf(ArrayIteratorPrototype), // 27.1.2 IteratorPrototype
215+
IteratorPrototype, // 27.1.2 IteratorPrototype
215216
// 27.1.3 AsyncIteratorPrototype
216217
ObjectGetPrototypeOf(ObjectGetPrototypeOf(ObjectGetPrototypeOf(
217218
(async function*() {})()

lib/internal/per_context/primordials.js

+2
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ function copyPrototype(src, dest, prefix) {
260260
copyPrototype(original.prototype, primordials, `${name}Prototype`);
261261
});
262262

263+
primordials.IteratorPrototype = Reflect.getPrototypeOf(primordials.ArrayIteratorPrototype);
264+
263265
/* eslint-enable node-core/prefer-primordials */
264266

265267
const {

lib/internal/url.js

+25-24
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
ArrayPrototypeSlice,
1010
FunctionPrototypeBind,
1111
Int8Array,
12+
IteratorPrototype,
1213
Number,
1314
ObjectDefineProperties,
1415
ObjectDefineProperty,
@@ -18,11 +19,13 @@ const {
1819
ReflectApply,
1920
ReflectGetOwnPropertyDescriptor,
2021
ReflectOwnKeys,
22+
RegExpPrototypeSymbolReplace,
2123
String,
24+
StringPrototypeCharAt,
2225
StringPrototypeCharCodeAt,
26+
StringPrototypeCodePointAt,
2327
StringPrototypeIncludes,
24-
StringPrototypeReplace,
25-
StringPrototypeReplaceAll,
28+
StringPrototypeIndexOf,
2629
StringPrototypeSlice,
2730
StringPrototypeSplit,
2831
StringPrototypeStartsWith,
@@ -44,6 +47,7 @@ const {
4447
removeColors,
4548
toUSVString,
4649
kEnumerableProperty,
50+
SideEffectFreeRegExpPrototypeSymbolReplace,
4751
} = require('internal/util');
4852

4953
const {
@@ -112,6 +116,8 @@ const {
112116
revokeDataObject,
113117
} = internalBinding('blob');
114118

119+
const FORWARD_SLASH = /\//g;
120+
115121
const context = Symbol('context');
116122
const cannotBeBase = Symbol('cannot-be-base');
117123
const cannotHaveUsernamePasswordPort =
@@ -138,11 +144,6 @@ function lazyCryptoRandom() {
138144
return cryptoRandom;
139145
}
140146

141-
// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
142-
const IteratorPrototype = ObjectGetPrototypeOf(
143-
ObjectGetPrototypeOf([][SymbolIterator]())
144-
);
145-
146147
// Refs: https://html.spec.whatwg.org/multipage/browsers.html#concept-origin-opaque
147148
const kOpaqueOrigin = 'null';
148149

@@ -1376,7 +1377,7 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParams Iterator', {
13761377
},
13771378
[]
13781379
);
1379-
const breakLn = inspect(output, innerOpts).includes('\n');
1380+
const breakLn = StringPrototypeIncludes(inspect(output, innerOpts), '\n');
13801381
const outputStrs = ArrayPrototypeMap(output, (p) => inspect(p, innerOpts));
13811382
let outputStr;
13821383
if (breakLn) {
@@ -1434,7 +1435,7 @@ function getPathFromURLWin32(url) {
14341435
let pathname = url.pathname;
14351436
for (let n = 0; n < pathname.length; n++) {
14361437
if (pathname[n] === '%') {
1437-
const third = pathname.codePointAt(n + 2) | 0x20;
1438+
const third = StringPrototypeCodePointAt(pathname, n + 2) | 0x20;
14381439
if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F /
14391440
(pathname[n + 1] === '5' && third === 99)) { // 5c 5C \
14401441
throw new ERR_INVALID_FILE_URL_PATH(
@@ -1443,7 +1444,7 @@ function getPathFromURLWin32(url) {
14431444
}
14441445
}
14451446
}
1446-
pathname = StringPrototypeReplaceAll(pathname, '/', '\\');
1447+
pathname = SideEffectFreeRegExpPrototypeSymbolReplace(FORWARD_SLASH, pathname, '\\');
14471448
pathname = decodeURIComponent(pathname);
14481449
if (hostname !== '') {
14491450
// If hostname is set, then we have a UNC path
@@ -1455,13 +1456,13 @@ function getPathFromURLWin32(url) {
14551456
return `\\\\${domainToUnicode(hostname)}${pathname}`;
14561457
}
14571458
// Otherwise, it's a local path that requires a drive letter
1458-
const letter = pathname.codePointAt(1) | 0x20;
1459-
const sep = pathname[2];
1459+
const letter = StringPrototypeCodePointAt(pathname, 1) | 0x20;
1460+
const sep = StringPrototypeCharAt(pathname, 2);
14601461
if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z
14611462
(sep !== ':')) {
14621463
throw new ERR_INVALID_FILE_URL_PATH('must be absolute');
14631464
}
1464-
return pathname.slice(1);
1465+
return StringPrototypeSlice(pathname, 1);
14651466
}
14661467

14671468
function getPathFromURLPosix(url) {
@@ -1471,7 +1472,7 @@ function getPathFromURLPosix(url) {
14711472
const pathname = url.pathname;
14721473
for (let n = 0; n < pathname.length; n++) {
14731474
if (pathname[n] === '%') {
1474-
const third = pathname.codePointAt(n + 2) | 0x20;
1475+
const third = StringPrototypeCodePointAt(pathname, n + 2) | 0x20;
14751476
if (pathname[n + 1] === '2' && third === 102) {
14761477
throw new ERR_INVALID_FILE_URL_PATH(
14771478
'must not include encoded / characters'
@@ -1511,42 +1512,42 @@ const tabRegEx = /\t/g;
15111512

15121513
function encodePathChars(filepath) {
15131514
if (StringPrototypeIncludes(filepath, '%'))
1514-
filepath = StringPrototypeReplace(filepath, percentRegEx, '%25');
1515+
filepath = RegExpPrototypeSymbolReplace(percentRegEx, filepath, '%25');
15151516
// In posix, backslash is a valid character in paths:
15161517
if (!isWindows && StringPrototypeIncludes(filepath, '\\'))
1517-
filepath = StringPrototypeReplace(filepath, backslashRegEx, '%5C');
1518+
filepath = RegExpPrototypeSymbolReplace(backslashRegEx, filepath, '%5C');
15181519
if (StringPrototypeIncludes(filepath, '\n'))
1519-
filepath = StringPrototypeReplace(filepath, newlineRegEx, '%0A');
1520+
filepath = RegExpPrototypeSymbolReplace(newlineRegEx, filepath, '%0A');
15201521
if (StringPrototypeIncludes(filepath, '\r'))
1521-
filepath = StringPrototypeReplace(filepath, carriageReturnRegEx, '%0D');
1522+
filepath = RegExpPrototypeSymbolReplace(carriageReturnRegEx, filepath, '%0D');
15221523
if (StringPrototypeIncludes(filepath, '\t'))
1523-
filepath = StringPrototypeReplace(filepath, tabRegEx, '%09');
1524+
filepath = RegExpPrototypeSymbolReplace(tabRegEx, filepath, '%09');
15241525
return filepath;
15251526
}
15261527

15271528
function pathToFileURL(filepath) {
15281529
const outURL = new URL('file://');
15291530
if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) {
15301531
// UNC path format: \\server\share\resource
1531-
const paths = StringPrototypeSplit(filepath, '\\');
1532-
if (paths.length <= 3) {
1532+
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
1533+
if (hostnameEndIndex === -1) {
15331534
throw new ERR_INVALID_ARG_VALUE(
15341535
'filepath',
15351536
filepath,
15361537
'Missing UNC resource path'
15371538
);
15381539
}
1539-
const hostname = paths[2];
1540-
if (hostname.length === 0) {
1540+
if (hostnameEndIndex === 2) {
15411541
throw new ERR_INVALID_ARG_VALUE(
15421542
'filepath',
15431543
filepath,
15441544
'Empty UNC servername'
15451545
);
15461546
}
1547+
const hostname = StringPrototypeSlice(filepath, 2, hostnameEndIndex);
15471548
outURL.hostname = domainToASCII(hostname);
15481549
outURL.pathname = encodePathChars(
1549-
ArrayPrototypeJoin(ArrayPrototypeSlice(paths, 3), '/'));
1550+
RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/'));
15501551
} else {
15511552
let resolved = path.resolve(filepath);
15521553
// path.resolve strips trailing slashes so we must add them back

0 commit comments

Comments
 (0)