Skip to content

Commit 7119303

Browse files
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 <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jordan Harband <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 59b3a8b commit 7119303

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
@@ -722,18 +722,8 @@ Module._findPath = function(request, paths, isMain, conditions = getCjsCondition
722722
)
723723
));
724724

725-
const isRelative = StringPrototypeCharCodeAt(request, 0) === CHAR_DOT &&
726-
(
727-
request.length === 1 ||
728-
StringPrototypeCharCodeAt(request, 1) === CHAR_FORWARD_SLASH ||
729-
(isWindows && StringPrototypeCharCodeAt(request, 1) === CHAR_BACKWARD_SLASH) ||
730-
(StringPrototypeCharCodeAt(request, 1) === CHAR_DOT && ((
731-
request.length === 2 ||
732-
StringPrototypeCharCodeAt(request, 2) === CHAR_FORWARD_SLASH) ||
733-
(isWindows && StringPrototypeCharCodeAt(request, 2) === CHAR_BACKWARD_SLASH)))
734-
);
735725
let insidePath = true;
736-
if (isRelative) {
726+
if (isRelative(request)) {
737727
const normalizedRequest = path.normalize(request);
738728
if (StringPrototypeStartsWith(normalizedRequest, '..')) {
739729
insidePath = false;
@@ -1328,12 +1318,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
13281318

13291319
if (typeof options === 'object' && options !== null) {
13301320
if (ArrayIsArray(options.paths)) {
1331-
const isRelative = StringPrototypeStartsWith(request, './') ||
1332-
StringPrototypeStartsWith(request, '../') ||
1333-
((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
1334-
StringPrototypeStartsWith(request, '..\\'));
1335-
1336-
if (isRelative) {
1321+
if (isRelative(request)) {
13371322
paths = options.paths;
13381323
} else {
13391324
const fakeParent = new Module('', null);
@@ -1978,6 +1963,21 @@ function createRequire(filename) {
19781963
return createRequireFromPath(filepath);
19791964
}
19801965

1966+
/**
1967+
* Checks if a path is relative
1968+
* @param {string} path the target path
1969+
* @returns {boolean} true if the path is relative, false otherwise
1970+
*/
1971+
function isRelative(path) {
1972+
if (StringPrototypeCharCodeAt(path, 0) !== CHAR_DOT) { return false; }
1973+
1974+
return path.length === 1 || path === '..' ||
1975+
StringPrototypeStartsWith(path, './') ||
1976+
StringPrototypeStartsWith(path, '../') ||
1977+
((isWindows && StringPrototypeStartsWith(path, '.\\')) ||
1978+
StringPrototypeStartsWith(path, '..\\'));
1979+
}
1980+
19811981
Module.createRequire = createRequire;
19821982

19831983
/**
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)