summaryrefslogtreecommitdiff
path: root/lib/internal/modules/cjs/loader.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/internal/modules/cjs/loader.js')
-rw-r--r--lib/internal/modules/cjs/loader.js785
1 files changed, 785 insertions, 0 deletions
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
new file mode 100644
index 0000000000..a172266661
--- /dev/null
+++ b/lib/internal/modules/cjs/loader.js
@@ -0,0 +1,785 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+'use strict';
+
+const { NativeModule } = require('internal/bootstrap/loaders');
+const util = require('util');
+const { decorateErrorStack } = require('internal/util');
+const { getURLFromFilePath } = require('internal/url');
+const vm = require('vm');
+const assert = require('assert').ok;
+const fs = require('fs');
+const internalFS = require('internal/fs');
+const path = require('path');
+const {
+ internalModuleReadJSON,
+ internalModuleStat
+} = process.binding('fs');
+const { safeGetenv } = process.binding('util');
+const {
+ makeRequireFunction,
+ requireDepth,
+ stripBOM,
+ stripShebang
+} = require('internal/modules/cjs/helpers');
+const preserveSymlinks = !!process.binding('config').preserveSymlinks;
+const experimentalModules = !!process.binding('config').experimentalModules;
+
+const {
+ ERR_INVALID_ARG_TYPE,
+ ERR_INVALID_ARG_VALUE,
+ ERR_REQUIRE_ESM
+} = require('internal/errors').codes;
+
+module.exports = Module;
+
+// these are below module.exports for the circular reference
+const asyncESM = require('internal/process/esm_loader');
+const ModuleJob = require('internal/modules/esm/ModuleJob');
+const createDynamicModule = require('internal/modules/esm/CreateDynamicModule');
+const {
+ CHAR_UPPERCASE_A,
+ CHAR_LOWERCASE_A,
+ CHAR_UPPERCASE_Z,
+ CHAR_LOWERCASE_Z,
+ CHAR_FORWARD_SLASH,
+ CHAR_BACKWARD_SLASH,
+ CHAR_COLON,
+ CHAR_DOT,
+ CHAR_UNDERSCORE,
+ CHAR_0,
+ CHAR_9,
+} = require('internal/constants');
+
+function stat(filename) {
+ filename = path.toNamespacedPath(filename);
+ const cache = stat.cache;
+ if (cache !== null) {
+ const result = cache.get(filename);
+ if (result !== undefined) return result;
+ }
+ const result = internalModuleStat(filename);
+ if (cache !== null) cache.set(filename, result);
+ return result;
+}
+stat.cache = null;
+
+function updateChildren(parent, child, scan) {
+ var children = parent && parent.children;
+ if (children && !(scan && children.includes(child)))
+ children.push(child);
+}
+
+function Module(id, parent) {
+ this.id = id;
+ this.exports = {};
+ this.parent = parent;
+ updateChildren(parent, this, false);
+ this.filename = null;
+ this.loaded = false;
+ this.children = [];
+}
+
+const builtinModules = Object.keys(NativeModule._source)
+ .filter(NativeModule.nonInternalExists);
+
+Object.freeze(builtinModules);
+Module.builtinModules = builtinModules;
+
+Module._cache = Object.create(null);
+Module._pathCache = Object.create(null);
+Module._extensions = Object.create(null);
+var modulePaths = [];
+Module.globalPaths = [];
+
+Module.wrap = function(script) {
+ return Module.wrapper[0] + script + Module.wrapper[1];
+};
+
+Module.wrapper = [
+ '(function (exports, require, module, __filename, __dirname) { ',
+ '\n});'
+];
+
+const debug = util.debuglog('module');
+
+Module._debug = util.deprecate(debug, 'Module._debug is deprecated.',
+ 'DEP0077');
+
+// given a module name, and a list of paths to test, returns the first
+// matching file in the following precedence.
+//
+// require("a.<ext>")
+// -> a.<ext>
+//
+// require("a")
+// -> a
+// -> a.<ext>
+// -> a/index.<ext>
+
+// check if the directory is a package.json dir
+const packageMainCache = Object.create(null);
+
+function readPackage(requestPath) {
+ const entry = packageMainCache[requestPath];
+ if (entry)
+ return entry;
+
+ const jsonPath = path.resolve(requestPath, 'package.json');
+ const json = internalModuleReadJSON(path.toNamespacedPath(jsonPath));
+
+ if (json === undefined) {
+ return false;
+ }
+
+ try {
+ var pkg = packageMainCache[requestPath] = JSON.parse(json).main;
+ } catch (e) {
+ e.path = jsonPath;
+ e.message = 'Error parsing ' + jsonPath + ': ' + e.message;
+ throw e;
+ }
+ return pkg;
+}
+
+function tryPackage(requestPath, exts, isMain) {
+ var pkg = readPackage(requestPath);
+
+ if (!pkg) return false;
+
+ var filename = path.resolve(requestPath, pkg);
+ return tryFile(filename, isMain) ||
+ tryExtensions(filename, exts, isMain) ||
+ tryExtensions(path.resolve(filename, 'index'), exts, isMain);
+}
+
+// In order to minimize unnecessary lstat() calls,
+// this cache is a list of known-real paths.
+// Set to an empty Map to reset.
+const realpathCache = new Map();
+
+// check if the file exists and is not a directory
+// if using --preserve-symlinks and isMain is false,
+// keep symlinks intact, otherwise resolve to the
+// absolute realpath.
+function tryFile(requestPath, isMain) {
+ const rc = stat(requestPath);
+ if (preserveSymlinks && !isMain) {
+ return rc === 0 && path.resolve(requestPath);
+ }
+ return rc === 0 && toRealPath(requestPath);
+}
+
+function toRealPath(requestPath) {
+ return fs.realpathSync(requestPath, {
+ [internalFS.realpathCacheKey]: realpathCache
+ });
+}
+
+// given a path, check if the file exists with any of the set extensions
+function tryExtensions(p, exts, isMain) {
+ for (var i = 0; i < exts.length; i++) {
+ const filename = tryFile(p + exts[i], isMain);
+
+ if (filename) {
+ return filename;
+ }
+ }
+ return false;
+}
+
+var warned = false;
+Module._findPath = function(request, paths, isMain) {
+ if (path.isAbsolute(request)) {
+ paths = [''];
+ } else if (!paths || paths.length === 0) {
+ return false;
+ }
+
+ var cacheKey = request + '\x00' +
+ (paths.length === 1 ? paths[0] : paths.join('\x00'));
+ var entry = Module._pathCache[cacheKey];
+ if (entry)
+ return entry;
+
+ var exts;
+ var trailingSlash = request.length > 0 &&
+ request.charCodeAt(request.length - 1) === CHAR_FORWARD_SLASH;
+ if (!trailingSlash) {
+ trailingSlash = /(?:^|\/)\.?\.$/.test(request);
+ }
+
+ // For each path
+ for (var i = 0; i < paths.length; i++) {
+ // Don't search further if path doesn't exist
+ const curPath = paths[i];
+ if (curPath && stat(curPath) < 1) continue;
+ var basePath = path.resolve(curPath, request);
+ var filename;
+
+ var rc = stat(basePath);
+ if (!trailingSlash) {
+ if (rc === 0) { // File.
+ if (preserveSymlinks && !isMain) {
+ filename = path.resolve(basePath);
+ } else {
+ filename = toRealPath(basePath);
+ }
+ }
+
+ if (!filename) {
+ // try it with each of the extensions
+ if (exts === undefined)
+ exts = Object.keys(Module._extensions);
+ filename = tryExtensions(basePath, exts, isMain);
+ }
+ }
+
+ if (!filename && rc === 1) { // Directory.
+ // try it with each of the extensions at "index"
+ if (exts === undefined)
+ exts = Object.keys(Module._extensions);
+ filename = tryPackage(basePath, exts, isMain);
+ if (!filename) {
+ filename = tryExtensions(path.resolve(basePath, 'index'), exts, isMain);
+ }
+ }
+
+ if (filename) {
+ // Warn once if '.' resolved outside the module dir
+ if (request === '.' && i > 0) {
+ if (!warned) {
+ warned = true;
+ process.emitWarning(
+ 'warning: require(\'.\') resolved outside the package ' +
+ 'directory. This functionality is deprecated and will be removed ' +
+ 'soon.',
+ 'DeprecationWarning', 'DEP0019');
+ }
+ }
+
+ Module._pathCache[cacheKey] = filename;
+ return filename;
+ }
+ }
+ return false;
+};
+
+// 'node_modules' character codes reversed
+var nmChars = [ 115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110 ];
+var nmLen = nmChars.length;
+if (process.platform === 'win32') {
+ // 'from' is the __dirname of the module.
+ Module._nodeModulePaths = function(from) {
+ // guarantee that 'from' is absolute.
+ from = path.resolve(from);
+
+ // note: this approach *only* works when the path is guaranteed
+ // to be absolute. Doing a fully-edge-case-correct path.split
+ // that works on both Windows and Posix is non-trivial.
+
+ // return root node_modules when path is 'D:\\'.
+ // path.resolve will make sure from.length >=3 in Windows.
+ if (from.charCodeAt(from.length - 1) === CHAR_BACKWARD_SLASH &&
+ from.charCodeAt(from.length - 2) === CHAR_COLON)
+ return [from + 'node_modules'];
+
+ const paths = [];
+ var p = 0;
+ var last = from.length;
+ for (var i = from.length - 1; i >= 0; --i) {
+ const code = from.charCodeAt(i);
+ // The path segment separator check ('\' and '/') was used to get
+ // node_modules path for every path segment.
+ // Use colon as an extra condition since we can get node_modules
+ // path for drive root like 'C:\node_modules' and don't need to
+ // parse drive name.
+ if (code === CHAR_BACKWARD_SLASH ||
+ code === CHAR_FORWARD_SLASH ||
+ code === CHAR_COLON) {
+ if (p !== nmLen)
+ paths.push(from.slice(0, last) + '\\node_modules');
+ last = i;
+ p = 0;
+ } else if (p !== -1) {
+ if (nmChars[p] === code) {
+ ++p;
+ } else {
+ p = -1;
+ }
+ }
+ }
+
+ return paths;
+ };
+} else { // posix
+ // 'from' is the __dirname of the module.
+ Module._nodeModulePaths = function(from) {
+ // guarantee that 'from' is absolute.
+ from = path.resolve(from);
+ // Return early not only to avoid unnecessary work, but to *avoid* returning
+ // an array of two items for a root: [ '//node_modules', '/node_modules' ]
+ if (from === '/')
+ return ['/node_modules'];
+
+ // note: this approach *only* works when the path is guaranteed
+ // to be absolute. Doing a fully-edge-case-correct path.split
+ // that works on both Windows and Posix is non-trivial.
+ const paths = [];
+ var p = 0;
+ var last = from.length;
+ for (var i = from.length - 1; i >= 0; --i) {
+ const code = from.charCodeAt(i);
+ if (code === CHAR_FORWARD_SLASH) {
+ if (p !== nmLen)
+ paths.push(from.slice(0, last) + '/node_modules');
+ last = i;
+ p = 0;
+ } else if (p !== -1) {
+ if (nmChars[p] === code) {
+ ++p;
+ } else {
+ p = -1;
+ }
+ }
+ }
+
+ // Append /node_modules to handle root paths.
+ paths.push('/node_modules');
+
+ return paths;
+ };
+}
+
+
+// 'index.' character codes
+var indexChars = [ 105, 110, 100, 101, 120, 46 ];
+var indexLen = indexChars.length;
+Module._resolveLookupPaths = function(request, parent, newReturn) {
+ if (NativeModule.nonInternalExists(request)) {
+ debug('looking for %j in []', request);
+ return (newReturn ? null : [request, []]);
+ }
+
+ // Check for relative path
+ if (request.length < 2 ||
+ request.charCodeAt(0) !== CHAR_DOT ||
+ (request.charCodeAt(1) !== CHAR_DOT &&
+ request.charCodeAt(1) !== CHAR_FORWARD_SLASH)) {
+ var paths = modulePaths;
+ if (parent) {
+ if (!parent.paths)
+ paths = parent.paths = [];
+ else
+ paths = parent.paths.concat(paths);
+ }
+
+ // Maintain backwards compat with certain broken uses of require('.')
+ // by putting the module's directory in front of the lookup paths.
+ if (request === '.') {
+ if (parent && parent.filename) {
+ paths.unshift(path.dirname(parent.filename));
+ } else {
+ paths.unshift(path.resolve(request));
+ }
+ }
+
+ debug('looking for %j in %j', request, paths);
+ return (newReturn ? (paths.length > 0 ? paths : null) : [request, paths]);
+ }
+
+ // with --eval, parent.id is not set and parent.filename is null
+ if (!parent || !parent.id || !parent.filename) {
+ // make require('./path/to/foo') work - normally the path is taken
+ // from realpath(__filename) but with eval there is no filename
+ var mainPaths = ['.'].concat(Module._nodeModulePaths('.'), modulePaths);
+
+ debug('looking for %j in %j', request, mainPaths);
+ return (newReturn ? mainPaths : [request, mainPaths]);
+ }
+
+ // Is the parent an index module?
+ // We can assume the parent has a valid extension,
+ // as it already has been accepted as a module.
+ const base = path.basename(parent.filename);
+ var parentIdPath;
+ if (base.length > indexLen) {
+ var i = 0;
+ for (; i < indexLen; ++i) {
+ if (indexChars[i] !== base.charCodeAt(i))
+ break;
+ }
+ if (i === indexLen) {
+ // We matched 'index.', let's validate the rest
+ for (; i < base.length; ++i) {
+ const code = base.charCodeAt(i);
+ if (code !== CHAR_UNDERSCORE &&
+ (code < CHAR_0 || code > CHAR_9) &&
+ (code < CHAR_UPPERCASE_A || code > CHAR_UPPERCASE_Z) &&
+ (code < CHAR_LOWERCASE_A || code > CHAR_LOWERCASE_Z))
+ break;
+ }
+ if (i === base.length) {
+ // Is an index module
+ parentIdPath = parent.id;
+ } else {
+ // Not an index module
+ parentIdPath = path.dirname(parent.id);
+ }
+ } else {
+ // Not an index module
+ parentIdPath = path.dirname(parent.id);
+ }
+ } else {
+ // Not an index module
+ parentIdPath = path.dirname(parent.id);
+ }
+ var id = path.resolve(parentIdPath, request);
+
+ // make sure require('./path') and require('path') get distinct ids, even
+ // when called from the toplevel js file
+ if (parentIdPath === '.' && id.indexOf('/') === -1) {
+ id = './' + id;
+ }
+
+ debug('RELATIVE: requested: %s set ID to: %s from %s', request, id,
+ parent.id);
+
+ var parentDir = [path.dirname(parent.filename)];
+ debug('looking for %j in %j', id, parentDir);
+ return (newReturn ? parentDir : [id, parentDir]);
+};
+
+// Check the cache for the requested file.
+// 1. If a module already exists in the cache: return its exports object.
+// 2. If the module is native: call `NativeModule.require()` with the
+// filename and return the result.
+// 3. Otherwise, create a new module for the file and save it to the cache.
+// Then have it load the file contents before returning its exports
+// object.
+Module._load = function(request, parent, isMain) {
+ if (parent) {
+ debug('Module._load REQUEST %s parent: %s', request, parent.id);
+ }
+
+ if (experimentalModules && isMain) {
+ asyncESM.loaderPromise.then((loader) => {
+ return loader.import(getURLFromFilePath(request).pathname);
+ })
+ .catch((e) => {
+ decorateErrorStack(e);
+ console.error(e);
+ process.exit(1);
+ });
+ return;
+ }
+
+ var filename = Module._resolveFilename(request, parent, isMain);
+
+ var cachedModule = Module._cache[filename];
+ if (cachedModule) {
+ updateChildren(parent, cachedModule, true);
+ return cachedModule.exports;
+ }
+
+ if (NativeModule.nonInternalExists(filename)) {
+ debug('load native module %s', request);
+ return NativeModule.require(filename);
+ }
+
+ // Don't call updateChildren(), Module constructor already does.
+ var module = new Module(filename, parent);
+
+ if (isMain) {
+ process.mainModule = module;
+ module.id = '.';
+ }
+
+ Module._cache[filename] = module;
+
+ tryModuleLoad(module, filename);
+
+ return module.exports;
+};
+
+function tryModuleLoad(module, filename) {
+ var threw = true;
+ try {
+ module.load(filename);
+ threw = false;
+ } finally {
+ if (threw) {
+ delete Module._cache[filename];
+ }
+ }
+}
+
+Module._resolveFilename = function(request, parent, isMain, options) {
+ if (NativeModule.nonInternalExists(request)) {
+ return request;
+ }
+
+ var paths;
+
+ if (typeof options === 'object' && options !== null &&
+ Array.isArray(options.paths)) {
+ const fakeParent = new Module('', null);
+
+ paths = [];
+
+ for (var i = 0; i < options.paths.length; i++) {
+ const path = options.paths[i];
+ fakeParent.paths = Module._nodeModulePaths(path);
+ const lookupPaths = Module._resolveLookupPaths(request, fakeParent, 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.
+ var filename = Module._findPath(request, paths, isMain);
+ if (!filename) {
+ var err = new Error(`Cannot find module '${request}'`);
+ err.code = 'MODULE_NOT_FOUND';
+ throw err;
+ }
+ return filename;
+};
+
+
+// Given a file name, pass it to the proper extension handler.
+Module.prototype.load = function(filename) {
+ debug('load %j for module %j', filename, this.id);
+
+ assert(!this.loaded);
+ this.filename = filename;
+ this.paths = Module._nodeModulePaths(path.dirname(filename));
+
+ var extension = path.extname(filename) || '.js';
+ if (!Module._extensions[extension]) extension = '.js';
+ Module._extensions[extension](this, filename);
+ this.loaded = true;
+
+ if (experimentalModules) {
+ const ESMLoader = asyncESM.ESMLoader;
+ const url = getURLFromFilePath(filename);
+ const urlString = `${url}`;
+ const exports = this.exports;
+ if (ESMLoader.moduleMap.has(urlString) !== true) {
+ ESMLoader.moduleMap.set(
+ urlString,
+ new ModuleJob(ESMLoader, url, async () => {
+ const ctx = createDynamicModule(
+ ['default'], url);
+ ctx.reflect.exports.default.set(exports);
+ return ctx;
+ })
+ );
+ } else {
+ const job = ESMLoader.moduleMap.get(urlString);
+ if (job.reflect)
+ job.reflect.exports.default.set(exports);
+ }
+ }
+};
+
+
+// Loads a module at the given file path. Returns that module's
+// `exports` property.
+Module.prototype.require = function(id) {
+ if (typeof id !== 'string') {
+ throw new ERR_INVALID_ARG_TYPE('id', 'string', id);
+ }
+ if (id === '') {
+ throw new ERR_INVALID_ARG_VALUE('id', id,
+ 'must be a non-empty string');
+ }
+ return Module._load(id, this, /* isMain */ false);
+};
+
+
+// Resolved path to process.argv[1] will be lazily placed here
+// (needed for setting breakpoint when called with --inspect-brk)
+var resolvedArgv;
+
+
+// Run the file contents in the correct scope or sandbox. Expose
+// the correct helper variables (require, module, exports) to
+// the file.
+// Returns exception, if any.
+Module.prototype._compile = function(content, filename) {
+
+ content = stripShebang(content);
+
+ // create wrapper function
+ var wrapper = Module.wrap(content);
+
+ var compiledWrapper = vm.runInThisContext(wrapper, {
+ filename: filename,
+ lineOffset: 0,
+ displayErrors: true
+ });
+
+ var inspectorWrapper = null;
+ if (process._breakFirstLine && process._eval == null) {
+ if (!resolvedArgv) {
+ // we enter the repl if we're not given a filename argument.
+ if (process.argv[1]) {
+ resolvedArgv = Module._resolveFilename(process.argv[1], null, false);
+ } else {
+ resolvedArgv = 'repl';
+ }
+ }
+
+ // Set breakpoint on module start
+ if (filename === resolvedArgv) {
+ delete process._breakFirstLine;
+ inspectorWrapper = process.binding('inspector').callAndPauseOnStart;
+ }
+ }
+ var dirname = path.dirname(filename);
+ var require = makeRequireFunction(this);
+ var depth = requireDepth;
+ if (depth === 0) stat.cache = new Map();
+ var result;
+ if (inspectorWrapper) {
+ result = inspectorWrapper(compiledWrapper, this.exports, this.exports,
+ require, this, filename, dirname);
+ } else {
+ result = compiledWrapper.call(this.exports, this.exports, require, this,
+ filename, dirname);
+ }
+ if (depth === 0) stat.cache = null;
+ return result;
+};
+
+
+// Native extension for .js
+Module._extensions['.js'] = function(module, filename) {
+ var content = fs.readFileSync(filename, 'utf8');
+ module._compile(stripBOM(content), filename);
+};
+
+
+// Native extension for .json
+Module._extensions['.json'] = function(module, filename) {
+ var content = fs.readFileSync(filename, 'utf8');
+ try {
+ module.exports = JSON.parse(stripBOM(content));
+ } catch (err) {
+ err.message = filename + ': ' + err.message;
+ throw err;
+ }
+};
+
+
+//Native extension for .node
+Module._extensions['.node'] = function(module, filename) {
+ return process.dlopen(module, path.toNamespacedPath(filename));
+};
+
+if (experimentalModules) {
+ Module._extensions['.mjs'] = function(module, filename) {
+ throw new ERR_REQUIRE_ESM(filename);
+ };
+}
+
+// bootstrap main module.
+Module.runMain = function() {
+ // Load the main module--the command line argument.
+ Module._load(process.argv[1], null, true);
+ // Handle any nextTicks added in the first tick of the program
+ process._tickCallback();
+};
+
+Module._initPaths = function() {
+ const isWindows = process.platform === 'win32';
+
+ var homeDir;
+ var nodePath;
+ if (isWindows) {
+ homeDir = process.env.USERPROFILE;
+ nodePath = process.env.NODE_PATH;
+ } else {
+ homeDir = safeGetenv('HOME');
+ nodePath = safeGetenv('NODE_PATH');
+ }
+
+ // $PREFIX/lib/node, where $PREFIX is the root of the Node.js installation.
+ var prefixDir;
+ // process.execPath is $PREFIX/bin/node except on Windows where it is
+ // $PREFIX\node.exe.
+ if (isWindows) {
+ prefixDir = path.resolve(process.execPath, '..');
+ } else {
+ prefixDir = path.resolve(process.execPath, '..', '..');
+ }
+ var paths = [path.resolve(prefixDir, 'lib', 'node')];
+
+ if (homeDir) {
+ paths.unshift(path.resolve(homeDir, '.node_libraries'));
+ paths.unshift(path.resolve(homeDir, '.node_modules'));
+ }
+
+ if (nodePath) {
+ paths = nodePath.split(path.delimiter).filter(function(path) {
+ return !!path;
+ }).concat(paths);
+ }
+
+ modulePaths = paths;
+
+ // clone as a shallow copy, for introspection.
+ Module.globalPaths = modulePaths.slice(0);
+};
+
+Module._preloadModules = function(requests) {
+ if (!Array.isArray(requests))
+ return;
+
+ // Preloaded modules have a dummy parent module which is deemed to exist
+ // in the current working directory. This seeds the search path for
+ // preloaded modules.
+ var parent = new Module('internal/preload', null);
+ try {
+ parent.paths = Module._nodeModulePaths(process.cwd());
+ } catch (e) {
+ if (e.code !== 'ENOENT') {
+ throw e;
+ }
+ }
+ for (var n = 0; n < requests.length; n++)
+ parent.require(requests[n]);
+};
+
+Module._initPaths();
+
+// backwards compatibility
+Module.Module = Module;