Skip to content

Commit a4539ba

Browse files
committed
[Breaking] bring resolve into line with require.resolve, which does not respect trailing slashes on non-directories.
1 parent cfd0bb8 commit a4539ba

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

lib/async.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,17 @@ module.exports = function resolve(x, options, callback) {
6161
var res;
6262
function validBasedir() {
6363
if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
64-
res = path.resolve(basedir, x);
64+
res = path.normalize(path.join(basedir, x));
6565
if (x === '..' || x.slice(-1) === '/') res += '/';
6666
if (/\/$/.test(x) && res === basedir) {
6767
loadAsDirectory(res, opts.package, onfile);
68-
} else loadAsFile(res, opts.package, onfile);
68+
} else {
69+
isFileWithExtensions(res, function (err, resIsFile) {
70+
if (err) { return onfile(err); }
71+
if (resIsFile) { return loadAsFile(res, opts.package, onfile); }
72+
return loadAsDirectory(res, opts.package, onfile);
73+
});
74+
}
6975
} else loadNodeModules(x, basedir, function (err, n, pkg) {
7076
if (err) cb(err);
7177
else if (core[x]) return cb(null, x);
@@ -78,6 +84,27 @@ module.exports = function resolve(x, options, callback) {
7884
});
7985
}
8086

87+
function isFileWithExtensions(file, cb, extensionIndex) {
88+
var newExtensionIndex = 0;
89+
var filename = file;
90+
if (typeof extensionIndex === 'number') {
91+
if (extensionIndex >= extensions.length) {
92+
return cb(null, false);
93+
}
94+
95+
newExtensionIndex = extensionIndex + 1;
96+
filename = file + extensions[extensionIndex];
97+
}
98+
99+
isFile(filename, function (err, filenameIsFile) {
100+
if (err) { return cb(err); }
101+
if (filenameIsFile) {
102+
return cb(null, filenameIsFile);
103+
}
104+
isFileWithExtensions(file, cb, newExtensionIndex);
105+
});
106+
}
107+
81108
function onfile(err, m, pkg) {
82109
if (err) cb(err);
83110
else if (m) cb(null, m, pkg);

lib/sync.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module.exports = function (x, options) {
4444
}
4545

4646
if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
47-
var res = path.resolve(basedir, x);
47+
var res = path.normalize(path.join(basedir, x));
4848
if (x === '..' || x.slice(-1) === '/') res += '/';
4949
var m = loadAsFileSync(res) || loadAsDirectorySync(res);
5050
if (m) return m;

test/resolver.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,23 @@ test('async: #121 - treating an existing file as a dir when no basedir', functio
310310
});
311311
});
312312

313+
t.test('with a trailing slash', function (st) {
314+
st.plan(4);
315+
316+
resolve('./' + testFile + '/', function (err, res, pkg) {
317+
st.ok(err, 'there is an error');
318+
st.notOk(res, 'no result');
319+
320+
st.equal(err && err.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
321+
st.equal(
322+
err && err.message,
323+
'Cannot find module \'./' + testFile + '/\' from \'' + __dirname + '\'',
324+
'can not find nonexistent module'
325+
);
326+
st.end();
327+
});
328+
});
329+
313330
t.test('with a fake directory', function (st) {
314331
st.plan(4);
315332

test/resolver_sync.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,25 @@ test('sync: #121 - treating an existing file as a dir when no basedir', function
235235
st.end();
236236
});
237237

238+
t.test('with a trailing slash', function (st) {
239+
function run() { return resolve.sync('./' + testFile + '/'); }
240+
241+
st.throws(run, 'throws an error');
242+
243+
try {
244+
run();
245+
} catch (e) {
246+
st.equal(e.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
247+
st.equal(
248+
e.message,
249+
'Cannot find module \'./' + testFile + '/\' from \'' + __dirname + '\'',
250+
'can not find nonexistent module'
251+
);
252+
}
253+
254+
st.end();
255+
});
256+
238257
t.test('with a fake directory', function (st) {
239258
function run() { return resolve.sync('./' + testFile + '/blah'); }
240259

0 commit comments

Comments
 (0)