Skip to content

Commit 90529ec

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

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

lib/async.js

+41-12
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 === '..') res += '/';
40-
if (/\/$/.test(x) && res === y) {
61+
if (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 === '..') 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
@@ -290,6 +290,23 @@ test('async: #121 - treating an existing file as a dir when no basedir', functio
290290
});
291291
});
292292

293+
t.test('with a trailing slash', function (st) {
294+
st.plan(4);
295+
296+
resolve('./' + testFile + '/', function (err, res, pkg) {
297+
st.ok(err, 'there is an error');
298+
st.notOk(res, 'no result');
299+
300+
st.equal(err && err.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
301+
st.equal(
302+
err && err.message,
303+
'Cannot find module \'./' + testFile + '/\' from \'' + __dirname + '\'',
304+
'can not find nonexistent module'
305+
);
306+
st.end();
307+
});
308+
});
309+
293310
t.test('with a fake directory', function (st) {
294311
st.plan(4);
295312

test/resolver_sync.js

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

219+
t.test('with a trailing slash', function (st) {
220+
function run() { return resolve.sync('./' + testFile + '/'); }
221+
222+
st.throws(run, 'throws an error');
223+
224+
try {
225+
run();
226+
} catch (e) {
227+
st.equal(e.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
228+
st.equal(
229+
e.message,
230+
'Cannot find module \'./' + testFile + '/\' from \'' + __dirname + '\'',
231+
'can not find nonexistent module'
232+
);
233+
}
234+
235+
st.end();
236+
});
237+
219238
t.test('with a fake directory', function (st) {
220239
function run() { return resolve.sync('./' + testFile + '/blah'); }
221240

0 commit comments

Comments
 (0)