Skip to content

Commit 8beaac3

Browse files
MylesBorinsaduh95
authored andcommitted
module: add createRequire method
This is an abstraction on top of creatRequireFromPath that can accept both paths, URL Strings, and URL Objects. PR-URL: nodejs/node#27405 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jan Krems <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent f38bcc2 commit 8beaac3

File tree

5 files changed

+86
-8
lines changed

5 files changed

+86
-8
lines changed

doc/api/deprecations.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,6 @@ Type: Documentation-only
21072107
[`fs.read()`]: fs.html#fs_fs_read_fd_buffer_offset_length_position_callback
21082108
[`fs.readSync()`]: fs.html#fs_fs_readsync_fd_buffer_offset_length_position
21092109
[`fs.stat()`]: fs.html#fs_fs_stat_path_options_callback
2110-
[`os.networkInterfaces`]: os.html#os_os_networkinterfaces
21112110
[`os.tmpdir()`]: os.html#os_os_tmpdir
21122111
[`process.env`]: process.html#process_process_env
21132112
[`punycode`]: punycode.html

doc/api/modules.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,26 @@ by the [module wrapper][]. To access it, require the `Module` module:
905905
const builtin = require('module').builtinModules;
906906
```
907907

908+
### module.createRequire(filename)
909+
<!-- YAML
910+
added:
911+
- REPLACEME
912+
- v12.2.0
913+
-->
914+
915+
* `filename` {string|URL} Filename to be used to construct the require
916+
function. Must be a file URL object, file URL string, or absolute path
917+
string.
918+
* Returns: {[`require`][]} Require function
919+
920+
```js
921+
const { createRequire } = require('module');
922+
const requireUtil = createRequire(require.resolve('../src/utils/'));
923+
924+
// Require `../src/utils/some-tool`
925+
requireUtil('./some-tool');
926+
```
927+
908928
### module.createRequireFromPath(filename)
909929
<!-- YAML
910930
added: v10.12.0

lib/internal/modules/cjs/loader.js

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
const { NativeModule } = require('internal/bootstrap/loaders');
2525
const util = require('util');
26-
const { pathToFileURL } = require('internal/url');
26+
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
2727
const vm = require('vm');
2828
const assert = require('assert').ok;
2929
const fs = require('fs');
@@ -834,12 +834,48 @@ Module.runMain = function() {
834834
process._tickCallback();
835835
};
836836

837-
Module.createRequireFromPath = (filename) => {
838-
const m = new Module(filename);
839-
m.filename = filename;
840-
m.paths = Module._nodeModulePaths(path.dirname(filename));
837+
function createRequireFromPath(filename) {
838+
// Allow a directory to be passed as the filename
839+
const trailingSlash =
840+
filename.endsWith(path.sep) || path.sep !== '/' && filename.endsWith('\\');
841+
842+
const proxyPath = trailingSlash ?
843+
path.join(filename, 'noop.js') :
844+
filename;
845+
846+
const m = new Module(proxyPath);
847+
m.filename = proxyPath;
848+
849+
m.paths = Module._nodeModulePaths(path.dirname(proxyPath));
841850
return makeRequireFunction(m);
842-
};
851+
}
852+
853+
Module.createRequireFromPath = createRequireFromPath;
854+
855+
const createRequireError = 'must be a file URL object, file URL string, or' +
856+
'absolute path string';
857+
858+
function createRequire(filename) {
859+
let filepath;
860+
if (typeof filename === 'object' && !(filename instanceof URL)) {
861+
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
862+
} else if (typeof filename === 'object' ||
863+
typeof filename === 'string' && !path.isAbsolute(filename)) {
864+
try {
865+
filepath = fileURLToPath(filename);
866+
} catch {
867+
throw new ERR_INVALID_ARG_VALUE('filename', filename,
868+
createRequireError);
869+
}
870+
} else if (typeof filename !== 'string') {
871+
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
872+
} else {
873+
filepath = filename;
874+
}
875+
return createRequireFromPath(filepath);
876+
}
877+
878+
Module.createRequire = createRequire;
843879

844880
Module._initPaths = function() {
845881
const isWindows = process.platform === 'win32';

test/fixtures/experimental

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports.ofLife=42

test/parallel/test-module-create-require.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,31 @@ require('../common');
44
const assert = require('assert');
55
const path = require('path');
66

7-
const { createRequireFromPath } = require('module');
7+
const { createRequire, createRequireFromPath } = require('module');
88

99
const p = path.resolve(__dirname, '..', 'fixtures', 'fake.js');
10+
const u = new URL(`file://${p}`);
1011

1112
const req = createRequireFromPath(p);
1213
assert.strictEqual(req('./baz'), 'perhaps I work');
14+
15+
const reqToo = createRequire(u);
16+
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });
17+
18+
assert.throws(() => {
19+
createRequire('https://github.com/nodejs/node/pull/27405/');
20+
}, {
21+
code: 'ERR_INVALID_ARG_VALUE'
22+
});
23+
24+
assert.throws(() => {
25+
createRequire('../');
26+
}, {
27+
code: 'ERR_INVALID_ARG_VALUE'
28+
});
29+
30+
assert.throws(() => {
31+
createRequire({});
32+
}, {
33+
code: 'ERR_INVALID_ARG_VALUE'
34+
});

0 commit comments

Comments
 (0)