Skip to content
This repository was archived by the owner on Aug 31, 2018. It is now read-only.

Commit db2a5fe

Browse files
cjihrigaddaleax
authored andcommitted
module: support custom paths to require.resolve()
This commit allows custom lookup paths to be passed to require.resolve(). It also adds require.resolve.paths() which retrieves the default resolution paths. Fixes: nodejs/node#5963 Fixes: nodejs/node#16389 PR-URL: nodejs/node#16397 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Wyatt Preul <wpreul@gmail.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
1 parent 59dfac2 commit db2a5fe

File tree

6 files changed

+111
-7
lines changed

6 files changed

+111
-7
lines changed

doc/api/modules.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -598,14 +598,36 @@ filename scales linearly with the number of registered extensions.
598598
In other words, adding extensions slows down the module loader and
599599
should be discouraged.
600600

601-
#### require.resolve()
601+
#### require.resolve(request[, options])
602602
<!-- YAML
603603
added: v0.3.0
604+
changes:
605+
- version: REPLACEME
606+
pr-url: https://github.com/nodejs/node/pull/16397
607+
description: The `paths` option is now supported.
604608
-->
605609

610+
* `request` {string} The module path to resolve.
611+
* `options` {Object}
612+
* `paths` {Array} Paths to resolve module location from. If present, these
613+
paths are used instead of the default resolution paths. Note that each of
614+
these paths is used as a starting point for the module resolution algorithm,
615+
meaning that the `node_modules` hierarchy is checked from this location.
616+
* Returns: {string}
617+
606618
Use the internal `require()` machinery to look up the location of a module,
607619
but rather than loading the module, just return the resolved filename.
608620

621+
#### require.resolve.paths(request)
622+
<!-- YAML
623+
added: REPLACEME
624+
-->
625+
626+
* `request` {string} The module path whose lookup paths are being retrieved.
627+
* Returns: {Array}
628+
629+
Returns an array containing the paths searched during resolution of `request`.
630+
609631
## The `module` Object
610632
<!-- YAML
611633
added: v0.1.16

doc/api/process.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ cases:
18991899
[`promise.catch()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
19001900
[`require()`]: globals.html#globals_require
19011901
[`require.main`]: modules.html#modules_accessing_the_main_module
1902-
[`require.resolve()`]: modules.html#modules_require_resolve
1902+
[`require.resolve()`]: modules.html#modules_require_resolve_request_options
19031903
[`setTimeout(fn, 0)`]: timers.html#timers_settimeout_callback_delay_args
19041904
[Child Process]: child_process.html
19051905
[Cluster]: cluster.html

lib/internal/module.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ function makeRequireFunction(mod) {
1414
}
1515
}
1616

17-
function resolve(request) {
18-
return Module._resolveFilename(request, mod);
17+
function resolve(request, options) {
18+
return Module._resolveFilename(request, mod, false, options);
1919
}
2020

2121
require.resolve = resolve;
2222

23+
function paths(request) {
24+
return Module._resolveLookupPaths(request, mod, true);
25+
}
26+
27+
resolve.paths = paths;
28+
2329
require.main = process.mainModule;
2430

2531
// Enable support to add extra extension types.

lib/module.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,32 @@ function tryModuleLoad(module, filename) {
484484
}
485485
}
486486

487-
Module._resolveFilename = function(request, parent, isMain) {
487+
Module._resolveFilename = function(request, parent, isMain, options) {
488488
if (NativeModule.nonInternalExists(request)) {
489489
return request;
490490
}
491491

492-
var paths = Module._resolveLookupPaths(request, parent, true);
492+
var paths;
493+
494+
if (typeof options === 'object' && options !== null &&
495+
Array.isArray(options.paths)) {
496+
paths = [];
497+
498+
for (var i = 0; i < options.paths.length; i++) {
499+
const path = options.paths[i];
500+
const lookupPaths = Module._resolveLookupPaths(path, parent, true);
501+
502+
if (!paths.includes(path))
503+
paths.push(path);
504+
505+
for (var j = 0; j < lookupPaths.length; j++) {
506+
if (!paths.includes(lookupPaths[j]))
507+
paths.push(lookupPaths[j]);
508+
}
509+
}
510+
} else {
511+
paths = Module._resolveLookupPaths(request, parent, true);
512+
}
493513

494514
// look up the filename first, since that's the cache key.
495515
var filename = Module._findPath(request, paths, isMain);

test/fixtures/require-resolve.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const path = require('path');
5+
const nodeModules = path.join(__dirname, 'node_modules');
6+
const nestedNodeModules = path.join(__dirname, 'node_modules', 'node_modules');
7+
const nestedIndex = path.join(__dirname, 'nested-index');
8+
9+
// Test the default behavior.
10+
assert.strictEqual(
11+
require.resolve('bar'),
12+
path.join(nodeModules, 'bar.js')
13+
);
14+
15+
// Verify that existing paths are removed.
16+
assert.throws(() => {
17+
require.resolve('bar', { paths: [] })
18+
}, /^Error: Cannot find module 'bar'$/);
19+
20+
// Verify that resolution path can be overwritten.
21+
{
22+
// three.js cannot be loaded from this file by default.
23+
assert.throws(() => {
24+
require.resolve('three')
25+
}, /^Error: Cannot find module 'three'$/);
26+
27+
// However, it can be found if resolution contains the nested index directory.
28+
assert.strictEqual(
29+
require.resolve('three', { paths: [nestedIndex] }),
30+
path.join(nestedIndex, 'three.js')
31+
);
32+
33+
// Resolution from nested index directory also checks node_modules.
34+
assert.strictEqual(
35+
require.resolve('bar', { paths: [nestedIndex] }),
36+
path.join(nodeModules, 'bar.js')
37+
);
38+
}
39+
40+
// Verify that the default paths can be used and modified.
41+
{
42+
const paths = require.resolve.paths('bar');
43+
44+
assert.strictEqual(paths[0], nodeModules);
45+
assert.strictEqual(
46+
require.resolve('bar', { paths }),
47+
path.join(nodeModules, 'bar.js')
48+
);
49+
50+
paths.unshift(nestedNodeModules);
51+
assert.strictEqual(
52+
require.resolve('bar', { paths }),
53+
path.join(nestedNodeModules, 'bar.js')
54+
);
55+
}

test/parallel/test-require-resolve.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ assert.strictEqual(
3535
require.resolve(fixtures.path('nested-index', 'one').toLowerCase()));
3636
assert.strictEqual('path', require.resolve('path'));
3737

38-
console.log('ok');
38+
// Test configurable resolve() paths.
39+
require(fixtures.path('require-resolve.js'));

0 commit comments

Comments
 (0)