Skip to content

Commit 5e2dab7

Browse files
dario-piotrowiczmarco-ippolito
authored andcommitted
module: fix bad require.resolve with option paths for . and ..
this change fixes `require.resolve` used with the `paths` option not considering `.` and `..` as relative Fixes: #47000 PR-URL: #56735 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jordan Harband <ljharb@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 5b88d48 commit 5e2dab7

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

lib/internal/modules/cjs/loader.js

+17-17
Original file line numberDiff line numberDiff line change
@@ -693,18 +693,8 @@ Module._findPath = function(request, paths, isMain) {
693693
)
694694
));
695695

696-
const isRelative = StringPrototypeCharCodeAt(request, 0) === CHAR_DOT &&
697-
(
698-
request.length === 1 ||
699-
StringPrototypeCharCodeAt(request, 1) === CHAR_FORWARD_SLASH ||
700-
(isWindows && StringPrototypeCharCodeAt(request, 1) === CHAR_BACKWARD_SLASH) ||
701-
(StringPrototypeCharCodeAt(request, 1) === CHAR_DOT && ((
702-
request.length === 2 ||
703-
StringPrototypeCharCodeAt(request, 2) === CHAR_FORWARD_SLASH) ||
704-
(isWindows && StringPrototypeCharCodeAt(request, 2) === CHAR_BACKWARD_SLASH)))
705-
);
706696
let insidePath = true;
707-
if (isRelative) {
697+
if (isRelative(request)) {
708698
const normalizedRequest = path.normalize(request);
709699
if (StringPrototypeStartsWith(normalizedRequest, '..')) {
710700
insidePath = false;
@@ -1147,12 +1137,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
11471137

11481138
if (typeof options === 'object' && options !== null) {
11491139
if (ArrayIsArray(options.paths)) {
1150-
const isRelative = StringPrototypeStartsWith(request, './') ||
1151-
StringPrototypeStartsWith(request, '../') ||
1152-
((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
1153-
StringPrototypeStartsWith(request, '..\\'));
1154-
1155-
if (isRelative) {
1140+
if (isRelative(request)) {
11561141
paths = options.paths;
11571142
} else {
11581143
const fakeParent = new Module('', null);
@@ -1715,6 +1700,21 @@ function createRequire(filename) {
17151700
return createRequireFromPath(filepath);
17161701
}
17171702

1703+
/**
1704+
* Checks if a path is relative
1705+
* @param {string} path the target path
1706+
* @returns {boolean} true if the path is relative, false otherwise
1707+
*/
1708+
function isRelative(path) {
1709+
if (StringPrototypeCharCodeAt(path, 0) !== CHAR_DOT) { return false; }
1710+
1711+
return path.length === 1 || path === '..' ||
1712+
StringPrototypeStartsWith(path, './') ||
1713+
StringPrototypeStartsWith(path, '../') ||
1714+
((isWindows && StringPrototypeStartsWith(path, '.\\')) ||
1715+
StringPrototypeStartsWith(path, '..\\'));
1716+
}
1717+
17181718
Module.createRequire = createRequire;
17191719

17201720
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports.value = 'relative subdir';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const fixtures = require('../common/fixtures');
6+
7+
if (!common.isMainThread)
8+
common.skip('process.chdir is not available in Workers');
9+
10+
const subdir = fixtures.path('module-require', 'relative', 'subdir');
11+
12+
process.chdir(subdir);
13+
14+
// Parent directory paths (`..`) work as intended
15+
{
16+
assert(require.resolve('.', { paths: ['../'] }).endsWith('index.js'));
17+
assert(require.resolve('./index.js', { paths: ['../'] }).endsWith('index.js'));
18+
19+
// paths: [".."] should resolve like paths: ["../"]
20+
assert(require.resolve('.', { paths: ['..'] }).endsWith('index.js'));
21+
assert(require.resolve('./index.js', { paths: ['..'] }).endsWith('index.js'));
22+
}
23+
24+
process.chdir('..');
25+
26+
// Current directory paths (`.`) work as intended
27+
{
28+
assert(require.resolve('.', { paths: ['.'] }).endsWith('index.js'));
29+
assert(require.resolve('./index.js', { paths: ['./'] }).endsWith('index.js'));
30+
31+
// paths: ["."] should resolve like paths: ["../"]
32+
assert(require.resolve('.', { paths: ['.'] }).endsWith('index.js'));
33+
assert(require.resolve('./index.js', { paths: ['.'] }).endsWith('index.js'));
34+
}
35+
36+
// Sub directory paths work as intended
37+
{
38+
// assert.deepStrictEqual(fs.readdirSync('./subdir'), [5]);
39+
assert(require.resolve('./relative-subdir.js', { paths: ['./subdir'] }).endsWith('relative-subdir.js'));
40+
41+
// paths: ["subdir"] should resolve like paths: ["./subdir"]
42+
assert(require.resolve('./relative-subdir.js', { paths: ['subdir'] }).endsWith('relative-subdir.js'));
43+
}

0 commit comments

Comments
 (0)