require.resolve('./', [options]) with paths option will resolve with root index.js file while it should error with MODULE_NOT_FOUND · Issue #23643 · nodejs/node (original) (raw)

Folder structure:

Test
├── OtherFolder
|   └── main.js
├── SubFolder
|   └── index.js
└── index.js

index.js

console.log(require.resolve.paths('./')) console.log(require.resolve('./'))

SubFolder/index.js

console.log(require.resolve.paths('./')) console.log(require.resolve('./')) console.log(require.resolve('./', { paths: ['/Users/niksajanjic/Projects/Test/OtherFolder'] }))

OtherFolder/main.js

console.log(require.resolve.paths('./')) console.log(require.resolve('./'))

If I run node index.js:

[ '/Users/niksajanjic/Projects/Test' ]
/Users/niksajanjic/Projects/Test/index.js

If I run node SubFolder/index.js (expected an error in the last line, not the resolvement):

[ '/Users/niksajanjic/Projects/Test/SubTest' ]
/Users/niksajanjic/Projects/Test/SubTest/index.js
/Users/niksajanjic/Projects/Test/index.js

If I run node OtherFolder/main.js:

[ '/Users/niksajanjic/Projects/Test/BugTest' ]
internal/modules/cjs/loader.js:582
    throw err;
    ^

Error: Cannot find module './'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:580:15)
    at Function.resolve (internal/modules/cjs/helpers.js:30:19)
    at Object.<anonymous> (/Users/niksajanjic/Projects/Test/BugTest/main.js:2:21)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:741:12)
    at startup (internal/bootstrap/node.js:285:19)

I feel the bug is the resolvement of this line console.log(require.resolve('./', { paths: ['/Users/niksajanjic/Projects/Test/OtherFolder'] })) inside SubFolder/index.js into /Users/niksajanjic/Projects/Test/index.js. That was unexpected for me and I expected it to error out same as running console.log(require.resolve('./')) inside OtherFolder/main.js errored out with MODULE_NOT_FOUND. I feel the result of those 2 calls should be exactly the same.

This means that if you have a file in the root folder (let's say main.js) and if you try to look for the file from A folder into B folder that has the same name as the one in root folder (require.resolve('./main.js', { paths: [ /path/to/folder/B ] })) it will never error out. Whether you have main.js inside B folder or not, the resolvement would still happen and return the path to the file in the root folder. This is very dangerous, this basically means you can't rely on making relative path resolvements inside other paths without the fear of them being resolved to files in the root directory with the same name, and that is a huge probability while using filenames like index.js, main.js, app.js or style.js.

While we're at this subject, could we benefit from an optional options argument inside require.resolve.paths(request, options) so we can see which paths does it resolve to?

If this is a bug and not an indended behavior, I could dig it up a bit and debug, maybe even come out with some PR. I know the problem is somewhere inside Module._resolveFilename function inside internal/modules/cjs/loader file.