Skip to content

Commit ce3764d

Browse files
committed
url: reduce pathToFileURL cpp calls
1 parent eece8d7 commit ce3764d

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

lib/internal/url.js

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,8 @@ const backslashRegEx = /\\/g;
14141414
const newlineRegEx = /\n/g;
14151415
const carriageReturnRegEx = /\r/g;
14161416
const tabRegEx = /\t/g;
1417+
const questionRegex = /\?/;
1418+
const hashRegex = /#/;
14171419

14181420
function encodePathChars(filepath) {
14191421
if (StringPrototypeIncludes(filepath, '%'))
@@ -1431,8 +1433,8 @@ function encodePathChars(filepath) {
14311433
}
14321434

14331435
function pathToFileURL(filepath) {
1434-
const outURL = new URL('file://');
14351436
if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) {
1437+
const outURL = new URL('file://');
14361438
// UNC path format: \\server\share\resource
14371439
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
14381440
if (hostnameEndIndex === -1) {
@@ -1453,18 +1455,29 @@ function pathToFileURL(filepath) {
14531455
outURL.hostname = domainToASCII(hostname);
14541456
outURL.pathname = encodePathChars(
14551457
RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/'));
1456-
} else {
1457-
let resolved = path.resolve(filepath);
1458-
// path.resolve strips trailing slashes so we must add them back
1459-
const filePathLast = StringPrototypeCharCodeAt(filepath,
1460-
filepath.length - 1);
1461-
if ((filePathLast === CHAR_FORWARD_SLASH ||
1462-
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
1463-
resolved[resolved.length - 1] !== path.sep)
1464-
resolved += '/';
1465-
outURL.pathname = encodePathChars(resolved);
1466-
}
1467-
return outURL;
1458+
return outURL;
1459+
}
1460+
let resolved = path.resolve(filepath);
1461+
// path.resolve strips trailing slashes so we must add them back
1462+
const filePathLast = StringPrototypeCharCodeAt(filepath,
1463+
filepath.length - 1);
1464+
if ((filePathLast === CHAR_FORWARD_SLASH ||
1465+
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
1466+
resolved[resolved.length - 1] !== path.sep)
1467+
resolved += '/';
1468+
1469+
// Call encodePathChars first to avoid encoding % again for ? and #.
1470+
resolved = encodePathChars(resolved);
1471+
1472+
// Question and hash character should be included in pathname.
1473+
// Therefore, encoding is required to eliminate parsing them in different states.
1474+
// This is done as an optimization to not creating a URL instance and
1475+
// later triggering pathname setter, which impacts performance
1476+
if (StringPrototypeIncludes(resolved, '?'))
1477+
resolved = RegExpPrototypeSymbolReplace(questionRegex, resolved, '%3F');
1478+
if (StringPrototypeIncludes(resolved, '#'))
1479+
resolved = RegExpPrototypeSymbolReplace(hashRegex, resolved, '%23');
1480+
return new URL(`file://${resolved}`);
14681481
}
14691482

14701483
function toPathIfFileURL(fileURLOrPath) {

0 commit comments

Comments
 (0)