diff --git a/doc/api/modules.md b/doc/api/modules.md index d52d4ddac5f32e..8638b137ade732 100644 --- a/doc/api/modules.md +++ b/doc/api/modules.md @@ -916,7 +916,7 @@ added: v10.12.0 ```js const { createRequireFromPath } = require('module'); -const requireUtil = createRequireFromPath('../src/utils'); +const requireUtil = createRequireFromPath('../src/utils/'); // Require `../src/utils/some-tool` requireUtil('./some-tool'); diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 96b5e8b7b881b6..5df34cb3f022b4 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -825,9 +825,18 @@ Module.runMain = function() { }; Module.createRequireFromPath = (filename) => { - const m = new Module(filename); - m.filename = filename; - m.paths = Module._nodeModulePaths(path.dirname(filename)); + // Allow a directory to be passed as the filename + const trailingSlash = + filename.endsWith(path.sep) || path.sep !== '/' && filename.endsWith('\\'); + + const proxyPath = trailingSlash ? + path.join(filename, 'noop.js') : + filename; + + const m = new Module(proxyPath); + m.filename = proxyPath; + + m.paths = Module._nodeModulePaths(m.path); return makeRequireFunction(m); }; diff --git a/test/parallel/test-module-create-require-from-directory.js b/test/parallel/test-module-create-require-from-directory.js new file mode 100644 index 00000000000000..f043adacf994d8 --- /dev/null +++ b/test/parallel/test-module-create-require-from-directory.js @@ -0,0 +1,18 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const path = require('path'); + +const { createRequireFromPath } = require('module'); + +const fixPath = path.resolve(__dirname, '..', 'fixtures'); +const p = path.join(fixPath, path.sep); + +const req = createRequireFromPath(p); +const reqFromNotDir = createRequireFromPath(fixPath); + +assert.strictEqual(req('./baz'), 'perhaps I work'); +assert.throws(() => { + reqFromNotDir('./baz'); +}, { code: 'MODULE_NOT_FOUND' });