Skip to content

Commit

Permalink
module: add createRequire method
Browse files Browse the repository at this point in the history
This is an abstraction on top of creatRequireFromPath that can accept
both paths, URL Strings, and URL Objects.

PR-URL: #27405
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jan Krems <jan.krems@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
MylesBorins authored and targos committed May 4, 2019
1 parent 2c3c0d7 commit 5bcd770
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 4 deletions.
14 changes: 14 additions & 0 deletions doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,19 @@ The `_channel` property of child process objects returned by `spawn()` and
similar functions is not intended for public use. Use `ChildProcess.channel`
instead.
<a id="DEP0130"></a>
### DEP00XX: Module.createRequireFromPath()
<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/27405
description: Documentation-only.
-->
Type: Documentation-only
Module.createRequireFromPath() is deprecated. Please use [`module.createRequire()`][] instead.
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
[`Buffer.from(array)`]: buffer.html#buffer_class_method_buffer_from_array
Expand Down Expand Up @@ -2486,6 +2499,7 @@ instead.
[`http.request()`]: http.html#http_http_request_options_callback
[`https.get()`]: https.html#https_https_get_options_callback
[`https.request()`]: https.html#https_https_request_options_callback
[`module.createRequire()`]: modules.html#modules_module_createrequire_filename
[`os.networkInterfaces()`]: os.html#os_os_networkinterfaces
[`os.tmpdir()`]: os.html#os_os_tmpdir
[`process.env`]: process.html#process_process_env
Expand Down
22 changes: 22 additions & 0 deletions doc/api/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -905,15 +905,36 @@ by the [module wrapper][]. To access it, require the `Module` module:
const builtin = require('module').builtinModules;
```

### module.createRequire(filename)
<!-- YAML
added: REPLACEME
-->

* `filename` {string|URL} Filename to be used to construct the require
function. Must be a file URL object, file URL string, or absolute path
string.
* Returns: {require} Require function

```js
const { createRequire } = require('module');
const requireUtil = createRequire(require.resolve('../src/utils/'));

// Require `../src/utils/some-tool`
requireUtil('./some-tool');
```

### module.createRequireFromPath(filename)
<!-- YAML
added: v10.12.0
deprecated: REPLACEME
-->

* `filename` {string} Filename to be used to construct the relative require
function.
* Returns: {require} Require function

> Stability: 0 - Deprecated: Please use [`createRequire()`][] instead.
```js
const { createRequireFromPath } = require('module');
const requireUtil = createRequireFromPath('../src/utils/');
Expand All @@ -926,6 +947,7 @@ requireUtil('./some-tool');
[`Error`]: errors.html#errors_class_error
[`__dirname`]: #modules_dirname
[`__filename`]: #modules_filename
[`createRequire()`]: #modules_module_createrequire_filename
[`module` object]: #modules_the_module_object
[`path.dirname()`]: path.html#path_path_dirname_path
[exports shortcut]: #modules_exports_shortcut
Expand Down
33 changes: 30 additions & 3 deletions lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
const { JSON, Object, Reflect } = primordials;

const { NativeModule } = require('internal/bootstrap/loaders');
const { pathToFileURL } = require('internal/url');
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
const { deprecate } = require('internal/util');
const vm = require('vm');
const assert = require('internal/assert');
Expand Down Expand Up @@ -824,7 +824,7 @@ Module.runMain = function() {
Module._load(process.argv[1], null, true);
};

Module.createRequireFromPath = (filename) => {
function createRequireFromPath(filename) {
// Allow a directory to be passed as the filename
const trailingSlash =
filename.endsWith(path.sep) || path.sep !== '/' && filename.endsWith('\\');
Expand All @@ -838,7 +838,34 @@ Module.createRequireFromPath = (filename) => {

m.paths = Module._nodeModulePaths(m.path);
return makeRequireFunction(m);
};
}

Module.createRequireFromPath = createRequireFromPath;

const createRequireError = 'must be a file URL object, file URL string, or' +
'absolute path string';

function createRequire(filename) {
let filepath;
if (typeof filename === 'object' && !(filename instanceof URL)) {
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
} else if (typeof filename === 'object' ||
typeof filename === 'string' && !path.isAbsolute(filename)) {
try {
filepath = fileURLToPath(filename);
} catch {
throw new ERR_INVALID_ARG_VALUE('filename', filename,
createRequireError);
}
} else if (typeof filename !== 'string') {
throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
} else {
filepath = filename;
}
return createRequireFromPath(filepath);
}

Module.createRequire = createRequire;

Module._initPaths = function() {
var homeDir;
Expand Down
24 changes: 23 additions & 1 deletion test/parallel/test-module-create-require.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,31 @@ require('../common');
const assert = require('assert');
const path = require('path');

const { createRequireFromPath } = require('module');
const { createRequire, createRequireFromPath } = require('module');

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

const req = createRequireFromPath(p);
assert.strictEqual(req('./baz'), 'perhaps I work');

const reqToo = createRequire(u);
assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 });

assert.throws(() => {
createRequire('https://github.com/nodejs/node/pull/27405/');
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

assert.throws(() => {
createRequire('../');
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

assert.throws(() => {
createRequire({});
}, {
code: 'ERR_INVALID_ARG_VALUE'
});

0 comments on commit 5bcd770

Please sign in to comment.