Skip to content

Commit 7a98ac5

Browse files
committed
path: support file urls
1 parent 1df52e6 commit 7a98ac5

13 files changed

+227
-106
lines changed

doc/api/path.md

+60-23
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,15 @@ example, `path.resolve('C:\\')` can potentially return a different result than
6767
<!-- YAML
6868
added: v0.1.25
6969
changes:
70+
- version: REPLACEME
71+
pr-url: https://github.com/nodejs/node/pull/52672
72+
description: Passing a file URL as an argument is now supported.
7073
- version: v6.0.0
7174
pr-url: https://github.com/nodejs/node/pull/5348
7275
description: Passing a non-string as the `path` argument will throw now.
7376
-->
7477

75-
* `path` {string}
78+
* `path` {string|URL}
7679
* `suffix` {string} An optional suffix to remove
7780
* Returns: {string}
7881

@@ -101,8 +104,8 @@ path.win32.basename('C:\\foo.HTML', '.html');
101104
// Returns: 'foo.HTML'
102105
```
103106

104-
A [`TypeError`][] is thrown if `path` is not a string or if `suffix` is given
105-
and is not a string.
107+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][],
108+
or if `suffix` is given and is not a string.
106109

107110
## `path.delimiter`
108111

@@ -142,12 +145,15 @@ process.env.PATH.split(path.delimiter);
142145
<!-- YAML
143146
added: v0.1.16
144147
changes:
148+
- version: REPLACEME
149+
pr-url: https://github.com/nodejs/node/pull/52672
150+
description: Passing a file URL as an argument is now supported.
145151
- version: v6.0.0
146152
pr-url: https://github.com/nodejs/node/pull/5348
147153
description: Passing a non-string as the `path` argument will throw now.
148154
-->
149155

150-
* `path` {string}
156+
* `path` {string|URL}
151157
* Returns: {string}
152158

153159
The `path.dirname()` method returns the directory name of a `path`, similar to
@@ -159,19 +165,22 @@ path.dirname('/foo/bar/baz/asdf/quux');
159165
// Returns: '/foo/bar/baz/asdf'
160166
```
161167

162-
A [`TypeError`][] is thrown if `path` is not a string.
168+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][]
163169

164170
## `path.extname(path)`
165171

166172
<!-- YAML
167173
added: v0.1.25
168174
changes:
175+
- version: REPLACEME
176+
pr-url: https://github.com/nodejs/node/pull/52672
177+
description: Passing a file URL as an argument is now supported.
169178
- version: v6.0.0
170179
pr-url: https://github.com/nodejs/node/pull/5348
171180
description: Passing a non-string as the `path` argument will throw now.
172181
-->
173182

174-
* `path` {string}
183+
* `path` {string|URL}
175184
* Returns: {string}
176185

177186
The `path.extname()` method returns the extension of the `path`, from the last
@@ -200,7 +209,7 @@ path.extname('.index.md');
200209
// Returns: '.md'
201210
```
202211

203-
A [`TypeError`][] is thrown if `path` is not a string.
212+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][].
204213

205214
## `path.format(pathObject)`
206215

@@ -283,9 +292,13 @@ path.format({
283292

284293
<!-- YAML
285294
added: v0.11.2
295+
changes:
296+
- version: REPLACEME
297+
pr-url: https://github.com/nodejs/node/pull/52672
298+
description: Passing a file URL as an argument is now supported.
286299
-->
287300

288-
* `path` {string}
301+
* `path` {string|URL}
289302
* Returns: {boolean}
290303

291304
The `path.isAbsolute()` method determines if `path` is an absolute path.
@@ -313,15 +326,19 @@ path.isAbsolute('bar/baz'); // false
313326
path.isAbsolute('.'); // false
314327
```
315328

316-
A [`TypeError`][] is thrown if `path` is not a string.
329+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][].
317330

318331
## `path.join([...paths])`
319332

