Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 17 additions & 205 deletions lib/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
const {
FunctionPrototypeBind,
StringPrototypeCharCodeAt,
StringPrototypeIndexOf,
StringPrototypeLastIndexOf,
StringPrototypeReplace,
StringPrototypeSlice,
StringPrototypeToLowerCase,
} = primordials;
Expand All @@ -46,6 +44,7 @@ const {
validateObject,
validateString,
} = require('internal/validators');
const _path = internalBinding('path');

const platformIsWin32 = (process.platform === 'win32');

Expand Down Expand Up @@ -153,154 +152,17 @@ function _format(sep, pathObject) {
return dir === pathObject.root ? `${dir}${base}` : `${dir}${sep}${base}`;
}

const win32 = {
/**
* path.resolve([from ...], to)
* @param {...string} args
* @returns {string}
*/
resolve(...args) {
let resolvedDevice = '';
let resolvedTail = '';
let resolvedAbsolute = false;

for (let i = args.length - 1; i >= -1; i--) {
let path;
if (i >= 0) {
path = args[i];
validateString(path, `paths[${i}]`);

// Skip empty entries
if (path.length === 0) {
continue;
}
} else if (resolvedDevice.length === 0) {
path = process.cwd();
} else {
// Windows has the concept of drive-specific current working
// directories. If we've resolved a drive letter but not yet an
// absolute path, get cwd for that drive, or the process cwd if
// the drive cwd is not available. We're sure the device is not
// a UNC path at this points, because UNC paths are always absolute.
path = process.env[`=${resolvedDevice}`] || process.cwd();

// Verify that a cwd was found and that it actually points
// to our drive. If not, default to the drive's root.
if (path === undefined ||
(StringPrototypeToLowerCase(StringPrototypeSlice(path, 0, 2)) !==
StringPrototypeToLowerCase(resolvedDevice) &&
StringPrototypeCharCodeAt(path, 2) === CHAR_BACKWARD_SLASH)) {
path = `${resolvedDevice}\\`;
}
}

const len = path.length;
let rootEnd = 0;
let device = '';
let isAbsolute = false;
const code = StringPrototypeCharCodeAt(path, 0);

// Try to match a root
if (len === 1) {
if (isPathSeparator(code)) {
// `path` contains just a path separator
rootEnd = 1;
isAbsolute = true;
}
} else if (isPathSeparator(code)) {
// Possible UNC root

// If we started with a separator, we know we at least have an
// absolute path of some kind (UNC or otherwise)
isAbsolute = true;

if (isPathSeparator(StringPrototypeCharCodeAt(path, 1))) {
// Matched double path separator at beginning
let j = 2;
let last = j;
// Match 1 or more non-path separators
while (j < len &&
!isPathSeparator(StringPrototypeCharCodeAt(path, j))) {
j++;
}
if (j < len && j !== last) {
const firstPart = StringPrototypeSlice(path, last, j);
// Matched!
last = j;
// Match 1 or more path separators
while (j < len &&
isPathSeparator(StringPrototypeCharCodeAt(path, j))) {
j++;
}
if (j < len && j !== last) {
// Matched!
last = j;
// Match 1 or more non-path separators
while (j < len &&
!isPathSeparator(StringPrototypeCharCodeAt(path, j))) {
j++;
}
if (j === len || j !== last) {
// We matched a UNC root
device =
`\\\\${firstPart}\\${StringPrototypeSlice(path, last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code) &&
StringPrototypeCharCodeAt(path, 1) === CHAR_COLON) {
// Possible device root
device = StringPrototypeSlice(path, 0, 2);
rootEnd = 2;
if (len > 2 && isPathSeparator(StringPrototypeCharCodeAt(path, 2))) {
// Treat separator following drive name as an absolute path
// indicator
isAbsolute = true;
rootEnd = 3;
}
}

if (device.length > 0) {
if (resolvedDevice.length > 0) {
if (StringPrototypeToLowerCase(device) !==
StringPrototypeToLowerCase(resolvedDevice))
// This path points to another device so it is not applicable
continue;
} else {
resolvedDevice = device;
}
}

if (resolvedAbsolute) {
if (resolvedDevice.length > 0)
break;
} else {
resolvedTail =
`${StringPrototypeSlice(path, rootEnd)}\\${resolvedTail}`;
resolvedAbsolute = isAbsolute;
if (isAbsolute && resolvedDevice.length > 0) {
break;
}
}
}

// At this point the path should be resolved to a full absolute path,
// but handle relative paths to be safe (might happen when process.cwd()
// fails)

// Normalize the tail path
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\',
isPathSeparator);

return resolvedAbsolute ?
`${resolvedDevice}\\${resolvedTail}` :
`${resolvedDevice}${resolvedTail}` || '.';
},
/**
* path.resolve([from ...], to)
* @param {...string} args
* @returns {string}
*/
function resolve(...args) {
return _path.resolve(args);
}

const win32 = {
resolve,
/**
* @param {string} path
* @returns {string}
Expand Down Expand Up @@ -504,8 +366,8 @@ const win32 = {
if (from === to)
return '';

const fromOrig = win32.resolve(from);
const toOrig = win32.resolve(to);
const fromOrig = resolve(from);
const toOrig = resolve(to);

if (fromOrig === toOrig)
return '';
Expand Down Expand Up @@ -624,7 +486,7 @@ const win32 = {
if (typeof path !== 'string' || path.length === 0)
return path;

const resolvedPath = win32.resolve(path);
const resolvedPath = resolve(path);

if (resolvedPath.length <= 2)
return path;
Expand Down Expand Up @@ -1071,58 +933,8 @@ const win32 = {
posix: null,
};

const posixCwd = (() => {
if (platformIsWin32) {
// Converts Windows' backslash path separators to POSIX forward slashes
// and truncates any drive indicator
const regexp = /\\/g;
return () => {
const cwd = StringPrototypeReplace(process.cwd(), regexp, '/');
return StringPrototypeSlice(cwd, StringPrototypeIndexOf(cwd, '/'));
};
}

// We're already on POSIX, no need for any transformations
return () => process.cwd();
})();

const posix = {
/**
* path.resolve([from ...], to)
* @param {...string} args
* @returns {string}
*/
resolve(...args) {
let resolvedPath = '';
let resolvedAbsolute = false;

for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
const path = i >= 0 ? args[i] : posixCwd();
validateString(path, `paths[${i}]`);

// Skip empty entries
if (path.length === 0) {
continue;
}

resolvedPath = `${path}/${resolvedPath}`;
resolvedAbsolute =
StringPrototypeCharCodeAt(path, 0) === CHAR_FORWARD_SLASH;
}

// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)

// Normalize the path
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, '/',
isPosixPathSeparator);

if (resolvedAbsolute) {
return `/${resolvedPath}`;
}
return resolvedPath.length > 0 ? resolvedPath : '.';
},

resolve,
/**
* @param {string} path
* @returns {string}
Expand Down Expand Up @@ -1198,8 +1010,8 @@ const posix = {
return '';

// Trim leading forward slashes.
from = posix.resolve(from);
to = posix.resolve(to);
from = resolve(from);
to = resolve(to);

if (from === to)
return '';
Expand Down
4 changes: 2 additions & 2 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
'src/node_modules.cc',
'src/node_options.cc',
'src/node_os.cc',
'src/node_path.cc',
'src/node_perf.cc',
'src/node_platform.cc',
'src/node_postmortem_metadata.cc',
Expand Down Expand Up @@ -143,7 +144,6 @@
'src/node_watchdog.cc',
'src/node_worker.cc',
'src/node_zlib.cc',
'src/path.cc',
'src/permission/child_process_permission.cc',
'src/permission/fs_permission.cc',
'src/permission/inspector_permission.cc',
Expand Down Expand Up @@ -240,6 +240,7 @@
'src/node_object_wrap.h',
'src/node_options.h',
'src/node_options-inl.h',
'src/node_path.h',
'src/node_perf.h',
'src/node_perf_common.h',
'src/node_platform.h',
Expand All @@ -265,7 +266,6 @@
'src/node_wasi.h',
'src/node_watchdog.h',
'src/node_worker.h',
'src/path.h',
'src/permission/child_process_permission.h',
'src/permission/fs_permission.h',
'src/permission/inspector_permission.h',
Expand Down
1 change: 1 addition & 0 deletions src/node_binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
V(options) \
V(os) \
V(performance) \
V(path) \
V(permission) \
V(pipe_wrap) \
V(process_wrap) \
Expand Down
1 change: 1 addition & 0 deletions src/node_external_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class ExternalReferenceRegistry {
V(modules) \
V(options) \
V(os) \
V(path) \
V(performance) \
V(permission) \
V(process_methods) \
Expand Down
Loading