Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
path: refactor for performance and consistency
Browse files Browse the repository at this point in the history
Improve performance by:
+ Not running the same code twice (in win32.resolve and .normalize)
+ Not leaking the `arguments` object!
+ Getting the last character of a string by index, instead of
  with `.substr()`

Improve code consistency by:
+ Using `[]` instead of `.charAt()` where possible
+ Using a function declaration instead of a var declaration
+ Using .slice() instead of .substr()
+ Standardizing getting certain path statistics with
  the new `win23StatPath()` function

Improve both by:
+ Making the reusable `trimArray()` function
+ Using `.slice()` with clearer arguments
  • Loading branch information
nwoltman committed Mar 19, 2015
1 parent eb2764a commit 7abada1
Showing 1 changed file with 67 additions and 63 deletions.
130 changes: 67 additions & 63 deletions lib/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,29 @@ function normalizeArray(parts, allowAboveRoot) {
return res;
}

// returns an array with empty elements removed from either end of the input
// array or the original array if no elements need to be removed
function trimArray(arr) {
var lastIndex = arr.length - 1;
var start = 0;
for (; start <= lastIndex; start++) {
if (arr[start])
break;
}

var end = lastIndex;
for (; end >= 0; end--) {
if (arr[end])
break;
}

if (start === 0 && end === lastIndex)
return arr;
if (start > end)
return [];
return arr.slice(start, end + 1);
}

// Regex to split a windows path into three parts: [*, device, slash,
// tail] windows-only
var splitDeviceRe =
Expand All @@ -76,9 +99,21 @@ function win32SplitPath(filename) {
return [device, dir, basename, ext];
}

var normalizeUNCRoot = function(device) {
function win32StatPath(path) {
var result = splitDeviceRe.exec(path),
device = result[1] || '',
isUnc = !!device && device[1] !== ':';
return {
device: device,
isUnc: isUnc,
isAbsolute: isUnc || !!result[2], // UNC paths are always absolute
tail: result[3]
};
}

function normalizeUNCRoot(device) {
return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');
};
}

// path.resolve([from ...], to)
win32.resolve = function() {
Expand Down Expand Up @@ -113,11 +148,11 @@ win32.resolve = function() {
continue;
}

var result = splitDeviceRe.exec(path),
device = result[1] || '',
isUnc = device && device.charAt(1) !== ':',
isAbsolute = win32.isAbsolute(path),
tail = result[3];
var result = win32StatPath(path),
device = result.device,
isUnc = result.isUnc,
isAbsolute = result.isAbsolute,
tail = result.tail;

if (device &&
resolvedDevice &&
Expand Down Expand Up @@ -159,11 +194,11 @@ win32.resolve = function() {


win32.normalize = function(path) {
var result = splitDeviceRe.exec(path),
device = result[1] || '',
isUnc = device && device.charAt(1) !== ':',
isAbsolute = win32.isAbsolute(path),
tail = result[3],
var result = win32StatPath(path),
device = result.device,
isUnc = result.isUnc,
isAbsolute = result.isAbsolute,
tail = result.tail,
trailingSlash = /[\\\/]$/.test(tail);

// Normalize the tail path
Expand All @@ -187,22 +222,21 @@ win32.normalize = function(path) {


win32.isAbsolute = function(path) {
var result = splitDeviceRe.exec(path),
device = result[1] || '',
isUnc = !!device && device.charAt(1) !== ':';
// UNC paths are always absolute
return !!result[2] || isUnc;
return win32StatPath(path).isAbsolute;
};

win32.join = function() {
function f(p) {
if (!util.isString(p)) {
var paths = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!util.isString(arg)) {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
if (arg) {
paths.push(arg);
}
}

var paths = Array.prototype.filter.call(arguments, f);
var joined = paths.join('\\');

// Make sure that the joined path doesn't start with two slashes, because
Expand Down Expand Up @@ -239,25 +273,10 @@ win32.relative = function(from, to) {
var lowerFrom = from.toLowerCase();
var lowerTo = to.toLowerCase();

function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}

var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
var toParts = trimArray(to.split('\\'));

if (start > end) return [];
return arr.slice(start, end + 1);
}

var toParts = trim(to.split('\\'));

var lowerFromParts = trim(lowerFrom.split('\\'));
var lowerToParts = trim(lowerTo.split('\\'));
var lowerFromParts = trimArray(lowerFrom.split('\\'));
var lowerToParts = trimArray(lowerTo.split('\\'));

var length = Math.min(lowerFromParts.length, lowerToParts.length);
var samePartsLength = length;
Expand Down Expand Up @@ -320,7 +339,7 @@ win32.dirname = function(path) {

if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
dir = dir.slice(0, -1);
}

return root + dir;
Expand Down Expand Up @@ -360,7 +379,7 @@ win32.format = function(pathObject) {

var dir = pathObject.dir;
var base = pathObject.base || '';
if (dir.slice(dir.length - 1, dir.length) === win32.sep) {
if (dir.slice(-1) === win32.sep) {
return dir + base;
}

Expand All @@ -384,7 +403,7 @@ win32.parse = function(pathString) {
}
return {
root: allParts[0],
dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1),
dir: allParts[0] + allParts[1].slice(0, -1),
base: allParts[2],
ext: allParts[3],
name: allParts[2].slice(0, allParts[2].length - allParts[3].length)
Expand Down Expand Up @@ -425,7 +444,7 @@ posix.resolve = function() {
}

resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
resolvedAbsolute = path[0] === '/';
}

// At this point the path should be resolved to a full absolute path, but
Expand All @@ -442,7 +461,7 @@ posix.resolve = function() {
// posix version
posix.normalize = function(path) {
var isAbsolute = posix.isAbsolute(path),
trailingSlash = path.substr(-1) === '/';
trailingSlash = path && path[path.length - 1] === '/';

// Normalize the path
path = normalizeArray(path.split('/'), !isAbsolute).join('/');
Expand Down Expand Up @@ -488,23 +507,8 @@ posix.relative = function(from, to) {
from = posix.resolve(from).substr(1);
to = posix.resolve(to).substr(1);

function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}

var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}

if (start > end) return [];
return arr.slice(start, end + 1);
}

var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var fromParts = trimArray(from.split('/'));
var toParts = trimArray(to.split('/'));

var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
Expand Down Expand Up @@ -543,7 +547,7 @@ posix.dirname = function(path) {

if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
dir = dir.slice(0, -1);
}

return root + dir;
Expand Down Expand Up @@ -603,7 +607,7 @@ posix.parse = function(pathString) {

return {
root: allParts[0],
dir: allParts[0] + allParts[1].slice(0, allParts[1].length - 1),
dir: allParts[0] + allParts[1].slice(0, -1),
base: allParts[2],
ext: allParts[3],
name: allParts[2].slice(0, allParts[2].length - allParts[3].length)
Expand Down

0 comments on commit 7abada1

Please sign in to comment.