path: deprecate internal _makeLong, replace

Replace the internal `path._makeLong()` with a public
`path.toLongUNCPath()` method. Add documentation.

PR-URL: https://github.com/nodejs/node/pull/14956
Ref: https://github.com/standard-things/esm/issues/66
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
James M Snell 2017-08-20 22:44:47 -07:00
parent 7069e633ca
commit 1f8d527e94
7 changed files with 116 additions and 83 deletions

View File

@ -710,6 +710,16 @@ function for [`util.inspect()`][] is deprecated. Use [`util.inspect.custom`][]
instead. For backwards compatibility with Node.js prior to version 6.4.0, both
may be specified.
<a id="DEP00XX"></a>
### DEP00XX: path.\_makeLong()
Type: Documentation-only
The internal `path._makeLong()` was not intended for public use. However,
userland modules have found it useful. The internal API has been deprecated
and replaced with an identical, public `path.toNamespacedPath()` method.
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
[`Buffer.from(buffer)`]: buffer.html#buffer_class_method_buffer_from_buffer

View File

@ -543,6 +543,21 @@ On Windows:
accepted as path segment separators; however, the `path` methods only add
backward slashes (`\`).
## path.toNamespacedPath(path)
<!-- YAML
added: REPLACEME
-->
* `path` {string}
* Returns: {string}
On Windows systems only, returns an equivalent [namespace-prefixed path][] for
the given `path`. If `path` is not a string, `path` will be returned without
modifications.
This method is meaningful only on Windows system. On posix systems, the
method is non-operational and always returns `path` without modifications.
## path.win32
<!-- YAML
added: v0.11.15
@ -559,3 +574,4 @@ of the `path` methods.
[`path.sep`]: #path_path_sep
[`path.win32`]: #path_path_win32
[MSDN-Rel-Path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#fully_qualified_vs._relative_paths
[namespace-prefixed path]: https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces

View File

@ -293,7 +293,7 @@ fs.access = function(path, mode, callback) {
mode = mode | 0;
var req = new FSReqWrap();
req.oncomplete = makeCallback(callback);
binding.access(pathModule._makeLong(path), mode, req);
binding.access(pathModule.toNamespacedPath(path), mode, req);
};
fs.accessSync = function(path, mode) {
@ -305,7 +305,7 @@ fs.accessSync = function(path, mode) {
else
mode = mode | 0;
binding.access(pathModule._makeLong(path), mode);
binding.access(pathModule.toNamespacedPath(path), mode);
};
fs.exists = function(path, callback) {
@ -314,7 +314,7 @@ fs.exists = function(path, callback) {
if (!nullCheck(path, cb)) return;
var req = new FSReqWrap();
req.oncomplete = cb;
binding.stat(pathModule._makeLong(path), req);
binding.stat(pathModule.toNamespacedPath(path), req);
function cb(err) {
if (callback) callback(err ? false : true);
}
@ -333,7 +333,7 @@ fs.existsSync = function(path) {
try {
handleError((path = getPathFromURL(path)));
nullCheck(path);
binding.stat(pathModule._makeLong(path));
binding.stat(pathModule.toNamespacedPath(path));
return true;
} catch (e) {
return false;
@ -362,7 +362,7 @@ fs.readFile = function(path, options, callback) {
return;
}
binding.open(pathModule._makeLong(path),
binding.open(pathModule.toNamespacedPath(path),
stringToFlags(options.flag || 'r'),
0o666,
req);
@ -646,7 +646,7 @@ fs.open = function(path, flags, mode, callback_) {
var req = new FSReqWrap();
req.oncomplete = callback;
binding.open(pathModule._makeLong(path),
binding.open(pathModule.toNamespacedPath(path),
stringToFlags(flags),
mode,
req);
@ -656,7 +656,8 @@ fs.openSync = function(path, flags, mode) {
mode = modeNum(mode, 0o666);
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode);
return binding.open(pathModule.toNamespacedPath(path),
stringToFlags(flags), mode);
};
fs.read = function(fd, buffer, offset, length, position, callback) {
@ -766,8 +767,8 @@ fs.rename = function(oldPath, newPath, callback) {
if (!nullCheck(newPath, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.rename(pathModule._makeLong(oldPath),
pathModule._makeLong(newPath),
binding.rename(pathModule.toNamespacedPath(oldPath),
pathModule.toNamespacedPath(newPath),
req);
};
@ -776,8 +777,8 @@ fs.renameSync = function(oldPath, newPath) {
handleError((newPath = getPathFromURL(newPath)));
nullCheck(oldPath);
nullCheck(newPath);
return binding.rename(pathModule._makeLong(oldPath),
pathModule._makeLong(newPath));
return binding.rename(pathModule.toNamespacedPath(oldPath),
pathModule.toNamespacedPath(newPath));
};
fs.truncate = function(path, len, callback) {
@ -850,13 +851,13 @@ fs.rmdir = function(path, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.rmdir(pathModule._makeLong(path), req);
binding.rmdir(pathModule.toNamespacedPath(path), req);
};
fs.rmdirSync = function(path) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.rmdir(pathModule._makeLong(path));
return binding.rmdir(pathModule.toNamespacedPath(path));
};
fs.fdatasync = function(fd, callback) {
@ -887,7 +888,7 @@ fs.mkdir = function(path, mode, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.mkdir(pathModule._makeLong(path),
binding.mkdir(pathModule.toNamespacedPath(path),
modeNum(mode, 0o777),
req);
};
@ -895,7 +896,7 @@ fs.mkdir = function(path, mode, callback) {
fs.mkdirSync = function(path, mode) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.mkdir(pathModule._makeLong(path),
return binding.mkdir(pathModule.toNamespacedPath(path),
modeNum(mode, 0o777));
};
@ -907,14 +908,14 @@ fs.readdir = function(path, options, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.readdir(pathModule._makeLong(path), options.encoding, req);
binding.readdir(pathModule.toNamespacedPath(path), options.encoding, req);
};
fs.readdirSync = function(path, options) {
options = getOptions(options, {});
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.readdir(pathModule._makeLong(path), options.encoding);
return binding.readdir(pathModule.toNamespacedPath(path), options.encoding);
};
fs.fstat = function(fd, callback) {
@ -930,7 +931,7 @@ fs.lstat = function(path, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.lstat(pathModule._makeLong(path), req);
binding.lstat(pathModule.toNamespacedPath(path), req);
};
fs.stat = function(path, callback) {
@ -940,7 +941,7 @@ fs.stat = function(path, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.stat(pathModule._makeLong(path), req);
binding.stat(pathModule.toNamespacedPath(path), req);
};
fs.fstatSync = function(fd) {
@ -951,14 +952,14 @@ fs.fstatSync = function(fd) {
fs.lstatSync = function(path) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
binding.lstat(pathModule._makeLong(path));
binding.lstat(pathModule.toNamespacedPath(path));
return statsFromValues();
};
fs.statSync = function(path) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
binding.stat(pathModule._makeLong(path));
binding.stat(pathModule.toNamespacedPath(path));
return statsFromValues();
};
@ -970,14 +971,14 @@ fs.readlink = function(path, options, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.readlink(pathModule._makeLong(path), options.encoding, req);
binding.readlink(pathModule.toNamespacedPath(path), options.encoding, req);
};
fs.readlinkSync = function(path, options) {
options = getOptions(options, {});
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.readlink(pathModule._makeLong(path), options.encoding);
return binding.readlink(pathModule.toNamespacedPath(path), options.encoding);
};
function preprocessSymlinkDestination(path, type, linkPath) {
@ -988,7 +989,7 @@ function preprocessSymlinkDestination(path, type, linkPath) {
// Junctions paths need to be absolute and \\?\-prefixed.
// A relative target is relative to the link's parent directory.
path = pathModule.resolve(linkPath, '..', path);
return pathModule._makeLong(path);
return pathModule.toNamespacedPath(path);
} else {
// Windows symlinks don't tolerate forward slashes.
return ('' + path).replace(/\//g, '\\');
@ -1012,7 +1013,7 @@ fs.symlink = function(target, path, type_, callback_) {
req.oncomplete = callback;
binding.symlink(preprocessSymlinkDestination(target, type, path),
pathModule._makeLong(path),
pathModule.toNamespacedPath(path),
type,
req);
};
@ -1025,7 +1026,7 @@ fs.symlinkSync = function(target, path, type) {
nullCheck(path);
return binding.symlink(preprocessSymlinkDestination(target, type, path),
pathModule._makeLong(path),
pathModule.toNamespacedPath(path),
type);
};
@ -1044,8 +1045,8 @@ fs.link = function(existingPath, newPath, callback) {
var req = new FSReqWrap();
req.oncomplete = callback;
binding.link(pathModule._makeLong(existingPath),
pathModule._makeLong(newPath),
binding.link(pathModule.toNamespacedPath(existingPath),
pathModule.toNamespacedPath(newPath),
req);
};
@ -1054,8 +1055,8 @@ fs.linkSync = function(existingPath, newPath) {
handleError((newPath = getPathFromURL(newPath)));
nullCheck(existingPath);
nullCheck(newPath);
return binding.link(pathModule._makeLong(existingPath),
pathModule._makeLong(newPath));
return binding.link(pathModule.toNamespacedPath(existingPath),
pathModule.toNamespacedPath(newPath));
};
fs.unlink = function(path, callback) {
@ -1065,13 +1066,13 @@ fs.unlink = function(path, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.unlink(pathModule._makeLong(path), req);
binding.unlink(pathModule.toNamespacedPath(path), req);
};
fs.unlinkSync = function(path) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.unlink(pathModule._makeLong(path));
return binding.unlink(pathModule.toNamespacedPath(path));
};
fs.fchmod = function(fd, mode, callback) {
@ -1129,7 +1130,7 @@ fs.chmod = function(path, mode, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.chmod(pathModule._makeLong(path),
binding.chmod(pathModule.toNamespacedPath(path),
modeNum(mode),
req);
};
@ -1137,7 +1138,7 @@ fs.chmod = function(path, mode, callback) {
fs.chmodSync = function(path, mode) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.chmod(pathModule._makeLong(path), modeNum(mode));
return binding.chmod(pathModule.toNamespacedPath(path), modeNum(mode));
};
if (constants.O_SYMLINK !== undefined) {
@ -1175,13 +1176,13 @@ fs.chown = function(path, uid, gid, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.chown(pathModule._makeLong(path), uid, gid, req);
binding.chown(pathModule.toNamespacedPath(path), uid, gid, req);
};
fs.chownSync = function(path, uid, gid) {
handleError((path = getPathFromURL(path)));
nullCheck(path);
return binding.chown(pathModule._makeLong(path), uid, gid);
return binding.chown(pathModule.toNamespacedPath(path), uid, gid);
};
// converts Date or number to a fractional UNIX timestamp
@ -1216,7 +1217,7 @@ fs.utimes = function(path, atime, mtime, callback) {
if (!nullCheck(path, callback)) return;
var req = new FSReqWrap();
req.oncomplete = callback;
binding.utimes(pathModule._makeLong(path),
binding.utimes(pathModule.toNamespacedPath(path),
toUnixTimestamp(atime),
toUnixTimestamp(mtime),
req);
@ -1227,7 +1228,7 @@ fs.utimesSync = function(path, atime, mtime) {
nullCheck(path);
atime = toUnixTimestamp(atime);
mtime = toUnixTimestamp(mtime);
binding.utimes(pathModule._makeLong(path), atime, mtime);
binding.utimes(pathModule.toNamespacedPath(path), atime, mtime);
};
fs.futimes = function(fd, atime, mtime, callback) {
@ -1383,7 +1384,7 @@ FSWatcher.prototype.start = function(filename,
encoding) {
handleError((filename = getPathFromURL(filename)));
nullCheck(filename);
var err = this._handle.start(pathModule._makeLong(filename),
var err = this._handle.start(pathModule.toNamespacedPath(filename),
persistent,
recursive,
encoding);
@ -1472,7 +1473,8 @@ util.inherits(StatWatcher, EventEmitter);
StatWatcher.prototype.start = function(filename, persistent, interval) {
handleError((filename = getPathFromURL(filename)));
nullCheck(filename);
this._handle.start(pathModule._makeLong(filename), persistent, interval);
this._handle.start(pathModule.toNamespacedPath(filename),
persistent, interval);
};
@ -1627,7 +1629,7 @@ fs.realpathSync = function realpathSync(p, options) {
// On windows, check that the root exists. On unix there is no need.
if (isWindows && !knownHard[base]) {
binding.lstat(pathModule._makeLong(base));
binding.lstat(pathModule.toNamespacedPath(base));
knownHard[base] = true;
}
@ -1666,7 +1668,7 @@ fs.realpathSync = function realpathSync(p, options) {
// Use stats array directly to avoid creating an fs.Stats instance just
// for our internal use.
var baseLong = pathModule._makeLong(base);
var baseLong = pathModule.toNamespacedPath(base);
binding.lstat(baseLong);
if ((statValues[1/*mode*/] & S_IFMT) !== S_IFLNK) {
@ -1706,7 +1708,7 @@ fs.realpathSync = function realpathSync(p, options) {
// On windows, check that the root exists. On unix there is no need.
if (isWindows && !knownHard[base]) {
binding.lstat(pathModule._makeLong(base));
binding.lstat(pathModule.toNamespacedPath(base));
knownHard[base] = true;
}
}

View File

@ -43,7 +43,7 @@ const { createDynamicModule } = require('internal/loader/ModuleWrap');
const ESMLoader = new Loader();
function stat(filename) {
filename = path._makeLong(filename);
filename = path.toNamespacedPath(filename);
const cache = stat.cache;
if (cache !== null) {
const result = cache.get(filename);
@ -106,7 +106,7 @@ function readPackage(requestPath) {
return entry;
const jsonPath = path.resolve(requestPath, 'package.json');
const json = internalModuleReadFile(path._makeLong(jsonPath));
const json = internalModuleReadFile(path.toNamespacedPath(jsonPath));
if (json === undefined) {
return false;
@ -626,7 +626,7 @@ Module._extensions['.json'] = function(module, filename) {
//Native extension for .node
Module._extensions['.node'] = function(module, filename) {
return process.dlopen(module, path._makeLong(filename));
return process.dlopen(module, path.toNamespacedPath(filename));
};
if (experimentalModules) {

View File

@ -687,7 +687,7 @@ const win32 = {
},
_makeLong: function _makeLong(path) {
toNamespacedPath: function toNamespacedPath(path) {
// Note: this will *probably* throw somewhere.
if (typeof path !== 'string')
return path;
@ -725,7 +725,6 @@ const win32 = {
return path;
},
dirname: function dirname(path) {
assertPath(path);
const len = path.length;
@ -1356,11 +1355,11 @@ const posix = {
},
_makeLong: function _makeLong(path) {
toNamespacedPath: function toNamespacedPath(path) {
// Non-op on posix systems
return path;
},
dirname: function dirname(path) {
assertPath(path);
if (path.length === 0)
@ -1630,6 +1629,9 @@ const posix = {
posix.win32 = win32.win32 = win32;
posix.posix = win32.posix = posix;
// Legacy internal API, docs-only deprecated: DEP00XX
win32._makeLong = win32.toNamespacedPath;
posix._makeLong = posix.toNamespacedPath;
if (process.platform === 'win32')
module.exports = win32;

View File

@ -28,53 +28,56 @@ if (common.isWindows) {
const file = path.join(common.fixturesDir, 'a.js');
const resolvedFile = path.resolve(file);
assert.strictEqual(`\\\\?\\${resolvedFile}`, path._makeLong(file));
assert.strictEqual(`\\\\?\\${resolvedFile}`,
path._makeLong(`\\\\?\\${file}`));
path.toNamespacedPath(file));
assert.strictEqual(`\\\\?\\${resolvedFile}`,
path.toNamespacedPath(`\\\\?\\${file}`));
assert.strictEqual('\\\\?\\UNC\\someserver\\someshare\\somefile',
path._makeLong('\\\\someserver\\someshare\\somefile'));
path.toNamespacedPath(
'\\\\someserver\\someshare\\somefile'));
assert.strictEqual('\\\\?\\UNC\\someserver\\someshare\\somefile', path
._makeLong('\\\\?\\UNC\\someserver\\someshare\\somefile'));
.toNamespacedPath('\\\\?\\UNC\\someserver\\someshare\\somefile'));
assert.strictEqual('\\\\.\\pipe\\somepipe',
path._makeLong('\\\\.\\pipe\\somepipe'));
path.toNamespacedPath('\\\\.\\pipe\\somepipe'));
}
assert.strictEqual(path._makeLong(null), null);
assert.strictEqual(path._makeLong(100), 100);
assert.strictEqual(path._makeLong(path), path);
assert.strictEqual(path._makeLong(false), false);
assert.strictEqual(path._makeLong(true), true);
assert.strictEqual(path.toNamespacedPath(null), null);
assert.strictEqual(path.toNamespacedPath(100), 100);
assert.strictEqual(path.toNamespacedPath(path), path);
assert.strictEqual(path.toNamespacedPath(false), false);
assert.strictEqual(path.toNamespacedPath(true), true);
const emptyObj = {};
assert.strictEqual(path.posix._makeLong('/foo/bar'), '/foo/bar');
assert.strictEqual(path.posix._makeLong('foo/bar'), 'foo/bar');
assert.strictEqual(path.posix._makeLong(null), null);
assert.strictEqual(path.posix._makeLong(true), true);
assert.strictEqual(path.posix._makeLong(1), 1);
assert.strictEqual(path.posix._makeLong(), undefined);
assert.strictEqual(path.posix._makeLong(emptyObj), emptyObj);
assert.strictEqual(path.posix.toNamespacedPath('/foo/bar'), '/foo/bar');
assert.strictEqual(path.posix.toNamespacedPath('foo/bar'), 'foo/bar');
assert.strictEqual(path.posix.toNamespacedPath(null), null);
assert.strictEqual(path.posix.toNamespacedPath(true), true);
assert.strictEqual(path.posix.toNamespacedPath(1), 1);
assert.strictEqual(path.posix.toNamespacedPath(), undefined);
assert.strictEqual(path.posix.toNamespacedPath(emptyObj), emptyObj);
if (common.isWindows) {
// These tests cause resolve() to insert the cwd, so we cannot test them from
// non-Windows platforms (easily)
assert.strictEqual(path.win32._makeLong('foo\\bar').toLowerCase(),
assert.strictEqual(path.win32.toNamespacedPath('foo\\bar').toLowerCase(),
`\\\\?\\${process.cwd().toLowerCase()}\\foo\\bar`);
assert.strictEqual(path.win32._makeLong('foo/bar').toLowerCase(),
assert.strictEqual(path.win32.toNamespacedPath('foo/bar').toLowerCase(),
`\\\\?\\${process.cwd().toLowerCase()}\\foo\\bar`);
const currentDeviceLetter = path.parse(process.cwd()).root.substring(0, 2);
assert.strictEqual(path.win32._makeLong(currentDeviceLetter).toLowerCase(),
`\\\\?\\${process.cwd().toLowerCase()}`);
assert.strictEqual(path.win32._makeLong('C').toLowerCase(),
assert.strictEqual(
path.win32.toNamespacedPath(currentDeviceLetter).toLowerCase(),
`\\\\?\\${process.cwd().toLowerCase()}`);
assert.strictEqual(path.win32.toNamespacedPath('C').toLowerCase(),
`\\\\?\\${process.cwd().toLowerCase()}\\c`);
}
assert.strictEqual(path.win32._makeLong('C:\\foo'), '\\\\?\\C:\\foo');
assert.strictEqual(path.win32._makeLong('C:/foo'), '\\\\?\\C:\\foo');
assert.strictEqual(path.win32._makeLong('\\\\foo\\bar'),
assert.strictEqual(path.win32.toNamespacedPath('C:\\foo'), '\\\\?\\C:\\foo');
assert.strictEqual(path.win32.toNamespacedPath('C:/foo'), '\\\\?\\C:\\foo');
assert.strictEqual(path.win32.toNamespacedPath('\\\\foo\\bar'),
'\\\\?\\UNC\\foo\\bar\\');
assert.strictEqual(path.win32._makeLong('//foo//bar'),
assert.strictEqual(path.win32.toNamespacedPath('//foo//bar'),
'\\\\?\\UNC\\foo\\bar\\');
assert.strictEqual(path.win32._makeLong('\\\\?\\foo'), '\\\\?\\foo');
assert.strictEqual(path.win32._makeLong(null), null);
assert.strictEqual(path.win32._makeLong(true), true);
assert.strictEqual(path.win32._makeLong(1), 1);
assert.strictEqual(path.win32._makeLong(), undefined);
assert.strictEqual(path.win32._makeLong(emptyObj), emptyObj);
assert.strictEqual(path.win32.toNamespacedPath('\\\\?\\foo'), '\\\\?\\foo');
assert.strictEqual(path.win32.toNamespacedPath(null), null);
assert.strictEqual(path.win32.toNamespacedPath(true), true);
assert.strictEqual(path.win32.toNamespacedPath(1), 1);
assert.strictEqual(path.win32.toNamespacedPath(), undefined);
assert.strictEqual(path.win32.toNamespacedPath(emptyObj), emptyObj);

View File

@ -118,7 +118,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check
req.oncomplete = () => { };
testUninitialized(req, 'FSReqWrap');
binding.access(path._makeLong('../'), fs.F_OK, req);
binding.access(path.toNamespacedPath('../'), fs.F_OK, req);
testInitialized(req, 'FSReqWrap');
const StatWatcher = binding.StatWatcher;