Skip to content

Commit b1fb413

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

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
@@ -36,22 +36,51 @@ module.exports = function resolve(x, options, callback) {
3636

3737
opts.paths = opts.paths || [];
3838

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

5685
function onfile(err, m, pkg) {
5786
if (err) cb(err);

lib/sync.js

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

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

test/resolver.js

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

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

test/resolver_sync.js

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

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

0 commit comments

Comments
 (0)