Skip to content

Commit 08bafc8

Browse files
aduh95juanarbol
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 03e244a commit 08bafc8

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
ObjectCreate,
1415
ObjectDefineProperties,
@@ -19,11 +20,13 @@ const {
1920
ReflectApply,
2021
ReflectGetOwnPropertyDescriptor,
2122
ReflectOwnKeys,
23+
RegExpPrototypeSymbolReplace,
2224
String,
25+
StringPrototypeCharAt,
2326
StringPrototypeCharCodeAt,
27+
StringPrototypeCodePointAt,
2428
StringPrototypeIncludes,
25-
StringPrototypeReplace,
26-
StringPrototypeReplaceAll,
29+
StringPrototypeIndexOf,
2730
StringPrototypeSlice,
2831
StringPrototypeSplit,
2932
StringPrototypeStartsWith,
@@ -45,6 +48,7 @@ const {
4548
removeColors,
4649
toUSVString,
4750
kEnumerableProperty,
51+
SideEffectFreeRegExpPrototypeSymbolReplace,
4852
} = require('internal/util');
4953

5054
const {
@@ -113,6 +117,8 @@ const {
113117
revokeDataObject,
114118
} = internalBinding('blob');
115119

120+
const FORWARD_SLASH = /\//g;
121+
116122
const context = Symbol('context');
117123
const cannotBeBase = Symbol('cannot-be-base');
118124
const cannotHaveUsernamePasswordPort =
@@ -139,11 +145,6 @@ function lazyCryptoRandom() {
139145
return cryptoRandom;
140146
}
141147

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

@@ -1377,7 +1378,7 @@ defineIDLClass(URLSearchParamsIteratorPrototype, 'URLSearchParams Iterator', {
13771378
},
13781379
[]
13791380
);
1380-
const breakLn = inspect(output, innerOpts).includes('\n');
1381+
const breakLn = StringPrototypeIncludes(inspect(output, innerOpts), '\n');
13811382
const outputStrs = ArrayPrototypeMap(output, (p) => inspect(p, innerOpts));
13821383
let outputStr;
13831384
if (breakLn) {
@@ -1435,7 +1436,7 @@ function getPathFromURLWin32(url) {
14351436
let pathname = url.pathname;
14361437
for (let n = 0; n < pathname.length; n++) {
14371438
if (pathname[n] === '%') {
1438-
const third = pathname.codePointAt(n + 2) | 0x20;
1439+
const third = StringPrototypeCodePointAt(pathname, n + 2) | 0x20;
14391440
if ((pathname[n + 1] === '2' && third === 102) || // 2f 2F /
14401441
(pathname[n + 1] === '5' && third === 99)) { // 5c 5C \
14411442
throw new ERR_INVALID_FILE_URL_PATH(
@@ -1444,7 +1445,7 @@ function getPathFromURLWin32(url) {
14441445
}
14451446
}
14461447
}
1447-
pathname = StringPrototypeReplaceAll(pathname, '/', '\\');
1448+
pathname = SideEffectFreeRegExpPrototypeSymbolReplace(FORWARD_SLASH, pathname, '\\');
14481449
pathname = decodeURIComponent(pathname);
14491450
if (hostname !== '') {
14501451
// If hostname is set, then we have a UNC path
@@ -1456,13 +1457,13 @@ function getPathFromURLWin32(url) {
14561457
return `\\\\${domainToUnicode(hostname)}${pathname}`;
14571458
}
14581459
// Otherwise, it's a local path that requires a drive letter
1459-
const letter = pathname.codePointAt(1) | 0x20;
1460-
const sep = pathname[2];
1460+
const letter = StringPrototypeCodePointAt(pathname, 1) | 0x20;
1461+
const sep = StringPrototypeCharAt(pathname, 2);
14611462
if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z
14621463
(sep !== ':')) {
14631464
throw new ERR_INVALID_FILE_URL_PATH('must be absolute');
14641465
}
1465-
return pathname.slice(1);
1466+
return StringPrototypeSlice(pathname, 1);
14661467
}
14671468

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

15131514
function encodePathChars(filepath) {
15141515
if (StringPrototypeIncludes(filepath, '%'))
1515-
filepath = StringPrototypeReplace(filepath, percentRegEx, '%25');
1516+
filepath = RegExpPrototypeSymbolReplace(percentRegEx, filepath, '%25');
15161517
// In posix, backslash is a valid character in paths:
15171518
if (!isWindows && StringPrototypeIncludes(filepath, '\\'))
1518-
filepath = StringPrototypeReplace(filepath, backslashRegEx, '%5C');
1519+
filepath = RegExpPrototypeSymbolReplace(backslashRegEx, filepath, '%5C');
15191520
if (StringPrototypeIncludes(filepath, '\n'))
1520-
filepath = StringPrototypeReplace(filepath, newlineRegEx, '%0A');
1521+
filepath = RegExpPrototypeSymbolReplace(newlineRegEx, filepath, '%0A');
15211522
if (StringPrototypeIncludes(filepath, '\r'))
1522-
filepath = StringPrototypeReplace(filepath, carriageReturnRegEx, '%0D');
1523+
filepath = RegExpPrototypeSymbolReplace(carriageReturnRegEx, filepath, '%0D');
15231524
if (StringPrototypeIncludes(filepath, '\t'))
1524-
filepath = StringPrototypeReplace(filepath, tabRegEx, '%09');
1525+
filepath = RegExpPrototypeSymbolReplace(tabRegEx, filepath, '%09');
15251526
return filepath;
15261527
}
15271528

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

0 commit comments

Comments
 (0)