320333
<!-- YAML
321334
added: v0.1.16
335+
changes:
336+
- version: REPLACEME
337+
pr-url: https://github.com/nodejs/node/pull/52672
338+
description: Passing a file URL as an argument is now supported.
322339
-->
323340

324-
* `...paths` {string} A sequence of path segments
341+
* `...paths` {string|URL} A sequence of path segments
325342
* Returns: {string}
326343

327344
The `path.join()` method joins all given `path` segments together using the
@@ -339,15 +356,19 @@ path.join('foo', {}, 'bar');
339356
// Throws 'TypeError: Path must be a string. Received {}'
340357
```
341358

342-
A [`TypeError`][] is thrown if any of the path segments is not a string.
359+
A [`TypeError`][] is thrown if any of the path segments is not a string or an instance of [`URL`][].
343360

344361
## `path.normalize(path)`
345362

346363
<!-- YAML
347364
added: v0.1.23
365+
changes:
366+
- version: REPLACEME
367+
pr-url: https://github.com/nodejs/node/pull/52672
368+
description: Passing a file URL as an argument is now supported.
348369
-->
349370

350-
* `path` {string}
371+
* `path` {string|URL}
351372
* Returns: {string}
352373

353374
The `path.normalize()` method normalizes the given `path`, resolving `'..'` and
@@ -391,15 +412,19 @@ path.win32.normalize('C:////temp\\\\/\\/\\/foo/bar');
391412
// Returns: 'C:\\temp\\foo\\bar'
392413
```
393414

394-
A [`TypeError`][] is thrown if `path` is not a string.
415+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][].
395416

396417
## `path.parse(path)`
397418

398419
<!-- YAML
399420
added: v0.11.15
421+
changes:
422+
- version: REPLACEME
423+
pr-url: https://github.com/nodejs/node/pull/52672
424+
description: Passing a file URL as an argument is now supported.
400425
-->
401426

402-
* `path` {string}
427+
* `path` {string|URL}
403428
* Returns: {Object}
404429

