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: https://github.com/nodejs/node/issues/5963
Fixes: https://github.com/nodejs/node/issues/16389
PR-URL: https://github.com/nodejs/node/pull/16397
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Wyatt Preul <wpreul@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
This commit is contained in:
cjihrig 2016-04-25 12:19:28 -04:00
parent 4997894390
commit 9c6f6b0633
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
6 changed files with 111 additions and 7 deletions

View File

@ -598,14 +598,36 @@ filename scales linearly with the number of registered extensions.
In other words, adding extensions slows down the module loader and In other words, adding extensions slows down the module loader and
should be discouraged. should be discouraged.
#### require.resolve() #### require.resolve(request[, options])
<!-- YAML <!-- YAML
added: v0.3.0 added: v0.3.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/16397
description: The `paths` option is now supported.
--> -->
* `request` {string} The module path to resolve.
* `options` {Object}
* `paths` {Array} Paths to resolve module location from. If present, these
paths are used instead of the default resolution paths. Note that each of
these paths is used as a starting point for the module resolution algorithm,
meaning that the `node_modules` hierarchy is checked from this location.
* Returns: {string}
Use the internal `require()` machinery to look up the location of a module, Use the internal `require()` machinery to look up the location of a module,
but rather than loading the module, just return the resolved filename. but rather than loading the module, just return the resolved filename.
#### require.resolve.paths(request)
<!-- YAML
added: REPLACEME
-->
* `request` {string} The module path whose lookup paths are being retrieved.
* Returns: {Array}
Returns an array containing the paths searched during resolution of `request`.
## The `module` Object ## The `module` Object
<!-- YAML <!-- YAML
added: v0.1.16 added: v0.1.16

View File

@ -1899,7 +1899,7 @@ cases:
[`promise.catch()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch [`promise.catch()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
[`require()`]: globals.html#globals_require [`require()`]: globals.html#globals_require
[`require.main`]: modules.html#modules_accessing_the_main_module [`require.main`]: modules.html#modules_accessing_the_main_module
[`require.resolve()`]: modules.html#modules_require_resolve [`require.resolve()`]: modules.html#modules_require_resolve_request_options
[`setTimeout(fn, 0)`]: timers.html#timers_settimeout_callback_delay_args [`setTimeout(fn, 0)`]: timers.html#timers_settimeout_callback_delay_args
[Child Process]: child_process.html [Child Process]: child_process.html
[Cluster]: cluster.html [Cluster]: cluster.html

View File

@ -14,12 +14,18 @@ function makeRequireFunction(mod) {
} }
} }
function resolve(request) { function resolve(request, options) {
return Module._resolveFilename(request, mod); return Module._resolveFilename(request, mod, false, options);
} }
require.resolve = resolve; require.resolve = resolve;
function paths(request) {
return Module._resolveLookupPaths(request, mod, true);
}
resolve.paths = paths;
require.main = process.mainModule; require.main = process.mainModule;
// Enable support to add extra extension types. // Enable support to add extra extension types.

View File

@ -484,12 +484,32 @@ function tryModuleLoad(module, filename) {
} }
} }
Module._resolveFilename = function(request, parent, isMain) { Module._resolveFilename = function(request, parent, isMain, options) {
if (NativeModule.nonInternalExists(request)) { if (NativeModule.nonInternalExists(request)) {
return request; return request;
} }
var paths = Module._resolveLookupPaths(request, parent, true); var paths;
if (typeof options === 'object' && options !== null &&
Array.isArray(options.paths)) {
paths = [];
for (var i = 0; i < options.paths.length; i++) {
const path = options.paths[i];
const lookupPaths = Module._resolveLookupPaths(path, parent, true);
if (!paths.includes(path))
paths.push(path);
for (var j = 0; j < lookupPaths.length; j++) {
if (!paths.includes(lookupPaths[j]))
paths.push(lookupPaths[j]);
}
}
} else {
paths = Module._resolveLookupPaths(request, parent, true);
}
// look up the filename first, since that's the cache key. // look up the filename first, since that's the cache key.
var filename = Module._findPath(request, paths, isMain); var filename = Module._findPath(request, paths, isMain);

55
test/fixtures/require-resolve.js vendored Normal file
View File

@ -0,0 +1,55 @@
'use strict';
require('../common');
const assert = require('assert');
const path = require('path');
const nodeModules = path.join(__dirname, 'node_modules');
const nestedNodeModules = path.join(__dirname, 'node_modules', 'node_modules');
const nestedIndex = path.join(__dirname, 'nested-index');
// Test the default behavior.
assert.strictEqual(
require.resolve('bar'),
path.join(nodeModules, 'bar.js')
);
// Verify that existing paths are removed.
assert.throws(() => {
require.resolve('bar', { paths: [] })
}, /^Error: Cannot find module 'bar'$/);
// Verify that resolution path can be overwritten.
{
// three.js cannot be loaded from this file by default.
assert.throws(() => {
require.resolve('three')
}, /^Error: Cannot find module 'three'$/);
// However, it can be found if resolution contains the nested index directory.
assert.strictEqual(
require.resolve('three', { paths: [nestedIndex] }),
path.join(nestedIndex, 'three.js')
);
// Resolution from nested index directory also checks node_modules.
assert.strictEqual(
require.resolve('bar', { paths: [nestedIndex] }),
path.join(nodeModules, 'bar.js')
);
}
// Verify that the default paths can be used and modified.
{
const paths = require.resolve.paths('bar');
assert.strictEqual(paths[0], nodeModules);
assert.strictEqual(
require.resolve('bar', { paths }),
path.join(nodeModules, 'bar.js')
);
paths.unshift(nestedNodeModules);
assert.strictEqual(
require.resolve('bar', { paths }),
path.join(nestedNodeModules, 'bar.js')
);
}

View File

@ -35,4 +35,5 @@ assert.strictEqual(
require.resolve(fixtures.path('nested-index', 'one').toLowerCase())); require.resolve(fixtures.path('nested-index', 'one').toLowerCase()));
assert.strictEqual('path', require.resolve('path')); assert.strictEqual('path', require.resolve('path'));
console.log('ok'); // Test configurable resolve() paths.
require(fixtures.path('require-resolve.js'));