lib, url: add a `windows` option to path parsing · nodejs/node@64428dc · GitHub
Skip to content

Commit 64428dc

Browse files
avivkelleraduh95
authored andcommitted
lib, url: add a windows option to path parsing
PR-URL: #52509 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com> Reviewed-By: LiviaMedeiros <livia@cirno.name>
1 parent 90c6e77 commit 64428dc

6 files changed

Lines changed: 267 additions & 216 deletions

File tree

doc/api/esm.md

Lines changed: 2 additions & 2 deletions

doc/api/url.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,13 +1151,23 @@ console.log(url.domainToUnicode('xn--iñvalid.com'));
11511151
// Prints an empty string
11521152
```
11531153

1154-
### `url.fileURLToPath(url)`
1154+
### `url.fileURLToPath(url[, options])`
11551155

11561156
<!-- YAML
11571157
added: v10.12.0
1158+
changes:
1159+
- version: REPLACEME
1160+
pr-url: https://github.com/nodejs/node/pull/52509
1161+
description: The `options` argument can now be used to
1162+
determine how to parse the `path` argument.
11581163
-->
11591164

11601165
* `url` {URL | string} The file URL string or URL object to convert to a path.
1166+
* `options` {Object}
1167+
* `windows` {boolean|undefined} `true` if the `path` should be
1168+
return as a windows filepath, `false` for posix, and
1169+
`undefined` for the system default.
1170+
**Default:** `undefined`.
11611171
* Returns: {string} The fully-resolved platform-specific Node.js file path.
11621172

11631173
This function ensures the correct decodings of percent-encoded characters as
@@ -1251,13 +1261,23 @@ console.log(url.format(myURL, { fragment: false, unicode: true, auth: false }));
12511261
// Prints 'https://測試/?abc'
12521262
```
12531263
1254-
### `url.pathToFileURL(path)`
1264+
### `url.pathToFileURL(path[, options])`
12551265
12561266
<!-- YAML
12571267
added: v10.12.0
1268+
changes:
1269+
- version: REPLACEME
1270+
pr-url: https://github.com/nodejs/node/pull/52509
1271+
description: The `options` argument can now be used to
1272+
determine how to return the `path` value.
12581273
-->
12591274
12601275
* `path` {string} The path to convert to a File URL.
1276+
* `options` {Object}
1277+
* `windows` {boolean|undefined} `true` if the `path` should be
1278+
treated as a windows filepath, `false` for posix, and
1279+
`undefined` for the system default.
1280+
**Default:** `undefined`.
12611281
* Returns: {URL} The file URL object.
12621282
12631283
This function ensures that `path` is resolved absolutely, and that the URL

lib/internal/url.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const {
4444
getConstructorOf,
4545
removeColors,
4646
kEnumerableProperty,
47+
kEmptyObject,
4748
SideEffectFreeRegExpPrototypeSymbolReplace,
4849
} = require('internal/util');
4950

@@ -1480,14 +1481,15 @@ function getPathFromURLPosix(url) {
14801481
return decodeURIComponent(pathname);
14811482
}
14821483

1483-
function fileURLToPath(path) {
1484+
function fileURLToPath(path, options = kEmptyObject) {
1485+
const windows = options?.windows;
14841486
if (typeof path === 'string')
14851487
path = new URL(path);
14861488
else if (!isURL(path))
14871489
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
14881490
if (path.protocol !== 'file:')
14891491
throw new ERR_INVALID_URL_SCHEME('file');
1490-
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
1492+
return (windows ?? isWindows) ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
14911493
}
14921494

14931495
// The following characters are percent-encoded when converting from file path
@@ -1509,11 +1511,12 @@ const tabRegEx = /\t/g;
15091511
const questionRegex = /\?/g;
15101512
const hashRegex = /#/g;
15111513

1512-
function encodePathChars(filepath) {
1514+
function encodePathChars(filepath, options = kEmptyObject) {
1515+
const windows = options?.windows;
15131516
if (StringPrototypeIndexOf(filepath, '%') !== -1)
15141517
filepath = RegExpPrototypeSymbolReplace(percentRegEx, filepath, '%25');
15151518
// In posix, backslash is a valid character in paths:
1516-
if (!isWindows && StringPrototypeIndexOf(filepath, '\\') !== -1)
1519+
if (!(windows ?? isWindows) && StringPrototypeIndexOf(filepath, '\\') !== -1)
15171520
filepath = RegExpPrototypeSymbolReplace(backslashRegEx, filepath, '%5C');
15181521
if (StringPrototypeIndexOf(filepath, '\n') !== -1)
15191522
filepath = RegExpPrototypeSymbolReplace(newlineRegEx, filepath, '%0A');
@@ -1524,8 +1527,9 @@ function encodePathChars(filepath) {
15241527
return filepath;
15251528
}
15261529

1527-
function pathToFileURL(filepath) {
1528-
if (isWindows && StringPrototypeStartsWith(filepath, '\\\\')) {
1530+
function pathToFileURL(filepath, options = kEmptyObject) {
1531+
const windows = options?.windows;
1532+
if ((windows ?? isWindows) && StringPrototypeStartsWith(filepath, '\\\\')) {
15291533
const outURL = new URL('file://');
15301534
// UNC path format: \\server\share\resource
15311535
const hostnameEndIndex = StringPrototypeIndexOf(filepath, '\\', 2);
@@ -1546,20 +1550,22 @@ function pathToFileURL(filepath) {
15461550
const hostname = StringPrototypeSlice(filepath, 2, hostnameEndIndex);
15471551
outURL.hostname = domainToASCII(hostname);
15481552
outURL.pathname = encodePathChars(
1549-
RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/'));
1553+
RegExpPrototypeSymbolReplace(backslashRegEx, StringPrototypeSlice(filepath, hostnameEndIndex), '/'),
1554+
{ windows },
1555+
);
15501556
return outURL;
15511557
}
1552-
let resolved = path.resolve(filepath);
1558+
let resolved = (windows ?? isWindows) ? path.win32.resolve(filepath) : path.posix.resolve(filepath);
15531559
// path.resolve strips trailing slashes so we must add them back
15541560
const filePathLast = StringPrototypeCharCodeAt(filepath,
15551561
filepath.length - 1);
15561562
if ((filePathLast === CHAR_FORWARD_SLASH ||
1557-
(isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&
1563+
((windows ?? isWindows) && filePathLast === CHAR_BACKWARD_SLASH)) &&
15581564
resolved[resolved.length - 1] !== path.sep)
15591565
resolved += '/';
15601566

15611567
// Call encodePathChars first to avoid encoding % again for ? and #.
1562-
resolved = encodePathChars(resolved);
1568+
resolved = encodePathChars(resolved, { windows });
15631569

15641570
// Question and hash character should be included in pathname.
15651571
// Therefore, encoding is required to eliminate parsing them in different states.

lib/url.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,10 +1020,10 @@ Url.prototype.parseHost = function parseHost() {
10201020
// When used internally, we are not obligated to associate TypeError with
10211021
// this function, so non-strings can be rejected by underlying implementation.
10221022
// Public API has to validate input and throw appropriate error.
1023-
function pathToFileURL(path) {
1023+
function pathToFileURL(path, options) {
10241024
validateString(path, 'path');
10251025

1026-
return _pathToFileURL(path);
1026+
return _pathToFileURL(path, options);
10271027
}
10281028

10291029
module.exports = {

test/parallel/test-url-fileurltopath.js

Lines changed: 115 additions & 101 deletions

0 commit comments

Comments
 (0)