Skip to content

Commit 906e561

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

File tree

4 files changed

+77
-12
lines changed

4 files changed

+77
-12
lines changed

lib/async.js

+40-11
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,51 @@ module.exports = function resolve(x, options, callback) {
3434

3535
opts.paths = opts.paths || [];
3636

37+
function isFileWithExtensions(file, cb, extensionIndex) {
38+
var newExtensionIndex = 0;
39+
var filename = file;
40+
if (typeof extensionIndex === 'number') {
41+
if (extensionIndex >= extensions.length) {
42+
return cb(null, false);
43+
}
44+
45+
newExtensionIndex = extensionIndex + 1;
46+
filename = file + extensions[extensionIndex];
47+
}
48+
49+
isFile(filename, function (err, filenameIsFile) {
50+
if (err) { return cb(err); }
51+
if (filenameIsFile) {
52+
return cb(null, filenameIsFile);
53+
}
54+
isFileWithExtensions(file, cb, newExtensionIndex);
55+
});
56+
}
57+
3758
if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
38-
var res = path.resolve(y, x);
59+
var res = path.normalize(path.join(y, x));
3960
if (x === '..' || x.slice(-1) === '/') res += '/';
4061
if (/\/$/.test(x) && res === y) {
4162
loadAsDirectory(res, opts.package, onfile);
42-
} else loadAsFile(res, opts.package, onfile);
43-
} else loadNodeModules(x, y, function (err, n, pkg) {
44-
if (err) cb(err);
45-
else if (n) cb(null, n, pkg);
46-
else if (core[x]) return cb(null, x);
47-
else {
48-
var moduleError = new Error("Cannot find module '" + x + "' from '" + y + "'");
49-
moduleError.code = 'MODULE_NOT_FOUND';
50-
cb(moduleError);
63+
} else {
64+
isFileWithExtensions(res, function (err, resIsFile) {
65+
if (err) { return onfile(err); }
66+
if (resIsFile) { return loadAsFile(res, opts.package, onfile); }
67+
return loadAsDirectory(res, opts.package, onfile);
68+
});
5169
}
52-
});
70+
} else {
71+
loadNodeModules(x, y, function (err, n, pkg) {
72+
if (err) cb(err);
73+
else if (n) cb(null, n, pkg);
74+
else if (core[x]) return cb(null, x);
75+
else {
76+
var moduleError = new Error("Cannot find module '" + x + "' from '" + y + "'");
77+
moduleError.code = 'MODULE_NOT_FOUND';
78+
cb(moduleError);
79+
}
80+
});
81+
}
5382

5483
function onfile(err, m, pkg) {
5584
if (err) cb(err);

lib/sync.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = function (x, options) {
2626
opts.paths = opts.paths || [];
2727

2828
if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
29-
var res = path.resolve(y, x);
29+
var res = path.normalize(path.join(y, x));
3030
if (x === '..' || x.slice(-1) === '/') res += '/';
3131
var m = loadAsFileSync(res) || loadAsDirectorySync(res);
3232
if (m) return m;

test/resolver.js

+17
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,23 @@ test('async: #121 - treating an existing file as a dir when no basedir', functio
306306
});
307307
});
308308

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

test/resolver_sync.js

+19
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,25 @@ test('sync: #121 - treating an existing file as a dir when no basedir', function
230230
st.end();
231231
});
232232

233+
t.test('with a trailing slash', function (st) {
234+
function run() { return resolve.sync('./' + testFile + '/'); }
235+
236+
st.throws(run, 'throws an error');
237+
238+
try {
239+
run();
240+
} catch (e) {
241+
st.equal(e.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
242+
st.equal(
243+
e.message,
244+
'Cannot find module \'./' + testFile + '/\' from \'' + __dirname + '\'',
245+
'can not find nonexistent module'
246+
);
247+
}
248+
249+
st.end();
250+
});
251+
233252
t.test('with a fake directory', function (st) {
234253
function run() { return resolve.sync('./' + testFile + '/blah'); }
235254

0 commit comments

Comments
 (0)