• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23
24const {
25  ArrayIsArray,
26  ArrayPrototypeConcat,
27  ArrayPrototypeFilter,
28  ArrayPrototypeIncludes,
29  ArrayPrototypeIndexOf,
30  ArrayPrototypeJoin,
31  ArrayPrototypePush,
32  ArrayPrototypeSlice,
33  ArrayPrototypeSplice,
34  ArrayPrototypeUnshift,
35  Boolean,
36  Error,
37  JSONParse,
38  ObjectCreate,
39  ObjectDefineProperty,
40  ObjectFreeze,
41  ObjectGetOwnPropertyDescriptor,
42  ObjectGetPrototypeOf,
43  ObjectKeys,
44  ObjectPrototype,
45  ObjectPrototypeHasOwnProperty,
46  ObjectSetPrototypeOf,
47  Proxy,
48  ReflectApply,
49  ReflectSet,
50  RegExpPrototypeTest,
51  SafeMap,
52  SafeWeakMap,
53  String,
54  StringPrototypeCharAt,
55  StringPrototypeCharCodeAt,
56  StringPrototypeEndsWith,
57  StringPrototypeLastIndexOf,
58  StringPrototypeIndexOf,
59  StringPrototypeMatch,
60  StringPrototypeSlice,
61  StringPrototypeSplit,
62  StringPrototypeStartsWith,
63} = primordials;
64
65// Map used to store CJS parsing data.
66const cjsParseCache = new SafeWeakMap();
67
68// Set first due to cycle with ESM loader functions.
69module.exports = {
70  wrapSafe, Module, toRealPath, readPackageScope, cjsParseCache,
71  get hasLoadedAnyUserCJSModule() { return hasLoadedAnyUserCJSModule; }
72};
73
74const { NativeModule } = require('internal/bootstrap/loaders');
75const {
76  maybeCacheSourceMap,
77} = require('internal/source_map/source_map_cache');
78const { pathToFileURL, fileURLToPath, isURLInstance } = require('internal/url');
79const { deprecate } = require('internal/util');
80const vm = require('vm');
81const assert = require('internal/assert');
82const fs = require('fs');
83const internalFS = require('internal/fs/utils');
84const path = require('path');
85const { sep } = path;
86const { internalModuleStat } = internalBinding('fs');
87const packageJsonReader = require('internal/modules/package_json_reader');
88const { safeGetenv } = internalBinding('credentials');
89const {
90  makeRequireFunction,
91  normalizeReferrerURL,
92  stripBOM,
93  cjsConditions,
94  loadNativeModule
95} = require('internal/modules/cjs/helpers');
96const { getOptionValue } = require('internal/options');
97const preserveSymlinks = getOptionValue('--preserve-symlinks');
98const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
99// Do not eagerly grab .manifest, it may be in TDZ
100const policy = getOptionValue('--experimental-policy') ?
101  require('internal/process/policy') :
102  null;
103const { compileFunction } = internalBinding('contextify');
104
105// Whether any user-provided CJS modules had been loaded (executed).
106// Used for internal assertions.
107let hasLoadedAnyUserCJSModule = false;
108
109const {
110  ERR_INVALID_ARG_VALUE,
111  ERR_INVALID_OPT_VALUE,
112  ERR_INVALID_MODULE_SPECIFIER,
113  ERR_REQUIRE_ESM,
114  ERR_UNKNOWN_BUILTIN_MODULE,
115} = require('internal/errors').codes;
116const { validateString } = require('internal/validators');
117const pendingDeprecation = getOptionValue('--pending-deprecation');
118
119const {
120  CHAR_FORWARD_SLASH,
121  CHAR_BACKWARD_SLASH,
122  CHAR_COLON
123} = require('internal/constants');
124
125const {
126  isProxy
127} = require('internal/util/types');
128
129const asyncESM = require('internal/process/esm_loader');
130const { enrichCJSError } = require('internal/modules/esm/translators');
131const { kEvaluated } = internalBinding('module_wrap');
132const {
133  encodedSepRegEx,
134  packageExportsResolve,
135  packageImportsResolve
136} = require('internal/modules/esm/resolve');
137
138const isWindows = process.platform === 'win32';
139
140const relativeResolveCache = ObjectCreate(null);
141
142let requireDepth = 0;
143let statCache = null;
144let isPreloading = false;
145
146function stat(filename) {
147  filename = path.toNamespacedPath(filename);
148  if (statCache !== null) {
149    const result = statCache.get(filename);
150    if (result !== undefined) return result;
151  }
152  const result = internalModuleStat(filename);
153  if (statCache !== null) statCache.set(filename, result);
154  return result;
155}
156
157function updateChildren(parent, child, scan) {
158  const children = parent && parent.children;
159  if (children && !(scan && ArrayPrototypeIncludes(children, child)))
160    ArrayPrototypePush(children, child);
161}
162
163function Module(id = '', parent) {
164  this.id = id;
165  this.path = path.dirname(id);
166  this.exports = {};
167  this.parent = parent;
168  updateChildren(parent, this, false);
169  this.filename = null;
170  this.loaded = false;
171  this.children = [];
172}
173
174const builtinModules = [];
175for (const { 0: id, 1: mod } of NativeModule.map) {
176  if (mod.canBeRequiredByUsers) {
177    ArrayPrototypePush(builtinModules, id);
178  }
179}
180
181ObjectFreeze(builtinModules);
182Module.builtinModules = builtinModules;
183
184Module._cache = ObjectCreate(null);
185Module._pathCache = ObjectCreate(null);
186Module._extensions = ObjectCreate(null);
187let modulePaths = [];
188Module.globalPaths = [];
189
190let patched = false;
191
192// eslint-disable-next-line func-style
193let wrap = function(script) {
194  return Module.wrapper[0] + script + Module.wrapper[1];
195};
196
197const wrapper = [
198  '(function (exports, require, module, __filename, __dirname) { ',
199  '\n});',
200];
201
202let wrapperProxy = new Proxy(wrapper, {
203  set(target, property, value, receiver) {
204    patched = true;
205    return ReflectSet(target, property, value, receiver);
206  },
207
208  defineProperty(target, property, descriptor) {
209    patched = true;
210    return ObjectDefineProperty(target, property, descriptor);
211  }
212});
213
214ObjectDefineProperty(Module, 'wrap', {
215  get() {
216    return wrap;
217  },
218
219  set(value) {
220    patched = true;
221    wrap = value;
222  }
223});
224
225ObjectDefineProperty(Module, 'wrapper', {
226  get() {
227    return wrapperProxy;
228  },
229
230  set(value) {
231    patched = true;
232    wrapperProxy = value;
233  }
234});
235
236const isPreloadingDesc = { get() { return isPreloading; } };
237ObjectDefineProperty(Module.prototype, 'isPreloading', isPreloadingDesc);
238ObjectDefineProperty(NativeModule.prototype, 'isPreloading', isPreloadingDesc);
239
240let debug = require('internal/util/debuglog').debuglog('module', (fn) => {
241  debug = fn;
242});
243Module._debug = deprecate(debug, 'Module._debug is deprecated.', 'DEP0077');
244
245// Given a module name, and a list of paths to test, returns the first
246// matching file in the following precedence.
247//
248// require("a.<ext>")
249//   -> a.<ext>
250//
251// require("a")
252//   -> a
253//   -> a.<ext>
254//   -> a/index.<ext>
255
256const packageJsonCache = new SafeMap();
257
258function readPackage(requestPath) {
259  const jsonPath = path.resolve(requestPath, 'package.json');
260
261  const existing = packageJsonCache.get(jsonPath);
262  if (existing !== undefined) return existing;
263
264  const result = packageJsonReader.read(jsonPath);
265  const json = result.containsKeys === false ? '{}' : result.string;
266  if (json === undefined) {
267    packageJsonCache.set(jsonPath, false);
268    return false;
269  }
270
271  try {
272    const parsed = JSONParse(json);
273    const filtered = {
274      name: parsed.name,
275      main: parsed.main,
276      exports: parsed.exports,
277      imports: parsed.imports,
278      type: parsed.type
279    };
280    packageJsonCache.set(jsonPath, filtered);
281    return filtered;
282  } catch (e) {
283    e.path = jsonPath;
284    e.message = 'Error parsing ' + jsonPath + ': ' + e.message;
285    throw e;
286  }
287}
288
289function readPackageScope(checkPath) {
290  const rootSeparatorIndex = StringPrototypeIndexOf(checkPath, sep);
291  let separatorIndex;
292  do {
293    separatorIndex = StringPrototypeLastIndexOf(checkPath, sep);
294    checkPath = StringPrototypeSlice(checkPath, 0, separatorIndex);
295    if (StringPrototypeEndsWith(checkPath, sep + 'node_modules'))
296      return false;
297    const pjson = readPackage(checkPath + sep);
298    if (pjson) return {
299      data: pjson,
300      path: checkPath,
301    };
302  } while (separatorIndex > rootSeparatorIndex);
303  return false;
304}
305
306function tryPackage(requestPath, exts, isMain, originalPath) {
307  const pkg = readPackage(requestPath)?.main;
308
309  if (!pkg) {
310    return tryExtensions(path.resolve(requestPath, 'index'), exts, isMain);
311  }
312
313  const filename = path.resolve(requestPath, pkg);
314  let actual = tryFile(filename, isMain) ||
315    tryExtensions(filename, exts, isMain) ||
316    tryExtensions(path.resolve(filename, 'index'), exts, isMain);
317  if (actual === false) {
318    actual = tryExtensions(path.resolve(requestPath, 'index'), exts, isMain);
319    if (!actual) {
320      // eslint-disable-next-line no-restricted-syntax
321      const err = new Error(
322        `Cannot find module '${filename}'. ` +
323        'Please verify that the package.json has a valid "main" entry'
324      );
325      err.code = 'MODULE_NOT_FOUND';
326      err.path = path.resolve(requestPath, 'package.json');
327      err.requestPath = originalPath;
328      // TODO(BridgeAR): Add the requireStack as well.
329      throw err;
330    } else if (pendingDeprecation) {
331      const jsonPath = path.resolve(requestPath, 'package.json');
332      process.emitWarning(
333        `Invalid 'main' field in '${jsonPath}' of '${pkg}'. ` +
334          'Please either fix that or report it to the module author',
335        'DeprecationWarning',
336        'DEP0128'
337      );
338    }
339  }
340  return actual;
341}
342
343// In order to minimize unnecessary lstat() calls,
344// this cache is a list of known-real paths.
345// Set to an empty Map to reset.
346const realpathCache = new SafeMap();
347
348// Check if the file exists and is not a directory
349// if using --preserve-symlinks and isMain is false,
350// keep symlinks intact, otherwise resolve to the
351// absolute realpath.
352function tryFile(requestPath, isMain) {
353  const rc = stat(requestPath);
354  if (rc !== 0) return;
355  if (preserveSymlinks && !isMain) {
356    return path.resolve(requestPath);
357  }
358  return toRealPath(requestPath);
359}
360
361function toRealPath(requestPath) {
362  return fs.realpathSync(requestPath, {
363    [internalFS.realpathCacheKey]: realpathCache
364  });
365}
366
367// Given a path, check if the file exists with any of the set extensions
368function tryExtensions(p, exts, isMain) {
369  for (let i = 0; i < exts.length; i++) {
370    const filename = tryFile(p + exts[i], isMain);
371
372    if (filename) {
373      return filename;
374    }
375  }
376  return false;
377}
378
379// Find the longest (possibly multi-dot) extension registered in
380// Module._extensions
381function findLongestRegisteredExtension(filename) {
382  const name = path.basename(filename);
383  let currentExtension;
384  let index;
385  let startIndex = 0;
386  while ((index = StringPrototypeIndexOf(name, '.', startIndex)) !== -1) {
387    startIndex = index + 1;
388    if (index === 0) continue; // Skip dotfiles like .gitignore
389    currentExtension = StringPrototypeSlice(name, index);
390    if (Module._extensions[currentExtension]) return currentExtension;
391  }
392  return '.js';
393}
394
395function trySelfParentPath(parent) {
396  if (!parent) return false;
397
398  if (parent.filename) {
399    return parent.filename;
400  } else if (parent.id === '<repl>' || parent.id === 'internal/preload') {
401    try {
402      return process.cwd() + path.sep;
403    } catch {
404      return false;
405    }
406  }
407}
408
409function trySelf(parentPath, request) {
410  if (!parentPath) return false;
411
412  const { data: pkg, path: pkgPath } = readPackageScope(parentPath) || {};
413  if (!pkg || pkg.exports === undefined) return false;
414  if (typeof pkg.name !== 'string') return false;
415
416  let expansion;
417  if (request === pkg.name) {
418    expansion = '.';
419  } else if (StringPrototypeStartsWith(request, `${pkg.name}/`)) {
420    expansion = '.' + StringPrototypeSlice(request, pkg.name.length);
421  } else {
422    return false;
423  }
424
425  try {
426    return finalizeEsmResolution(packageExportsResolve(
427      pathToFileURL(pkgPath + '/package.json'), expansion, pkg,
428      pathToFileURL(parentPath), cjsConditions), request, parentPath, pkgPath);
429  } catch (e) {
430    if (e.code === 'ERR_MODULE_NOT_FOUND')
431      throw createEsmNotFoundErr(request, pkgPath + '/package.json');
432    throw e;
433  }
434}
435
436// This only applies to requests of a specific form:
437// 1. name/.*
438// 2. @scope/name/.*
439const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;
440function resolveExports(nmPath, request) {
441  // The implementation's behavior is meant to mirror resolution in ESM.
442  const { 1: name, 2: expansion = '' } =
443    StringPrototypeMatch(request, EXPORTS_PATTERN) || [];
444  if (!name)
445    return;
446  const pkgPath = path.resolve(nmPath, name);
447  const pkg = readPackage(pkgPath);
448  if (pkg && pkg.exports !== null && pkg.exports !== undefined) {
449    try {
450      return finalizeEsmResolution(packageExportsResolve(
451        pathToFileURL(pkgPath + '/package.json'), '.' + expansion, pkg, null,
452        cjsConditions), request, null, pkgPath);
453    } catch (e) {
454      if (e.code === 'ERR_MODULE_NOT_FOUND')
455        throw createEsmNotFoundErr(request, pkgPath + '/package.json');
456      throw e;
457    }
458  }
459}
460
461const trailingSlashRegex = /(?:^|\/)\.?\.$/;
462Module._findPath = function(request, paths, isMain) {
463  const absoluteRequest = path.isAbsolute(request);
464  if (absoluteRequest) {
465    paths = [''];
466  } else if (!paths || paths.length === 0) {
467    return false;
468  }
469
470  const cacheKey = request + '\x00' + ArrayPrototypeJoin(paths, '\x00');
471  const entry = Module._pathCache[cacheKey];
472  if (entry)
473    return entry;
474
475  let exts;
476  let trailingSlash = request.length > 0 &&
477    StringPrototypeCharCodeAt(request, request.length - 1) ===
478    CHAR_FORWARD_SLASH;
479  if (!trailingSlash) {
480    trailingSlash = RegExpPrototypeTest(trailingSlashRegex, request);
481  }
482
483  // For each path
484  for (let i = 0; i < paths.length; i++) {
485    // Don't search further if path doesn't exist
486    const curPath = paths[i];
487    if (curPath && stat(curPath) < 1) continue;
488
489    if (!absoluteRequest) {
490      const exportsResolved = resolveExports(curPath, request);
491      if (exportsResolved)
492        return exportsResolved;
493    }
494
495    const basePath = path.resolve(curPath, request);
496    let filename;
497
498    const rc = stat(basePath);
499    if (!trailingSlash) {
500      if (rc === 0) {  // File.
501        if (!isMain) {
502          if (preserveSymlinks) {
503            filename = path.resolve(basePath);
504          } else {
505            filename = toRealPath(basePath);
506          }
507        } else if (preserveSymlinksMain) {
508          // For the main module, we use the preserveSymlinksMain flag instead
509          // mainly for backward compatibility, as the preserveSymlinks flag
510          // historically has not applied to the main module.  Most likely this
511          // was intended to keep .bin/ binaries working, as following those
512          // symlinks is usually required for the imports in the corresponding
513          // files to resolve; that said, in some use cases following symlinks
514          // causes bigger problems which is why the preserveSymlinksMain option
515          // is needed.
516          filename = path.resolve(basePath);
517        } else {
518          filename = toRealPath(basePath);
519        }
520      }
521
522      if (!filename) {
523        // Try it with each of the extensions
524        if (exts === undefined)
525          exts = ObjectKeys(Module._extensions);
526        filename = tryExtensions(basePath, exts, isMain);
527      }
528    }
529
530    if (!filename && rc === 1) {  // Directory.
531      // try it with each of the extensions at "index"
532      if (exts === undefined)
533        exts = ObjectKeys(Module._extensions);
534      filename = tryPackage(basePath, exts, isMain, request);
535    }
536
537    if (filename) {
538      Module._pathCache[cacheKey] = filename;
539      return filename;
540    }
541  }
542
543  return false;
544};
545
546// 'node_modules' character codes reversed
547const nmChars = [ 115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110 ];
548const nmLen = nmChars.length;
549if (isWindows) {
550  // 'from' is the __dirname of the module.
551  Module._nodeModulePaths = function(from) {
552    // Guarantee that 'from' is absolute.
553    from = path.resolve(from);
554
555    // note: this approach *only* works when the path is guaranteed
556    // to be absolute.  Doing a fully-edge-case-correct path.split
557    // that works on both Windows and Posix is non-trivial.
558
559    // return root node_modules when path is 'D:\\'.
560    // path.resolve will make sure from.length >=3 in Windows.
561    if (StringPrototypeCharCodeAt(from, from.length - 1) ===
562          CHAR_BACKWARD_SLASH &&
563        StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON)
564      return [from + 'node_modules'];
565
566    const paths = [];
567    for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
568      const code = StringPrototypeCharCodeAt(from, i);
569      // The path segment separator check ('\' and '/') was used to get
570      // node_modules path for every path segment.
571      // Use colon as an extra condition since we can get node_modules
572      // path for drive root like 'C:\node_modules' and don't need to
573      // parse drive name.
574      if (code === CHAR_BACKWARD_SLASH ||
575          code === CHAR_FORWARD_SLASH ||
576          code === CHAR_COLON) {
577        if (p !== nmLen)
578          ArrayPrototypePush(
579            paths,
580            StringPrototypeSlice(from, 0, last) + '\\node_modules'
581          );
582        last = i;
583        p = 0;
584      } else if (p !== -1) {
585        if (nmChars[p] === code) {
586          ++p;
587        } else {
588          p = -1;
589        }
590      }
591    }
592
593    return paths;
594  };
595} else { // posix
596  // 'from' is the __dirname of the module.
597  Module._nodeModulePaths = function(from) {
598    // Guarantee that 'from' is absolute.
599    from = path.resolve(from);
600    // Return early not only to avoid unnecessary work, but to *avoid* returning
601    // an array of two items for a root: [ '//node_modules', '/node_modules' ]
602    if (from === '/')
603      return ['/node_modules'];
604
605    // note: this approach *only* works when the path is guaranteed
606    // to be absolute.  Doing a fully-edge-case-correct path.split
607    // that works on both Windows and Posix is non-trivial.
608    const paths = [];
609    for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
610      const code = StringPrototypeCharCodeAt(from, i);
611      if (code === CHAR_FORWARD_SLASH) {
612        if (p !== nmLen)
613          ArrayPrototypePush(
614            paths,
615            StringPrototypeSlice(from, 0, last) + '/node_modules'
616          );
617        last = i;
618        p = 0;
619      } else if (p !== -1) {
620        if (nmChars[p] === code) {
621          ++p;
622        } else {
623          p = -1;
624        }
625      }
626    }
627
628    // Append /node_modules to handle root paths.
629    ArrayPrototypePush(paths, '/node_modules');
630
631    return paths;
632  };
633}
634
635Module._resolveLookupPaths = function(request, parent) {
636  if (NativeModule.canBeRequiredByUsers(request)) {
637    debug('looking for %j in []', request);
638    return null;
639  }
640
641  // Check for node modules paths.
642  if (StringPrototypeCharAt(request, 0) !== '.' ||
643      (request.length > 1 &&
644      StringPrototypeCharAt(request, 1) !== '.' &&
645      StringPrototypeCharAt(request, 1) !== '/' &&
646      (!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) {
647
648    let paths = modulePaths;
649    if (parent != null && parent.paths && parent.paths.length) {
650      paths = ArrayPrototypeConcat(parent.paths, paths);
651    }
652
653    debug('looking for %j in %j', request, paths);
654    return paths.length > 0 ? paths : null;
655  }
656
657  // In REPL, parent.filename is null.
658  if (!parent || !parent.id || !parent.filename) {
659    // Make require('./path/to/foo') work - normally the path is taken
660    // from realpath(__filename) but in REPL there is no filename
661    const mainPaths = ['.'];
662
663    debug('looking for %j in %j', request, mainPaths);
664    return mainPaths;
665  }
666
667  debug('RELATIVE: requested: %s from parent.id %s', request, parent.id);
668
669  const parentDir = [path.dirname(parent.filename)];
670  debug('looking for %j', parentDir);
671  return parentDir;
672};
673
674function emitCircularRequireWarning(prop) {
675  process.emitWarning(
676    `Accessing non-existent property '${String(prop)}' of module exports ` +
677    'inside circular dependency'
678  );
679}
680
681// A Proxy that can be used as the prototype of a module.exports object and
682// warns when non-existent properties are accessed.
683const CircularRequirePrototypeWarningProxy = new Proxy({}, {
684  get(target, prop) {
685    // Allow __esModule access in any case because it is used in the output
686    // of transpiled code to determine whether something comes from an
687    // ES module, and is not used as a regular key of `module.exports`.
688    if (prop in target || prop === '__esModule') return target[prop];
689    emitCircularRequireWarning(prop);
690    return undefined;
691  },
692
693  getOwnPropertyDescriptor(target, prop) {
694    if (ObjectPrototypeHasOwnProperty(target, prop) || prop === '__esModule')
695      return ObjectGetOwnPropertyDescriptor(target, prop);
696    emitCircularRequireWarning(prop);
697    return undefined;
698  }
699});
700
701function getExportsForCircularRequire(module) {
702  if (module.exports &&
703      !isProxy(module.exports) &&
704      ObjectGetPrototypeOf(module.exports) === ObjectPrototype &&
705      // Exclude transpiled ES6 modules / TypeScript code because those may
706      // employ unusual patterns for accessing 'module.exports'. That should
707      // be okay because ES6 modules have a different approach to circular
708      // dependencies anyway.
709      !module.exports.__esModule) {
710    // This is later unset once the module is done loading.
711    ObjectSetPrototypeOf(
712      module.exports, CircularRequirePrototypeWarningProxy);
713  }
714
715  return module.exports;
716}
717
718// Check the cache for the requested file.
719// 1. If a module already exists in the cache: return its exports object.
720// 2. If the module is native: call
721//    `NativeModule.prototype.compileForPublicLoader()` and return the exports.
722// 3. Otherwise, create a new module for the file and save it to the cache.
723//    Then have it load  the file contents before returning its exports
724//    object.
725Module._load = function(request, parent, isMain) {
726  let relResolveCacheIdentifier;
727  if (parent) {
728    debug('Module._load REQUEST %s parent: %s', request, parent.id);
729    // Fast path for (lazy loaded) modules in the same directory. The indirect
730    // caching is required to allow cache invalidation without changing the old
731    // cache key names.
732    relResolveCacheIdentifier = `${parent.path}\x00${request}`;
733    const filename = relativeResolveCache[relResolveCacheIdentifier];
734    if (filename !== undefined) {
735      const cachedModule = Module._cache[filename];
736      if (cachedModule !== undefined) {
737        updateChildren(parent, cachedModule, true);
738        if (!cachedModule.loaded)
739          return getExportsForCircularRequire(cachedModule);
740        return cachedModule.exports;
741      }
742      delete relativeResolveCache[relResolveCacheIdentifier];
743    }
744  }
745
746  const filename = Module._resolveFilename(request, parent, isMain);
747  if (StringPrototypeStartsWith(filename, 'node:')) {
748    // Slice 'node:' prefix
749    const id = StringPrototypeSlice(filename, 5);
750
751    const module = loadNativeModule(id, request);
752    if (!module?.canBeRequiredByUsers) {
753      throw new ERR_UNKNOWN_BUILTIN_MODULE(filename);
754    }
755
756    return module.exports;
757  }
758
759  const cachedModule = Module._cache[filename];
760  if (cachedModule !== undefined) {
761    updateChildren(parent, cachedModule, true);
762    if (!cachedModule.loaded) {
763      const parseCachedModule = cjsParseCache.get(cachedModule);
764      if (!parseCachedModule || parseCachedModule.loaded)
765        return getExportsForCircularRequire(cachedModule);
766      parseCachedModule.loaded = true;
767    } else {
768      return cachedModule.exports;
769    }
770  }
771
772  const mod = loadNativeModule(filename, request);
773  if (mod && mod.canBeRequiredByUsers) return mod.exports;
774
775  // Don't call updateChildren(), Module constructor already does.
776  const module = cachedModule || new Module(filename, parent);
777
778  if (isMain) {
779    process.mainModule = module;
780    module.id = '.';
781  }
782
783  Module._cache[filename] = module;
784  if (parent !== undefined) {
785    relativeResolveCache[relResolveCacheIdentifier] = filename;
786  }
787
788  let threw = true;
789  try {
790    module.load(filename);
791    threw = false;
792  } finally {
793    if (threw) {
794      delete Module._cache[filename];
795      if (parent !== undefined) {
796        delete relativeResolveCache[relResolveCacheIdentifier];
797        const children = parent && parent.children;
798        if (ArrayIsArray(children)) {
799          const index = ArrayPrototypeIndexOf(children, module);
800          if (index !== -1) {
801            ArrayPrototypeSplice(children, index, 1);
802          }
803        }
804      }
805    } else if (module.exports &&
806               !isProxy(module.exports) &&
807               ObjectGetPrototypeOf(module.exports) ===
808                 CircularRequirePrototypeWarningProxy) {
809      ObjectSetPrototypeOf(module.exports, ObjectPrototype);
810    }
811  }
812
813  return module.exports;
814};
815
816Module._resolveFilename = function(request, parent, isMain, options) {
817  if (StringPrototypeStartsWith(request, 'node:') ||
818      NativeModule.canBeRequiredByUsers(request)) {
819    return request;
820  }
821
822  let paths;
823
824  if (typeof options === 'object' && options !== null) {
825    if (ArrayIsArray(options.paths)) {
826      const isRelative = StringPrototypeStartsWith(request, './') ||
827          StringPrototypeStartsWith(request, '../') ||
828          ((isWindows && StringPrototypeStartsWith(request, '.\\')) ||
829          StringPrototypeStartsWith(request, '..\\'));
830
831      if (isRelative) {
832        paths = options.paths;
833      } else {
834        const fakeParent = new Module('', null);
835
836        paths = [];
837
838        for (let i = 0; i < options.paths.length; i++) {
839          const path = options.paths[i];
840          fakeParent.paths = Module._nodeModulePaths(path);
841          const lookupPaths = Module._resolveLookupPaths(request, fakeParent);
842
843          for (let j = 0; j < lookupPaths.length; j++) {
844            if (!ArrayPrototypeIncludes(paths, lookupPaths[j]))
845              ArrayPrototypePush(paths, lookupPaths[j]);
846          }
847        }
848      }
849    } else if (options.paths === undefined) {
850      paths = Module._resolveLookupPaths(request, parent);
851    } else {
852      throw new ERR_INVALID_OPT_VALUE('options.paths', options.paths);
853    }
854  } else {
855    paths = Module._resolveLookupPaths(request, parent);
856  }
857
858  if (parent && parent.filename) {
859    if (request[0] === '#') {
860      const pkg = readPackageScope(parent.filename) || {};
861      if (pkg.data && pkg.data.imports !== null &&
862          pkg.data.imports !== undefined) {
863        try {
864          return finalizeEsmResolution(
865            packageImportsResolve(request, pathToFileURL(parent.filename),
866                                  cjsConditions), request, parent.filename,
867            pkg.path);
868        } catch (e) {
869          if (e.code === 'ERR_MODULE_NOT_FOUND')
870            throw createEsmNotFoundErr(request);
871          throw e;
872        }
873      }
874    }
875  }
876
877  // Try module self resolution first
878  const parentPath = trySelfParentPath(parent);
879  const selfResolved = trySelf(parentPath, request);
880  if (selfResolved) {
881    const cacheKey = request + '\x00' +
882         (paths.length === 1 ? paths[0] : ArrayPrototypeJoin(paths, '\x00'));
883    Module._pathCache[cacheKey] = selfResolved;
884    return selfResolved;
885  }
886
887  // Look up the filename first, since that's the cache key.
888  const filename = Module._findPath(request, paths, isMain, false);
889  if (filename) return filename;
890  const requireStack = [];
891  for (let cursor = parent;
892    cursor;
893    cursor = cursor.parent) {
894    ArrayPrototypePush(requireStack, cursor.filename || cursor.id);
895  }
896  let message = `Cannot find module '${request}'`;
897  if (requireStack.length > 0) {
898    message = message + '\nRequire stack:\n- ' +
899              ArrayPrototypeJoin(requireStack, '\n- ');
900  }
901  // eslint-disable-next-line no-restricted-syntax
902  const err = new Error(message);
903  err.code = 'MODULE_NOT_FOUND';
904  err.requireStack = requireStack;
905  throw err;
906};
907
908function finalizeEsmResolution(match, request, parentPath, pkgPath) {
909  const { resolved, exact } = match;
910  if (RegExpPrototypeTest(encodedSepRegEx, resolved))
911    throw new ERR_INVALID_MODULE_SPECIFIER(
912      resolved, 'must not include encoded "/" or "\\" characters', parentPath);
913  const filename = fileURLToPath(resolved);
914  let actual = tryFile(filename);
915  if (!exact && !actual) {
916    const exts = ObjectKeys(Module._extensions);
917    actual = tryExtensions(filename, exts, false) ||
918      tryPackage(filename, exts, false, request);
919  }
920  if (actual)
921    return actual;
922  const err = createEsmNotFoundErr(filename,
923                                   path.resolve(pkgPath, 'package.json'));
924  throw err;
925}
926
927function createEsmNotFoundErr(request, path) {
928  // eslint-disable-next-line no-restricted-syntax
929  const err = new Error(`Cannot find module '${request}'`);
930  err.code = 'MODULE_NOT_FOUND';
931  if (path)
932    err.path = path;
933  // TODO(BridgeAR): Add the requireStack as well.
934  return err;
935}
936
937// Given a file name, pass it to the proper extension handler.
938Module.prototype.load = function(filename) {
939  debug('load %j for module %j', filename, this.id);
940
941  assert(!this.loaded);
942  this.filename = filename;
943  this.paths = Module._nodeModulePaths(path.dirname(filename));
944
945  const extension = findLongestRegisteredExtension(filename);
946  // allow .mjs to be overridden
947  if (StringPrototypeEndsWith(filename, '.mjs') && !Module._extensions['.mjs'])
948    throw new ERR_REQUIRE_ESM(filename);
949
950  Module._extensions[extension](this, filename);
951  this.loaded = true;
952
953  const ESMLoader = asyncESM.ESMLoader;
954  // Create module entry at load time to snapshot exports correctly
955  const exports = this.exports;
956  // Preemptively cache
957  if ((module?.module === undefined ||
958       module.module.getStatus() < kEvaluated) &&
959      !ESMLoader.cjsCache.has(this))
960    ESMLoader.cjsCache.set(this, exports);
961};
962
963
964// Loads a module at the given file path. Returns that module's
965// `exports` property.
966Module.prototype.require = function(id) {
967  validateString(id, 'id');
968  if (id === '') {
969    throw new ERR_INVALID_ARG_VALUE('id', id,
970                                    'must be a non-empty string');
971  }
972  requireDepth++;
973  try {
974    return Module._load(id, this, /* isMain */ false);
975  } finally {
976    requireDepth--;
977  }
978};
979
980
981// Resolved path to process.argv[1] will be lazily placed here
982// (needed for setting breakpoint when called with --inspect-brk)
983let resolvedArgv;
984let hasPausedEntry = false;
985
986function wrapSafe(filename, content, cjsModuleInstance) {
987  if (patched) {
988    const wrapper = Module.wrap(content);
989    return vm.runInThisContext(wrapper, {
990      filename,
991      lineOffset: 0,
992      displayErrors: true,
993      importModuleDynamically: async (specifier) => {
994        const loader = asyncESM.ESMLoader;
995        return loader.import(specifier, normalizeReferrerURL(filename));
996      },
997    });
998  }
999  let compiled;
1000  try {
1001    compiled = compileFunction(
1002      content,
1003      filename,
1004      0,
1005      0,
1006      undefined,
1007      false,
1008      undefined,
1009      [],
1010      [
1011        'exports',
1012        'require',
1013        'module',
1014        '__filename',
1015        '__dirname',
1016      ]
1017    );
1018  } catch (err) {
1019    if (process.mainModule === cjsModuleInstance)
1020      enrichCJSError(err);
1021    throw err;
1022  }
1023
1024  const { callbackMap } = internalBinding('module_wrap');
1025  callbackMap.set(compiled.cacheKey, {
1026    importModuleDynamically: async (specifier) => {
1027      const loader = asyncESM.ESMLoader;
1028      return loader.import(specifier, normalizeReferrerURL(filename));
1029    }
1030  });
1031
1032  return compiled.function;
1033}
1034
1035// Run the file contents in the correct scope or sandbox. Expose
1036// the correct helper variables (require, module, exports) to
1037// the file.
1038// Returns exception, if any.
1039Module.prototype._compile = function(content, filename) {
1040  let moduleURL;
1041  let redirects;
1042  if (policy?.manifest) {
1043    moduleURL = pathToFileURL(filename);
1044    redirects = policy.manifest.getDependencyMapper(moduleURL);
1045    policy.manifest.assertIntegrity(moduleURL, content);
1046  }
1047
1048  maybeCacheSourceMap(filename, content, this);
1049  const compiledWrapper = wrapSafe(filename, content, this);
1050
1051  let inspectorWrapper = null;
1052  if (getOptionValue('--inspect-brk') && process._eval == null) {
1053    if (!resolvedArgv) {
1054      // We enter the repl if we're not given a filename argument.
1055      if (process.argv[1]) {
1056        try {
1057          resolvedArgv = Module._resolveFilename(process.argv[1], null, false);
1058        } catch {
1059          // We only expect this codepath to be reached in the case of a
1060          // preloaded module (it will fail earlier with the main entry)
1061          assert(ArrayIsArray(getOptionValue('--require')));
1062        }
1063      } else {
1064        resolvedArgv = 'repl';
1065      }
1066    }
1067
1068    // Set breakpoint on module start
1069    if (resolvedArgv && !hasPausedEntry && filename === resolvedArgv) {
1070      hasPausedEntry = true;
1071      inspectorWrapper = internalBinding('inspector').callAndPauseOnStart;
1072    }
1073  }
1074  const dirname = path.dirname(filename);
1075  const require = makeRequireFunction(this, redirects);
1076  let result;
1077  const exports = this.exports;
1078  const thisValue = exports;
1079  const module = this;
1080  if (requireDepth === 0) statCache = new SafeMap();
1081  if (inspectorWrapper) {
1082    result = inspectorWrapper(compiledWrapper, thisValue, exports,
1083                              require, module, filename, dirname);
1084  } else {
1085    result = ReflectApply(compiledWrapper, thisValue,
1086                          [exports, require, module, filename, dirname]);
1087  }
1088  hasLoadedAnyUserCJSModule = true;
1089  if (requireDepth === 0) statCache = null;
1090  return result;
1091};
1092
1093// Native extension for .js
1094Module._extensions['.js'] = function(module, filename) {
1095  if (StringPrototypeEndsWith(filename, '.js')) {
1096    const pkg = readPackageScope(filename);
1097    // Function require shouldn't be used in ES modules.
1098    if (pkg && pkg.data && pkg.data.type === 'module') {
1099      const { parent } = module;
1100      const parentPath = parent && parent.filename;
1101      const packageJsonPath = path.resolve(pkg.path, 'package.json');
1102      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
1103    }
1104  }
1105  // If already analyzed the source, then it will be cached.
1106  const cached = cjsParseCache.get(module);
1107  let content;
1108  if (cached && cached.source) {
1109    content = cached.source;
1110    cached.source = undefined;
1111  } else {
1112    content = fs.readFileSync(filename, 'utf8');
1113  }
1114  module._compile(content, filename);
1115};
1116
1117
1118// Native extension for .json
1119Module._extensions['.json'] = function(module, filename) {
1120  const content = fs.readFileSync(filename, 'utf8');
1121
1122  if (policy?.manifest) {
1123    const moduleURL = pathToFileURL(filename);
1124    policy.manifest.assertIntegrity(moduleURL, content);
1125  }
1126
1127  try {
1128    module.exports = JSONParse(stripBOM(content));
1129  } catch (err) {
1130    err.message = filename + ': ' + err.message;
1131    throw err;
1132  }
1133};
1134
1135
1136// Native extension for .node
1137Module._extensions['.node'] = function(module, filename) {
1138  if (policy?.manifest) {
1139    const content = fs.readFileSync(filename);
1140    const moduleURL = pathToFileURL(filename);
1141    policy.manifest.assertIntegrity(moduleURL, content);
1142  }
1143  // Be aware this doesn't use `content`
1144  return process.dlopen(module, path.toNamespacedPath(filename));
1145};
1146
1147function createRequireFromPath(filename) {
1148  // Allow a directory to be passed as the filename
1149  const trailingSlash =
1150    StringPrototypeEndsWith(filename, '/') ||
1151    (isWindows && StringPrototypeEndsWith(filename, '\\'));
1152
1153  const proxyPath = trailingSlash ?
1154    path.join(filename, 'noop.js') :
1155    filename;
1156
1157  const m = new Module(proxyPath);
1158  m.filename = proxyPath;
1159
1160  m.paths = Module._nodeModulePaths(m.path);
1161  return makeRequireFunction(m, null);
1162}
1163
1164Module.createRequireFromPath = deprecate(
1165  createRequireFromPath,
1166  'Module.createRequireFromPath() is deprecated. ' +
1167  'Use Module.createRequire() instead.',
1168  'DEP0130'
1169);
1170
1171const createRequireError = 'must be a file URL object, file URL string, or ' +
1172  'absolute path string';
1173
1174function createRequire(filename) {
1175  let filepath;
1176
1177  if (isURLInstance(filename) ||
1178      (typeof filename === 'string' && !path.isAbsolute(filename))) {
1179    try {
1180      filepath = fileURLToPath(filename);
1181    } catch {
1182      throw new ERR_INVALID_ARG_VALUE('filename', filename,
1183                                      createRequireError);
1184    }
1185  } else if (typeof filename !== 'string') {
1186    throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError);
1187  } else {
1188    filepath = filename;
1189  }
1190  return createRequireFromPath(filepath);
1191}
1192
1193Module.createRequire = createRequire;
1194
1195Module._initPaths = function() {
1196  const homeDir = isWindows ? process.env.USERPROFILE : safeGetenv('HOME');
1197  const nodePath = isWindows ? process.env.NODE_PATH : safeGetenv('NODE_PATH');
1198
1199  // process.execPath is $PREFIX/bin/node except on Windows where it is
1200  // $PREFIX\node.exe where $PREFIX is the root of the Node.js installation.
1201  const prefixDir = isWindows ?
1202    path.resolve(process.execPath, '..') :
1203    path.resolve(process.execPath, '..', '..');
1204
1205  let paths = [path.resolve(prefixDir, 'lib', 'node')];
1206
1207  if (homeDir) {
1208    ArrayPrototypeUnshift(paths, path.resolve(homeDir, '.node_libraries'));
1209    ArrayPrototypeUnshift(paths, path.resolve(homeDir, '.node_modules'));
1210  }
1211
1212  if (nodePath) {
1213    paths = ArrayPrototypeConcat(ArrayPrototypeFilter(
1214      StringPrototypeSplit(nodePath, path.delimiter),
1215      Boolean
1216    ), paths);
1217  }
1218
1219  modulePaths = paths;
1220
1221  // Clone as a shallow copy, for introspection.
1222  Module.globalPaths = ArrayPrototypeSlice(modulePaths);
1223};
1224
1225Module._preloadModules = function(requests) {
1226  if (!ArrayIsArray(requests))
1227    return;
1228
1229  isPreloading = true;
1230
1231  // Preloaded modules have a dummy parent module which is deemed to exist
1232  // in the current working directory. This seeds the search path for
1233  // preloaded modules.
1234  const parent = new Module('internal/preload', null);
1235  try {
1236    parent.paths = Module._nodeModulePaths(process.cwd());
1237  } catch (e) {
1238    if (e.code !== 'ENOENT') {
1239      isPreloading = false;
1240      throw e;
1241    }
1242  }
1243  for (let n = 0; n < requests.length; n++)
1244    parent.require(requests[n]);
1245  isPreloading = false;
1246};
1247
1248Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
1249  for (const mod of NativeModule.map.values()) {
1250    if (mod.canBeRequiredByUsers) {
1251      mod.syncExports();
1252    }
1253  }
1254};
1255
1256// Backwards compatibility
1257Module.Module = Module;
1258