diff --git a/doc/api/fs.md b/doc/api/fs.md index 4700101df4..0efe9ed23b 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -94,6 +94,95 @@ Error: EISDIR: illegal operation on a directory, read ``` +## WHATWG URL object support + + +> Stability: 1 - Experimental + +For most `fs` module functions, the `path` or `filename` argument may be passed +as a WHATWG [`URL`][] object. Only [`URL`][] objects using the `file:` protocol +are supported. + +```js +const fs = require('fs'); +const { URL } = require('url'); +const fileUrl = new URL('file:///tmp/hello'); + +fs.readFileSync(fileUrl); +``` + +*Note*: `file:` URLs are always absolute paths. + +Using WHATWG [`URL`][] objects might introduce platform-specific behaviors. + +On Windows, `file:` URLs with a hostname convert to UNC paths, while `file:` +URLs with drive letters convert to local absolute paths. `file:` URLs without a +hostname nor a drive letter will result in a throw : + +```js +// On Windows : + +// - WHATWG file URLs with hostname convert to UNC path +// file://hostname/p/a/t/h/file => \\hostname\p\a\t\h\file +fs.readFileSync(new URL('file://hostname/p/a/t/h/file')); + +// - WHATWG file URLs with drive letters convert to absolute path +// file:///C:/tmp/hello => C:\tmp\hello +fs.readFileSync(new URL('file:///C:/tmp/hello')); + +// - WHATWG file URLs without hostname must have a drive letters +fs.readFileSync(new URL('file:///notdriveletter/p/a/t/h/file')); +fs.readFileSync(new URL('file:///c/p/a/t/h/file')); +// TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute +``` + +*Note*: `file:` URLs with drive letters must use `:` as a separator just after +the drive letter. Using another separator will result in a throw. + +On all other platforms, `file:` URLs with a hostname are unsupported and will +result in a throw: + +```js +// On other platforms: + +// - WHATWG file URLs with hostname are unsupported +// file://hostname/p/a/t/h/file => throw! +fs.readFileSync(new URL('file://hostname/p/a/t/h/file')); +// TypeError [ERR_INVALID_FILE_URL_PATH]: must be absolute + +// - WHATWG file URLs convert to absolute path +// file:///tmp/hello => /tmp/hello +fs.readFileSync(new URL('file:///tmp/hello')); +``` + +A `file:` URL having encoded slash characters will result in a throw on all +platforms: + +```js +// On Windows +fs.readFileSync(new URL('file:///C:/p/a/t/h/%2F')); +fs.readFileSync(new URL('file:///C:/p/a/t/h/%2f')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +\ or / characters */ + +// On POSIX +fs.readFileSync(new URL('file:///p/a/t/h/%2F')); +fs.readFileSync(new URL('file:///p/a/t/h/%2f')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +/ characters */ +``` +On Windows, `file:` URLs having encoded backslash will result in a throw: + +```js +// On Windows +fs.readFileSync(new URL('file:///C:/path/%5C')); +fs.readFileSync(new URL('file:///C:/path/%5c')); +/* TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must not include encoded +\ or / characters */ +``` + ## Buffer API -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} * `callback` {Function} @@ -440,9 +534,14 @@ process. ## fs.accessSync(path[, mode]) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} Synchronous version of [`fs.access()`][]. This throws if any accessibility @@ -520,13 +619,17 @@ The synchronous version of [`fs.appendFile()`][]. Returns `undefined`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} * `callback` {Function} @@ -536,9 +639,14 @@ to the completion callback. ## fs.chmodSync(path, mode) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} Synchronous chmod(2). Returns `undefined`. @@ -547,13 +655,17 @@ Synchronous chmod(2). Returns `undefined`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `uid` {integer} * `gid` {integer} * `callback` {Function} @@ -564,9 +676,14 @@ to the completion callback. ## fs.chownSync(path, uid, gid) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `uid` {integer} * `gid` {integer} @@ -607,6 +724,10 @@ operations. The specific constants currently defined are described in -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `flags` {string} * `encoding` {string} @@ -675,6 +796,10 @@ If `options` is a string, then it specifies the encoding. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `flags` {string} * `defaultEncoding` {string} @@ -731,12 +856,17 @@ If `options` is a string, then it specifies the encoding. ## fs.exists(path, callback) > Stability: 0 - Deprecated: Use [`fs.stat()`][] or [`fs.access()`][] instead. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `callback` {Function} Test whether or not the given path exists by checking with the file system. @@ -836,9 +966,14 @@ process. ## fs.existsSync(path) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} Synchronous version of [`fs.exists()`][]. Returns `true` if the file exists, `false` otherwise. @@ -1148,14 +1283,19 @@ Synchronous lchown(2). Returns `undefined`. -* `existingPath` {string|Buffer} -* `newPath` {string|Buffer} +* `existingPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} * `callback` {Function} Asynchronous link(2). No arguments other than a possible exception are given to @@ -1164,10 +1304,16 @@ the completion callback. ## fs.linkSync(existingPath, newPath) -* `existingPath` {string|Buffer} -* `newPath` {string|Buffer} +* `existingPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} Synchronous link(2). Returns `undefined`. @@ -1175,13 +1321,17 @@ Synchronous link(2). Returns `undefined`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `callback` {Function} Asynchronous lstat(2). The callback gets two arguments `(err, stats)` where @@ -1192,9 +1342,14 @@ not the file that it refers to. ## fs.lstatSync(path) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} Synchronous lstat(2). Returns an instance of [`fs.Stats`][]. @@ -1202,13 +1357,17 @@ Synchronous lstat(2). Returns an instance of [`fs.Stats`][]. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} * `callback` {Function} @@ -1218,9 +1377,14 @@ to the completion callback. `mode` defaults to `0o777`. ## fs.mkdirSync(path[, mode]) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `mode` {integer} Synchronous mkdir(2). Returns `undefined`. @@ -1313,9 +1477,14 @@ object with an `encoding` property specifying the character encoding to use. ## fs.open(path, flags[, mode], callback) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `flags` {string|number} * `mode` {integer} * `callback` {Function} @@ -1397,9 +1566,14 @@ fs.open('', 'a+', (err, fd) => { ## fs.openSync(path, flags[, mode]) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `flags` {string|number} * `mode` {integer} @@ -1442,6 +1616,10 @@ The callback is given the three arguments, `(err, bytesRead, buffer)`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` * `callback` {Function} @@ -1468,9 +1646,14 @@ the filenames returned will be passed as `Buffer` objects. ## fs.readdirSync(path[, options]) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` @@ -1482,10 +1665,14 @@ object with an `encoding` property specifying the character encoding to use for the filenames passed to the callback. If the `encoding` is set to `'buffer'`, the filenames returned will be passed as `Buffer` objects. -## fs.readFile(file[, options], callback) +## fs.readFile(path[, options], callback) -* `file` {string|Buffer|integer} filename or file descriptor +* `path` {string|Buffer|URL|integer} filename or file descriptor * `options` {Object|string} * `encoding` {string|null} default = `null` * `flag` {string} default = `'r'` @@ -1527,19 +1714,23 @@ fs.readFile('/etc/passwd', 'utf8', callback); Any specified file descriptor has to support reading. -_Note: If a file descriptor is specified as the `file`, it will not be closed +_Note: If a file descriptor is specified as the `path`, it will not be closed automatically._ -## fs.readFileSync(file[, options]) +## fs.readFileSync(path[, options]) -* `file` {string|Buffer|integer} filename or file descriptor +* `path` {string|Buffer|URL|integer} filename or file descriptor * `options` {Object|string} * `encoding` {string|null} default = `null` * `flag` {string} default = `'r'` @@ -1553,13 +1744,17 @@ string. Otherwise it returns a buffer. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` * `callback` {Function} @@ -1575,9 +1770,14 @@ the link path returned will be passed as a `Buffer` object. ## fs.readlinkSync(path[, options]) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` @@ -1609,6 +1809,10 @@ Synchronous version of [`fs.read()`][]. Returns the number of `bytesRead`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` * `callback` {Function} @@ -1641,6 +1845,10 @@ the path returned will be passed as a `Buffer` object. -* `path` {string|Buffer}; +* `path` {string|Buffer|URL} * `options` {string|Object} * `encoding` {string} default = `'utf8'` @@ -1667,14 +1875,19 @@ will be passed as a `Buffer` object. -* `oldPath` {string|Buffer} -* `newPath` {string|Buffer} +* `oldPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} * `callback` {Function} Asynchronous rename(2). No arguments other than a possible exception are given @@ -1683,10 +1896,16 @@ to the completion callback. ## fs.renameSync(oldPath, newPath) -* `oldPath` {string|Buffer} -* `newPath` {string|Buffer} +* `oldPath` {string|Buffer|URL} +* `newPath` {string|Buffer|URL} Synchronous rename(2). Returns `undefined`. @@ -1694,13 +1913,17 @@ Synchronous rename(2). Returns `undefined`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `callback` {Function} Asynchronous rmdir(2). No arguments other than a possible exception are given @@ -1709,9 +1932,14 @@ to the completion callback. ## fs.rmdirSync(path) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} Synchronous rmdir(2). Returns `undefined`. @@ -1719,13 +1947,17 @@ Synchronous rmdir(2). Returns `undefined`. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `callback` {Function} Asynchronous stat(2). The callback gets two arguments `(err, stats)` where @@ -1744,19 +1976,30 @@ is recommended. ## fs.statSync(path) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} Synchronous stat(2). Returns an instance of [`fs.Stats`][]. ## fs.symlink(target, path[, type], callback) -* `target` {string|Buffer} -* `path` {string|Buffer} +* `target` {string|Buffer|URL} +* `path` {string|Buffer|URL} * `type` {string} * `callback` {Function} @@ -1778,10 +2021,16 @@ It creates a symbolic link named "new-port" that points to "foo". ## fs.symlinkSync(target, path[, type]) -* `target` {string|Buffer} -* `path` {string|Buffer} +* `target` {string|Buffer|URL} +* `path` {string|Buffer|URL} * `type` {string} Synchronous symlink(2). Returns `undefined`. @@ -1819,13 +2068,17 @@ passed as the first argument. In this case, `fs.ftruncateSync()` is called. -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `callback` {Function} Asynchronous unlink(2). No arguments other than a possible exception are given @@ -1834,9 +2087,14 @@ to the completion callback. ## fs.unlinkSync(path) -* `path` {string|Buffer} +* `path` {string|Buffer|URL} Synchronous unlink(2). Returns `undefined`. @@ -1863,6 +2121,10 @@ when possible._ -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `atime` {integer} * `mtime` {integer} * `callback` {Function} @@ -1893,13 +2155,17 @@ follow these rules: -* `path` {string|Buffer} +* `path` {string|Buffer|URL} * `atime` {integer} * `mtime` {integer} @@ -1909,12 +2175,16 @@ Synchronous version of [`fs.utimes()`][]. Returns `undefined`. -* `filename` {string|Buffer} +* `filename` {string|Buffer|URL} * `options` {string|Object} * `persistent` {boolean} Indicates whether the process should continue to run as long as files are being watched. default = `true` @@ -2015,9 +2285,14 @@ fs.watch('somedir', (eventType, filename) => { ## fs.watchFile(filename[, options], listener) -* `filename` {string|Buffer} +* `filename` {string|Buffer|URL} * `options` {Object} * `persistent` {boolean} * `interval` {integer} @@ -2513,3 +2788,4 @@ The following constants are meant for use with the [`fs.Stats`][] object's [`AHAFS`]: https://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ [Common System Errors]: errors.html#errors_common_system_errors [`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array +[`URL`]: url.html#url_the_whatwg_url_api