diff --git a/lib/fs.js b/lib/fs.js index 76bb78715c2..a09c59a96d0 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -204,6 +204,24 @@ function validateOffsetLengthWrite(offset, length, byteLength) { } } +function validatePath(path, propName) { + let err; + + if (propName === undefined) { + propName = 'path'; + } + + if (typeof path !== 'string' && !isUint8Array(path)) { + err = new errors.TypeError('ERR_INVALID_ARG_TYPE', propName, + ['string', 'Buffer', 'URL']); + } + + if (err !== undefined) { + Error.captureStackTrace(err, validatePath); + throw err; + } +} + // Special case of `makeCallback()` that is specific to async `*stat()` calls as // an optimization, since the data passed back to the callback needs to be // transformed anyway. @@ -351,10 +369,7 @@ fs.access = function(path, mode, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; - if (typeof path !== 'string' && !(path instanceof Buffer)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!nullCheck(path, callback)) return; @@ -367,12 +382,7 @@ fs.access = function(path, mode, callback) { fs.accessSync = function(path, mode) { handleError((path = getPathFromURL(path))); - - if (typeof path !== 'string' && !(path instanceof Buffer)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } - + validatePath(path); nullCheck(path); if (mode === undefined) @@ -391,10 +401,7 @@ fs.accessSync = function(path, mode) { fs.exists = function(path, callback) { if (handleError((path = getPathFromURL(path)), cb)) return; - if (typeof path !== 'string' && !(path instanceof Buffer)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!nullCheck(path, cb)) return; var req = new FSReqWrap(); req.oncomplete = cb; @@ -416,7 +423,9 @@ Object.defineProperty(fs.exists, internalUtil.promisify.custom, { fs.existsSync = function(path) { try { handleError((path = getPathFromURL(path))); - if (typeof path !== 'string' && !(path instanceof Buffer)) { + try { + validatePath(path); + } catch (e) { return false; } nullCheck(path); @@ -447,11 +456,10 @@ fs.readFile = function(path, options, callback) { req.oncomplete(null, path); }); return; - } else if (typeof path !== 'string' && !(path instanceof Buffer)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); } + validatePath(path); + binding.open(pathModule.toNamespacedPath(path), stringToFlags(options.flag || 'r'), 0o666, @@ -733,11 +741,7 @@ fs.open = function(path, flags, mode, callback_) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -755,10 +759,7 @@ fs.openSync = function(path, flags, mode) { mode = modeNum(mode, 0o666); handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -896,15 +897,8 @@ fs.rename = function(oldPath, newPath, callback) { if (!nullCheck(oldPath, callback)) return; if (!nullCheck(newPath, callback)) return; - - if (typeof oldPath !== 'string' && !isUint8Array(oldPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', - ['string', 'Buffer', 'URL']); - } - if (typeof newPath !== 'string' && !isUint8Array(newPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', - ['string', 'Buffer', 'URL']); - } + validatePath(oldPath, 'oldPath'); + validatePath(newPath, 'newPath'); const req = new FSReqWrap(); req.oncomplete = callback; binding.rename(pathModule.toNamespacedPath(oldPath), @@ -917,14 +911,8 @@ fs.renameSync = function(oldPath, newPath) { handleError((newPath = getPathFromURL(newPath))); nullCheck(oldPath); nullCheck(newPath); - if (typeof oldPath !== 'string' && !isUint8Array(oldPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', - ['string', 'Buffer', 'URL']); - } - if (typeof newPath !== 'string' && !isUint8Array(newPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', - ['string', 'Buffer', 'URL']); - } + validatePath(oldPath, 'oldPath'); + validatePath(newPath, 'newPath'); return binding.rename(pathModule.toNamespacedPath(oldPath), pathModule.toNamespacedPath(newPath)); }; @@ -1002,10 +990,7 @@ fs.rmdir = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; binding.rmdir(pathModule.toNamespacedPath(path), req); @@ -1014,10 +999,7 @@ fs.rmdir = function(path, callback) { fs.rmdirSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); return binding.rmdir(pathModule.toNamespacedPath(path)); }; @@ -1052,10 +1034,7 @@ fs.mkdir = function(path, mode, callback) { return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); mode = modeNum(mode, 0o777); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -1068,10 +1047,7 @@ fs.mkdir = function(path, mode, callback) { fs.mkdirSync = function(path, mode) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); mode = modeNum(mode, 0o777); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -1085,10 +1061,7 @@ fs.readdir = function(path, options, callback) { return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1099,10 +1072,7 @@ fs.readdirSync = function(path, options) { options = getOptions(options, {}); handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); return binding.readdir(pathModule.toNamespacedPath(path), options.encoding); }; @@ -1118,10 +1088,7 @@ fs.lstat = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; binding.lstat(pathModule.toNamespacedPath(path), req); @@ -1132,10 +1099,7 @@ fs.stat = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; binding.stat(pathModule.toNamespacedPath(path), req); @@ -1150,10 +1114,7 @@ fs.fstatSync = function(fd) { fs.lstatSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); binding.lstat(pathModule.toNamespacedPath(path)); return statsFromValues(); }; @@ -1161,10 +1122,7 @@ fs.lstatSync = function(path) { fs.statSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); binding.stat(pathModule.toNamespacedPath(path)); return statsFromValues(); }; @@ -1175,10 +1133,7 @@ fs.readlink = function(path, options, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', - ['string', 'Buffer', 'URL']); - } + validatePath(path, 'oldPath'); const req = new FSReqWrap(); req.oncomplete = callback; binding.readlink(pathModule.toNamespacedPath(path), options.encoding, req); @@ -1188,10 +1143,7 @@ fs.readlinkSync = function(path, options) { options = getOptions(options, {}); handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'oldPath', - ['string', 'Buffer', 'URL']); - } + validatePath(path, 'oldPath'); return binding.readlink(pathModule.toNamespacedPath(path), options.encoding); }; @@ -1243,15 +1195,8 @@ fs.symlink = function(target, path, type_, callback_) { if (!nullCheck(target, callback)) return; if (!nullCheck(path, callback)) return; - - if (typeof target !== 'string' && !isUint8Array(target)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'target', - ['string', 'Buffer', 'URL']); - } - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(target, 'target'); + validatePath(path); const flags = stringToSymlinkType(type); const req = new FSReqWrap(); @@ -1267,14 +1212,8 @@ fs.symlinkSync = function(target, path, type) { nullCheck(target); nullCheck(path); - if (typeof target !== 'string' && !isUint8Array(target)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'target', - ['string', 'Buffer', 'URL']); - } - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(target, 'target'); + validatePath(path); const flags = stringToSymlinkType(type); return binding.symlink(preprocessSymlinkDestination(target, type, path), pathModule.toNamespacedPath(path), flags); @@ -1292,14 +1231,8 @@ fs.link = function(existingPath, newPath, callback) { if (!nullCheck(existingPath, callback)) return; if (!nullCheck(newPath, callback)) return; - if (typeof existingPath !== 'string' && !isUint8Array(existingPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'existingPath', - ['string', 'Buffer', 'URL']); - } - if (typeof newPath !== 'string' && !isUint8Array(newPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', - ['string', 'Buffer', 'URL']); - } + validatePath(existingPath, 'existingPath'); + validatePath(newPath, 'newPath'); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1314,14 +1247,8 @@ fs.linkSync = function(existingPath, newPath) { handleError((newPath = getPathFromURL(newPath))); nullCheck(existingPath); nullCheck(newPath); - if (typeof existingPath !== 'string' && !isUint8Array(existingPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'existingPath', - ['string', 'Buffer', 'URL']); - } - if (typeof newPath !== 'string' && !isUint8Array(newPath)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'newPath', - ['string', 'Buffer', 'URL']); - } + validatePath(existingPath, 'existingPath'); + validatePath(newPath, 'newPath'); return binding.link(pathModule.toNamespacedPath(existingPath), pathModule.toNamespacedPath(newPath)); }; @@ -1331,10 +1258,7 @@ fs.unlink = function(path, callback) { if (handleError((path = getPathFromURL(path)), callback)) return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; binding.unlink(pathModule.toNamespacedPath(path), req); @@ -1343,10 +1267,7 @@ fs.unlink = function(path, callback) { fs.unlinkSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); return binding.unlink(pathModule.toNamespacedPath(path)); }; @@ -1417,10 +1338,7 @@ fs.chmod = function(path, mode, callback) { return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); mode = modeNum(mode); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -1433,10 +1351,7 @@ fs.chmod = function(path, mode, callback) { fs.chmodSync = function(path, mode) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); mode = modeNum(mode); if (!isUint32(mode)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'integer'); @@ -1489,10 +1404,7 @@ fs.chown = function(path, uid, gid, callback) { return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!isUint32(uid)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); if (!isUint32(gid)) @@ -1506,10 +1418,7 @@ fs.chown = function(path, uid, gid, callback) { fs.chownSync = function(path, uid, gid) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); if (!isUint32(uid)) throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'uid', 'integer'); if (!isUint32(gid)) @@ -1548,10 +1457,7 @@ fs.utimes = function(path, atime, mtime, callback) { return; if (!nullCheck(path, callback)) return; - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); const req = new FSReqWrap(); req.oncomplete = callback; @@ -1564,10 +1470,7 @@ fs.utimes = function(path, atime, mtime, callback) { fs.utimesSync = function(path, atime, mtime) { handleError((path = getPathFromURL(path))); nullCheck(path); - if (typeof path !== 'string' && !isUint8Array(path)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'path', - ['string', 'Buffer', 'URL']); - } + validatePath(path); binding.utimes(pathModule.toNamespacedPath(path), toUnixTimestamp(atime), toUnixTimestamp(mtime)); @@ -2279,14 +2182,8 @@ fs.copyFile = function(src, dest, flags, callback) { if (!nullCheck(dest, callback)) return; - if (typeof src !== 'string' && !isUint8Array(src)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'src', - ['string', 'Buffer', 'URL']); - } - if (typeof dest !== 'string' && !isUint8Array(dest)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'dest', - ['string', 'Buffer', 'URL']); - } + validatePath(src, 'src'); + validatePath(dest, 'dest'); src = pathModule._makeLong(src); dest = pathModule._makeLong(dest); @@ -2306,14 +2203,8 @@ fs.copyFileSync = function(src, dest, flags) { handleError(dest); nullCheck(dest); - if (typeof src !== 'string' && !isUint8Array(src)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'src', - ['string', 'Buffer', 'URL']); - } - if (typeof dest !== 'string' && !isUint8Array(dest)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'dest', - ['string', 'Buffer', 'URL']); - } + validatePath(src, 'src'); + validatePath(dest, 'dest'); src = pathModule._makeLong(src); dest = pathModule._makeLong(dest);