path: assert inputs are strings
This commit makes input type checking consistent across all path functions. PR-URL: https://github.com/nodejs/node/pull/5348 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io>
This commit is contained in:
parent
af09a9cc1b
commit
08085c49b6
@ -3,16 +3,16 @@
|
||||
Stability: 2 - Stable
|
||||
|
||||
This module contains utilities for handling and transforming file
|
||||
paths. Almost all these methods perform only string transformations.
|
||||
The file system is not consulted to check whether paths are valid.
|
||||
paths. The file system is not consulted to check whether paths are valid.
|
||||
|
||||
Use `require('path')` to use this module. The following methods are provided:
|
||||
|
||||
## path.basename(p[, ext])
|
||||
## path.basename(path[, ext])
|
||||
|
||||
Return the last portion of a path. Similar to the Unix `basename` command.
|
||||
Return the last portion of a path, similar to the Unix `basename` command.
|
||||
`path` must be a string. `ext`, if given, must also be a string.
|
||||
|
||||
Example:
|
||||
Examples:
|
||||
|
||||
```js
|
||||
path.basename('/foo/bar/baz/asdf/quux.html')
|
||||
@ -46,9 +46,10 @@ process.env.PATH.split(path.delimiter)
|
||||
// returns ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
|
||||
```
|
||||
|
||||
## path.dirname(p)
|
||||
## path.dirname(path)
|
||||
|
||||
Return the directory name of a path. Similar to the Unix `dirname` command.
|
||||
Return the directory name of a path, similar to the Unix `dirname` command.
|
||||
`path` must be a string.
|
||||
|
||||
Example:
|
||||
|
||||
@ -57,12 +58,14 @@ path.dirname('/foo/bar/baz/asdf/quux')
|
||||
// returns '/foo/bar/baz/asdf'
|
||||
```
|
||||
|
||||
## path.extname(p)
|
||||
## path.extname(path)
|
||||
|
||||
Return the extension of the path, from the last '.' to end of string
|
||||
in the last portion of the path. If there is no '.' in the last portion
|
||||
of the path or the first character of it is '.', then it returns
|
||||
an empty string. Examples:
|
||||
an empty string. `path` must be a string.
|
||||
|
||||
Examples:
|
||||
|
||||
```js
|
||||
path.extname('index.html')
|
||||
@ -100,6 +103,8 @@ string will be the contents of the `base` property.
|
||||
If the `base` property is not supplied, a concatenation of the `name` property
|
||||
and the `ext` property will be used as the `base` property.
|
||||
|
||||
Examples:
|
||||
|
||||
```js
|
||||
path.format({
|
||||
root : "/",
|
||||
@ -123,9 +128,10 @@ path.format({
|
||||
## path.isAbsolute(path)
|
||||
|
||||
Determines whether `path` is an absolute path. An absolute path will always
|
||||
resolve to the same location, regardless of the working directory.
|
||||
resolve to the same location, regardless of the working directory. `path` must
|
||||
be a string.
|
||||
|
||||
Posix examples:
|
||||
Examples on \*nix:
|
||||
|
||||
```js
|
||||
path.isAbsolute('/foo/bar') // true
|
||||
@ -134,7 +140,7 @@ path.isAbsolute('qux/') // false
|
||||
path.isAbsolute('.') // false
|
||||
```
|
||||
|
||||
Windows examples:
|
||||
Examples on Windows:
|
||||
|
||||
```js
|
||||
path.isAbsolute('//server') // true
|
||||
@ -151,10 +157,10 @@ path.isAbsolute('.') // false
|
||||
|
||||
Join all arguments together and normalize the resulting path.
|
||||
|
||||
Arguments must be strings. In v0.8, non-string arguments were
|
||||
All arguments must be strings. In v0.8, non-string arguments were
|
||||
silently ignored. In v0.10 and up, an exception is thrown.
|
||||
|
||||
Example:
|
||||
Examples:
|
||||
|
||||
```js
|
||||
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
|
||||
@ -170,9 +176,10 @@ TypeError: Arguments to path.join must be strings
|
||||
zero-length string then `'.'` will be returned, which represents the
|
||||
current working directory.
|
||||
|
||||
## path.normalize(p)
|
||||
## path.normalize(path)
|
||||
|
||||
Normalize a string path, taking care of `'..'` and `'.'` parts.
|
||||
Normalize a path, taking care of `'..'` and `'.'` parts. `path` must be a
|
||||
string.
|
||||
|
||||
When multiple slashes are found, they're replaced by a single one;
|
||||
when the path contains a trailing slash, it is preserved.
|
||||
@ -188,9 +195,9 @@ path.normalize('/foo/bar//baz/asdf/quux/..')
|
||||
*Note:* If the path string passed as argument is a zero-length string then `'.'`
|
||||
will be returned, which represents the current working directory.
|
||||
|
||||
## path.parse(pathString)
|
||||
## path.parse(path)
|
||||
|
||||
Returns an object from a path string.
|
||||
Returns an object from a path. `path` must be a string.
|
||||
|
||||
An example on \*nix:
|
||||
|
||||
@ -227,7 +234,7 @@ compatible way.
|
||||
|
||||
## path.relative(from, to)
|
||||
|
||||
Solve the relative path from `from` to `to`.
|
||||
Solve the relative path from `from` to `to`. `from` and `to` must be strings.
|
||||
|
||||
At times we have two absolute paths, and we need to derive the relative
|
||||
path from one to the other. This is actually the reverse transform of
|
||||
@ -253,13 +260,13 @@ path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
|
||||
|
||||
## path.resolve([from ...], to)
|
||||
|
||||
Resolves `to` to an absolute path.
|
||||
Resolves `to` to an absolute path. All arguments must be strings.
|
||||
|
||||
If `to` isn't already absolute `from` arguments are prepended in right to left
|
||||
order, until an absolute path is found. If after using all `from` paths still
|
||||
no absolute path is found, the current working directory is used as well. The
|
||||
resulting path is normalized, and trailing slashes are removed unless the path
|
||||
gets resolved to the root directory. Non-string `from` arguments are ignored.
|
||||
gets resolved to the root directory.
|
||||
|
||||
Another way to think of it is as a sequence of `cd` commands in a shell.
|
||||
|
||||
@ -320,4 +327,4 @@ An example on Windows:
|
||||
Provide access to aforementioned `path` methods but always interact in a win32
|
||||
compatible way.
|
||||
|
||||
[`path.parse`]: #path_path_parse_pathstring
|
||||
[`path.parse`]: #path_path_parse_path
|
||||
|
18
lib/path.js
18
lib/path.js
@ -734,8 +734,7 @@ const win32 = {
|
||||
|
||||
|
||||
dirname: function dirname(path) {
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
const len = path.length;
|
||||
if (len === 0)
|
||||
return '.';
|
||||
@ -839,8 +838,7 @@ const win32 = {
|
||||
basename: function basename(path, ext) {
|
||||
if (ext !== undefined && typeof ext !== 'string')
|
||||
throw new TypeError('"ext" argument must be a string');
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
var start = 0;
|
||||
var end = -1;
|
||||
var matchedSlash = true;
|
||||
@ -926,8 +924,7 @@ const win32 = {
|
||||
|
||||
|
||||
extname: function extname(path) {
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
var startDot = -1;
|
||||
var startPart = 0;
|
||||
var end = -1;
|
||||
@ -1364,8 +1361,7 @@ const posix = {
|
||||
|
||||
|
||||
dirname: function dirname(path) {
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
if (path.length === 0)
|
||||
return '.';
|
||||
var code = path.charCodeAt(0);
|
||||
@ -1396,8 +1392,7 @@ const posix = {
|
||||
basename: function basename(path, ext) {
|
||||
if (ext !== undefined && typeof ext !== 'string')
|
||||
throw new TypeError('"ext" argument must be a string');
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
|
||||
var start = 0;
|
||||
var end = -1;
|
||||
@ -1471,8 +1466,7 @@ const posix = {
|
||||
|
||||
|
||||
extname: function extname(path) {
|
||||
if (typeof path !== 'string')
|
||||
path = '' + path;
|
||||
assertPath(path);
|
||||
var startDot = -1;
|
||||
var startPart = 0;
|
||||
var end = -1;
|
||||
|
@ -23,11 +23,11 @@ assert.equal(path.win32.basename('basename.ext'), 'basename.ext');
|
||||
assert.equal(path.win32.basename('basename.ext\\'), 'basename.ext');
|
||||
assert.equal(path.win32.basename('basename.ext\\\\'), 'basename.ext');
|
||||
assert.equal(path.win32.basename('foo'), 'foo');
|
||||
assert.equal(path.win32.basename(null), 'null');
|
||||
assert.equal(path.win32.basename(true), 'true');
|
||||
assert.equal(path.win32.basename(1), '1');
|
||||
assert.equal(path.win32.basename(), 'undefined');
|
||||
assert.equal(path.win32.basename({}), '[object Object]');
|
||||
assert.throws(path.win32.basename.bind(null, null), TypeError);
|
||||
assert.throws(path.win32.basename.bind(null, true), TypeError);
|
||||
assert.throws(path.win32.basename.bind(null, 1), TypeError);
|
||||
assert.throws(path.win32.basename.bind(null), TypeError);
|
||||
assert.throws(path.win32.basename.bind(null, {}), TypeError);
|
||||
|
||||
// On unix a backslash is just treated as any other character.
|
||||
assert.equal(path.posix.basename('\\dir\\basename.ext'), '\\dir\\basename.ext');
|
||||
@ -36,11 +36,11 @@ assert.equal(path.posix.basename('basename.ext'), 'basename.ext');
|
||||
assert.equal(path.posix.basename('basename.ext\\'), 'basename.ext\\');
|
||||
assert.equal(path.posix.basename('basename.ext\\\\'), 'basename.ext\\\\');
|
||||
assert.equal(path.posix.basename('foo'), 'foo');
|
||||
assert.equal(path.posix.basename(null), 'null');
|
||||
assert.equal(path.posix.basename(true), 'true');
|
||||
assert.equal(path.posix.basename(1), '1');
|
||||
assert.equal(path.posix.basename(), 'undefined');
|
||||
assert.equal(path.posix.basename({}), '[object Object]');
|
||||
assert.throws(path.posix.basename.bind(null, null), TypeError);
|
||||
assert.throws(path.posix.basename.bind(null, true), TypeError);
|
||||
assert.throws(path.posix.basename.bind(null, 1), TypeError);
|
||||
assert.throws(path.posix.basename.bind(null), TypeError);
|
||||
assert.throws(path.posix.basename.bind(null, {}), TypeError);
|
||||
|
||||
// POSIX filenames may include control characters
|
||||
// c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
|
||||
@ -60,11 +60,11 @@ assert.equal(path.posix.dirname(''), '.');
|
||||
assert.equal(path.posix.dirname('/'), '/');
|
||||
assert.equal(path.posix.dirname('////'), '/');
|
||||
assert.equal(path.posix.dirname('foo'), '.');
|
||||
assert.equal(path.posix.dirname(null), '.');
|
||||
assert.equal(path.posix.dirname(true), '.');
|
||||
assert.equal(path.posix.dirname(1), '.');
|
||||
assert.equal(path.posix.dirname(), '.');
|
||||
assert.equal(path.posix.dirname({}), '.');
|
||||
assert.throws(path.posix.dirname.bind(null, null), TypeError);
|
||||
assert.throws(path.posix.dirname.bind(null, true), TypeError);
|
||||
assert.throws(path.posix.dirname.bind(null, 1), TypeError);
|
||||
assert.throws(path.posix.dirname.bind(null), TypeError);
|
||||
assert.throws(path.posix.dirname.bind(null, {}), TypeError);
|
||||
|
||||
assert.equal(path.win32.dirname('c:\\'), 'c:\\');
|
||||
assert.equal(path.win32.dirname('c:\\foo'), 'c:\\');
|
||||
@ -100,11 +100,11 @@ assert.equal(path.win32.dirname(''), '.');
|
||||
assert.equal(path.win32.dirname('/'), '/');
|
||||
assert.equal(path.win32.dirname('////'), '/');
|
||||
assert.equal(path.win32.dirname('foo'), '.');
|
||||
assert.equal(path.win32.dirname(null), '.');
|
||||
assert.equal(path.win32.dirname(true), '.');
|
||||
assert.equal(path.win32.dirname(1), '.');
|
||||
assert.equal(path.win32.dirname(), '.');
|
||||
assert.equal(path.win32.dirname({}), '.');
|
||||
assert.throws(path.win32.dirname.bind(null, null), TypeError);
|
||||
assert.throws(path.win32.dirname.bind(null, true), TypeError);
|
||||
assert.throws(path.win32.dirname.bind(null, 1), TypeError);
|
||||
assert.throws(path.win32.dirname.bind(null), TypeError);
|
||||
assert.throws(path.win32.dirname.bind(null, {}), TypeError);
|
||||
|
||||
|
||||
// path.extname tests
|
||||
@ -180,11 +180,11 @@ assert.equal(path.win32.extname('file\\'), '');
|
||||
assert.equal(path.win32.extname('file\\\\'), '');
|
||||
assert.equal(path.win32.extname('file.\\'), '.');
|
||||
assert.equal(path.win32.extname('file.\\\\'), '.');
|
||||
assert.equal(path.win32.extname(null), '');
|
||||
assert.equal(path.win32.extname(true), '');
|
||||
assert.equal(path.win32.extname(1), '');
|
||||
assert.equal(path.win32.extname(), '');
|
||||
assert.equal(path.win32.extname({}), '');
|
||||
assert.throws(path.win32.extname.bind(null, null), TypeError);
|
||||
assert.throws(path.win32.extname.bind(null, true), TypeError);
|
||||
assert.throws(path.win32.extname.bind(null, 1), TypeError);
|
||||
assert.throws(path.win32.extname.bind(null), TypeError);
|
||||
assert.throws(path.win32.extname.bind(null, {}), TypeError);
|
||||
|
||||
// On *nix, backslash is a valid name component like any other character.
|
||||
assert.equal(path.posix.extname('.\\'), '');
|
||||
@ -195,11 +195,11 @@ assert.equal(path.posix.extname('file\\'), '');
|
||||
assert.equal(path.posix.extname('file\\\\'), '');
|
||||
assert.equal(path.posix.extname('file.\\'), '.\\');
|
||||
assert.equal(path.posix.extname('file.\\\\'), '.\\\\');
|
||||
assert.equal(path.posix.extname(null), '');
|
||||
assert.equal(path.posix.extname(true), '');
|
||||
assert.equal(path.posix.extname(1), '');
|
||||
assert.equal(path.posix.extname(), '');
|
||||
assert.equal(path.posix.extname({}), '');
|
||||
assert.throws(path.posix.extname.bind(null, null), TypeError);
|
||||
assert.throws(path.posix.extname.bind(null, true), TypeError);
|
||||
assert.throws(path.posix.extname.bind(null, 1), TypeError);
|
||||
assert.throws(path.posix.extname.bind(null), TypeError);
|
||||
assert.throws(path.posix.extname.bind(null, {}), TypeError);
|
||||
|
||||
|
||||
// path.join tests
|
||||
@ -336,10 +336,10 @@ assert.equal(failures.length, 0, failures.join(''));
|
||||
|
||||
|
||||
// Test thrown TypeErrors
|
||||
var typeErrorTests = [true, false, 7, null, {}, undefined, [], NaN];
|
||||
const typeErrorTests = [true, false, 7, null, {}, undefined, [], NaN];
|
||||
|
||||
function fail(fn) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
assert.throws(function() {
|
||||
fn.apply(null, args);
|
||||
@ -347,24 +347,23 @@ function fail(fn) {
|
||||
}
|
||||
|
||||
typeErrorTests.forEach(function(test) {
|
||||
fail(path.join, test);
|
||||
fail(path.resolve, test);
|
||||
fail(path.normalize, test);
|
||||
fail(path.isAbsolute, test);
|
||||
fail(path.relative, test, 'foo');
|
||||
fail(path.relative, 'foo', test);
|
||||
fail(path.parse, test);
|
||||
|
||||
// These methods should throw a TypeError, but do not for backwards
|
||||
// compatibility. Uncommenting these lines in the future should be a goal.
|
||||
// fail(path.dirname, test);
|
||||
// fail(path.basename, test);
|
||||
// fail(path.extname, test);
|
||||
[path.posix, path.win32].forEach(function(namespace) {
|
||||
fail(namespace.join, test);
|
||||
fail(namespace.resolve, test);
|
||||
fail(namespace.normalize, test);
|
||||
fail(namespace.isAbsolute, test);
|
||||
fail(namespace.relative, test, 'foo');
|
||||
fail(namespace.relative, 'foo', test);
|
||||
fail(namespace.parse, test);
|
||||
fail(namespace.dirname, test);
|
||||
fail(namespace.basename, test);
|
||||
fail(namespace.extname, test);
|
||||
|
||||
// undefined is a valid value as the second argument to basename
|
||||
if (test !== undefined) {
|
||||
fail(path.basename, 'foo', test);
|
||||
fail(namespace.basename, 'foo', test);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user