405430
The `path.parse()` method returns an object whose properties represent
@@ -458,7 +483,7 @@ path.parse('C:\\path\\dir\\file.txt');
458483
(All spaces in the "" line should be ignored. They are purely for formatting.)
459484
```
460485

461-
A [`TypeError`][] is thrown if `path` is not a string.
486+
A [`TypeError`][] is thrown if `path` is not a string or an instance of [`URL`][].
462487

463488
## `path.posix`
464489

@@ -482,14 +507,17 @@ The API is accessible via `require('node:path').posix` or `require('node:path/po
482507
<!-- YAML
483508
added: v0.5.0
484509
changes:
510+
- version: REPLACEME
511+
pr-url: https://github.com/nodejs/node/pull/52672
512+
description: Passing a file URL as an argument is now supported.
485513
- version: v6.8.0
486514
pr-url: https://github.com/nodejs/node/pull/8523
487515
description: On Windows, the leading slashes for UNC paths are now included
488516
in the return value.
489517
-->
490518

491-
* `from` {string}
492-
* `to` {string}
519+
* `from` {string|URL}
520+
* `to` {string|URL}
493521
* Returns: {string}
494522

495523
The `path.relative()` method returns the relative path from `from` to `to` based
@@ -513,15 +541,19 @@ path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb');
513541
// Returns: '..\\..\\impl\\bbb'
514542
```
515543

516-
A [`TypeError`][] is thrown if either `from` or `to` is not a string.
544+
A [`TypeError`][] is thrown if either `from` or `to` is not a string or an instance of [`URL`][].
517545

518546
## `path.resolve([...paths])`
519547

520548
<!-- YAML
521549
added: v0.3.4
550+
changes:
551+
- version: REPLACEME
552+
pr-url: https://github.com/nodejs/node/pull/52672
553+
description: Passing a file URL as an argument is now supported.
522554
-->
523555

524-
* `...paths` {string} A sequence of paths or path segments
556+
* `...paths` {string|URL} A sequence of paths or path segments
525557
* Returns: {string}
526558

527559
The `path.resolve()` method resolves a sequence of paths or path segments into
@@ -556,7 +588,7 @@ path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
556588
// this returns '/home/myself/node/wwwroot/static_files/gif/image.gif'
557589
```
558590

559-
A [`TypeError`][] is thrown if any of the arguments is not a string.
591+
A [`TypeError`][] is thrown if any of the arguments is not a string or an instance of [`URL`][].
560592

561593
## `path.sep`
562594

@@ -593,14 +625,18 @@ slashes (`\`).
593625

594626
<!-- YAML
595627
added: v9.0.0
628+
changes:
629+
- version: REPLACEME
630+
pr-url: https://github.com/nodejs/node/pull/52672
631+
description: Passing a file URL as an argument is now supported.
596632
-->
597633

598-
* `path` {string}
634+
* `path` {string|URL}
599635
* Returns: {string}
600636

601637
On Windows systems only, returns an equivalent [namespace-prefixed path][] for
602-
the given `path`. If `path` is not a string, `path` will be returned without
603-
modifications.
638+
the given `path`. If `path` is not a string or URL, `path` will be returned
639+
without modifications.
604640

605641
This method is meaningful only on Windows systems. On POSIX systems, the
606642
method is non-operational and always returns `path` without modifications.
@@ -624,6 +660,7 @@ The API is accessible via `require('node:path').win32` or `require('node:path/wi
624660

625661
[MSDN-Rel-Path]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#fully-qualified-vs-relative-paths
626662
[`TypeError`]: errors.md#class-typeerror
663+
[`URL`]: url.md#the-whatwg-url-api
627664
[`path.parse()`]: #pathparsepath
628665
[`path.posix`]: #pathposix
629666
[`path.sep`]: #pathsep

lib/internal/url.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const {
4646
kEnumerableProperty,
4747
kEmptyObject,
4848
SideEffectFreeRegExpPrototypeSymbolReplace,
49+
getLazy,
4950
} = require('internal/util');
5051

5152
const {
@@ -77,7 +78,7 @@ const {
7778
CHAR_PERCENT,
7879
CHAR_PLUS,
7980
} = require('internal/constants');
80-
const path = require('path');
81+
const lazyPath = getLazy(() => require('path'));
8182

8283
const {
8384
validateFunction,
@@ -1555,13 +1556,13 @@ function pathToFileURL(filepath, options = kEmptyObject) {
15551556
);
15561557
return outURL;
15571558
}
1558-
let resolved = (windows ?? isWindows) ? path.win32.resolve(filepath) : path.posix.resolve(filepath);
1559+
let resolved = (windows ?? isWindows) ? lazyPath().win32.resolve(filepath) : lazyPath().posix.resolve(filepath);
15591560
// path.resolve strips trailing slashes so we must add them back
15601561
const filePathLast = StringPrototypeCharCodeAt(filepath,
15611562
filepath.length - 1);
15621563
if ((filePathLast === CHAR_FORWARD_SLASH ||
15631564
((windows ?? isWindows) && filePathLast === CHAR_BACKWARD_SLASH)) &&
1564-
resolved[resolved.length - 1] !== path.sep)
1565+
resolved[resolved.length - 1] !== lazyPath().sep)
15651566
resolved += '/';
15661567

15671568
// Call encodePathChars first to avoid encoding % again for ? and #.
@@ -1578,10 +1579,10 @@ function pathToFileURL(filepath, options = kEmptyObject) {
15781579
return new URL(`file://${resolved}`);
15791580
}
15801581

1581-
function toPathIfFileURL(fileURLOrPath) {
1582+
function toPathIfFileURL(fileURLOrPath, options = kEmptyObject) {
15821583
if (!isURL(fileURLOrPath))
15831584
return fileURLOrPath;
1584-
return fileURLToPath(fileURLOrPath);
1585+
return fileURLToPath(fileURLOrPath, options);
15851586
}
15861587

15871588
/**

0 commit comments

Comments
 (0)