current commit
261011.7 · module: fix require of imports with package map
// 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 {
  ArrayIsArray,
  ArrayPrototypeFilter,
  ArrayPrototypeIncludes,
  ArrayPrototypeIndexOf,
  ArrayPrototypeJoin,
  ArrayPrototypeMap,
  ArrayPrototypePush,
  ArrayPrototypePushApply,
  ArrayPrototypeSlice,
  ArrayPrototypeSplice,
  ArrayPrototypeUnshift,
  ArrayPrototypeUnshiftApply,
  Boolean,
  Error,
  FunctionPrototypeCall,
  JSONParse,
  ObjectDefineProperty,
  ObjectFreeze,
  ObjectGetOwnPropertyDescriptor,
  ObjectGetPrototypeOf,
  ObjectHasOwn,
  ObjectKeys,
  ObjectPrototype,
  ObjectPrototypeHasOwnProperty,
  ObjectSetPrototypeOf,
  Proxy,
  ReflectSet,
  RegExpPrototypeExec,
  SafeMap,
  SafeSet,
  String,
  StringPrototypeCharAt,
  StringPrototypeCharCodeAt,
  StringPrototypeEndsWith,
  StringPrototypeIndexOf,
  StringPrototypeRepeat,
  StringPrototypeSlice,
  StringPrototypeSplit,
  StringPrototypeStartsWith,
  Symbol,
} = primordials;
const {
  privateSymbols: {
    module_source_private_symbol,
    module_export_names_private_symbol,
    module_circular_visited_private_symbol,
    module_export_private_symbol,
    module_first_parent_private_symbol,
    module_last_parent_private_symbol,
  },
  isInsideNodeModules,
} = internalBinding('util');

const { kEvaluated, createRequiredModuleFacade } = internalBinding('module_wrap');

// Internal properties for Module instances.
/**
 * Cached {@link Module} source string.
 */
const kModuleSource = module_source_private_symbol;
/**
 * Cached {@link Module} export names for ESM loader.
 */
const kModuleExportNames = module_export_names_private_symbol;
/**
 * {@link Module} circular dependency visited flag.
 */
const kModuleCircularVisited = module_circular_visited_private_symbol;
/**
 * {@link Module} export object snapshot for ESM loader.
 */
const kModuleExport = module_export_private_symbol;
/**
 * {@link Module} The first parent module that loads a module with require().
 */
const kFirstModuleParent = module_first_parent_private_symbol;
/**
 * {@link Module} The last parent module that loads a module with require().
 */
const kLastModuleParent = module_last_parent_private_symbol;

const kIsMainSymbol = Symbol('kIsMainSymbol');
const kIsCachedByESMLoader = Symbol('kIsCachedByESMLoader');
const kRequiredModuleSymbol = Symbol('kRequiredModuleSymbol');
const kIsExecuting = Symbol('kIsExecuting');

const kURL = Symbol('kURL');
const kFormat = Symbol('kFormat');

// Set first due to cycle with ESM loader functions.
module.exports = {
  purgeModuleCachesForPrefix,
  kModuleSource,
  kModuleExport,
  kModuleExportNames,
  kModuleCircularVisited,
  initializeCJS,
  Module,
  findLongestRegisteredExtension,
  resolveForCJSWithHooks,
  loadSourceForCJSWithHooks: loadSource,
  populateCJSExportsFromESM,
  wrapSafe,
  wrapModuleLoad,
  kIsMainSymbol,
  kIsCachedByESMLoader,
  kRequiredModuleSymbol,
  kIsExecuting,
};

const { BuiltinModule } = require('internal/bootstrap/realm');
const {
  maybeCacheSourceMap,
} = require('internal/source_map/source_map_cache');
const { pathToFileURL, fileURLToPath, isURL, URL } = require('internal/url');
const {
  pendingDeprecate,
  emitExperimentalWarning,
  kEmptyObject,
  setOwnProperty,
  getLazy,
  isWindows,
  isUnderNodeModules,
} = require('internal/util');
const {
  makeContextifyScript,
  runScriptInThisContext,
} = require('internal/vm');
const {
  containsModuleSyntax,
  compileFunctionForCJSLoader,
} = internalBinding('contextify');

const assert = require('internal/assert');
const path = require('path');
const { safeGetenv } = internalBinding('credentials');
const {
  cleanForVfsPrefix,
  getCjsConditions,
  getCjsConditionsArray,
  initializeCjsConditions,
  loaderMethods,
  loadBuiltinModule,
  makeRequireFunction,
  setHasStartedUserCJSExecution,
  stripBOM,
  getRequireStack,
} = require('internal/modules/helpers');
const {
  convertCJSFilenameToURL,
  convertURLToCJSFilename,
  loadHooks,
  loadWithHooks,
  registerHooks,
  resolveHooks,
  resolveWithHooks,
  validateLoadStrict,
} = require('internal/modules/customization_hooks');
const lazyTypeScript = getLazy(() => require('internal/modules/typescript'));
const packageJsonReader = require('internal/modules/package_json_reader');
const { getOptionValue, getEmbedderOptions } = require('internal/options');
const shouldReportRequiredModules = getLazy(() => process.env.WATCH_REPORT_DEPENDENCIES);

const {
  hasPackageMap,
  packageMapResolve,
} = require('internal/modules/package_map');

const {
  vm_dynamic_import_default_internal,
} = internalBinding('symbols');

const {
  codes: {
    ERR_INVALID_ARG_TYPE,
    ERR_INVALID_ARG_VALUE,
    ERR_INVALID_MODULE_SPECIFIER,
    ERR_REQUIRE_CYCLE_MODULE,
    ERR_REQUIRE_ESM,
    ERR_UNKNOWN_BUILTIN_MODULE,
    ERR_UNKNOWN_MODULE_FORMAT,
  },
  setArrowMessage,
} = require('internal/errors');
const { validateString } = require('internal/validators');

const {
  CHAR_BACKWARD_SLASH,
  CHAR_COLON,
  CHAR_DOT,
  CHAR_FORWARD_SLASH,
} = require('internal/constants');

const {
  isProxy,
} = require('internal/util/types');

const { debuglog, debugWithTimer } = require('internal/util/debuglog');

let { startTimer, endTimer } = debugWithTimer('module_timer', (start, end) => {
  startTimer = start;
  endTimer = end;
});

const { tracingChannel } = require('diagnostics_channel');
const onRequire = getLazy(() => tracingChannel('module.require'));

const relativeResolveCache = new SafeMap();

let requireDepth = 0;
let isPreloading = false;
let statCache = null;

/**
 * Internal method to add tracing capabilities for Module._load.
 *
 * See more {@link Module._load}
 * @returns {object}
 */
function wrapModuleLoad(request, parent, isMain, options) {
  const logLabel = `[${parent?.id || ''}] [${request}]`;
  const traceLabel = `require('${request}')`;
  const channel = onRequire();

  startTimer(logLabel, traceLabel);

  try {
    if (channel.hasSubscribers) {
      return onRequire().traceSync(Module._load, {
        __proto__: null,
        parentFilename: parent?.filename,
        id: request,
      }, Module, request, parent, isMain, options);
    }
    // No subscribers, skip the wrapping to avoid clobbering stack traces
    // and debugging steps.
    return Module._load(request, parent, isMain, options);
  } finally {
    endTimer(logLabel, traceLabel);
  }
}

/**
 * Get a path's properties, using an in-memory cache to minimize lookups.
 * @param {string} filename Absolute path to the file
 * @returns {number}
 */
function stat(filename) {
  // Guard against internal bugs where a non-string filename is passed in by mistake.
  assert(typeof filename === 'string');

  filename = path.toNamespacedPath(filename);
  if (statCache !== null) {
    const result = statCache.get(filename);
    if (result !== undefined) { return result; }
  }
  const result = loaderMethods.internalModuleStat(filename);
  if (statCache !== null && result >= 0) {
    // Only set cache when `internalModuleStat(filename)` succeeds.
    statCache.set(filename, result);
  }
  return result;
}

/**
 * Drop every module-loader cache entry (Module._cache,
 * Module._pathCache, the stat cache) whose filename lives under
 * `mountPoint`. Called by internal/vfs/setup.js when a VFS is
 * unmounted. VFS mount points live in a reserved namespace that
 * cannot collide with real paths, so a prefix scan is exact:
 * real-fs entries and other-VFS entries never match.
 * @param {string} mountPoint Absolute mount-point path
 */
function purgeModuleCachesForPrefix(mountPoint) {
  cleanForVfsPrefix(Module._cache, mountPoint);
  // Module._pathCache keys are `request\0parent` tokens; match on value.
  cleanForVfsPrefix(Module._pathCache, mountPoint, true);
  if (statCache !== null) { cleanForVfsPrefix(statCache, mountPoint); }
}

let _stat = stat;
ObjectDefineProperty(Module, '_stat', {
  __proto__: null,
  get() { return _stat; },
  set(stat) {
    emitExperimentalWarning('Module._stat');
    _stat = stat;
    return true;
  },
  configurable: true,
});

/**
 * Update the parent's children array with the child module.
 * @param {Module} parent Module requiring the children
 * @param {Module} child Module being required
 * @param {boolean} scan Add the child to the parent's children if not already present
 * @returns {void}
 */
function updateChildren(parent, child, scan) {
  const children = parent?.children;
  if (children && !(scan && ArrayPrototypeIncludes(children, child))) {
    ArrayPrototypePush(children, child);
  }
}

/**
 * Tell the watch mode that a module was required.
 * @param {string} filename Absolute path of the module
 * @returns {void}
 */
function reportModuleToWatchMode(filename) {
  if (shouldReportRequiredModules() && process.send) {
    process.send({ 'watch:require': [filename] });
  }
}

/**
 * Tell the watch mode that a module was not found.
 * @param {string} basePath The absolute path that errored
 * @param {string[]} extensions The extensions that were tried
 * @returns {void}
 */
function reportModuleNotFoundToWatchMode(basePath, extensions) {
  if (shouldReportRequiredModules() && process.send) {
    process.send({ 'watch:require': ArrayPrototypeMap(extensions, (ext) => path.resolve(`${basePath}${ext}`)) });
  }
}

/**
 * Tell the watch mode that a module was required, from within a worker thread.
 * @param {string} filename Absolute path of the module
 * @returns {void}
 */
function reportModuleToWatchModeFromWorker(filename) {
  if (!shouldReportRequiredModules()) {
    return;
  }
  const { isMainThread } = internalBinding('worker');
  if (isMainThread) {
    return;
  }
  // Lazy require to avoid circular dependency: worker_threads is loaded after
  // the CJS loader is fully set up.
  const { parentPort } = require('worker_threads');
  if (!parentPort) {
    return;
  }
  parentPort.postMessage({ 'watch:require': [filename] });
}

/**
 * Create a new module instance.
 * @param {string} id
 * @param {Module} parent
 * @returns {void}
 */
function Module(id = '', parent) {
  this.id = id;
  this.path = path.dirname(id);
  setOwnProperty(this, 'exports', {});
  this[kFirstModuleParent] = parent;
  this[kLastModuleParent] = parent;
  updateChildren(parent, this, false);
  this.filename = null;
  this.loaded = false;
  this.children = [];
}

/** @type {Record<string, Module>} */
Module._cache = { __proto__: null };
/** @type {Record<string, string>} */
Module._pathCache = { __proto__: null };
/** @type {{[key: string]: function(Module, string): void}} */
Module._extensions = { __proto__: null };
/** @type {string[]} */
let modulePaths = [];
/** @type {string[]} */
Module.globalPaths = [];

let patched = false;

/**
 * Add the CommonJS wrapper around a module's source code.
 * @param {string} script Module source code
 * @returns {string}
 */
let wrap = function(script) { // eslint-disable-line func-style
  return Module.wrapper[0] + script + Module.wrapper[1];
};

const wrapper = [
  '(function (exports, require, module, __filename, __dirname) { ',
  '\n});',
];

let wrapperProxy = new Proxy(wrapper, {
  __proto__: null,

  set(target, property, value, receiver) {
    patched = true;
    return ReflectSet(target, property, value, receiver);
  },

  defineProperty(target, property, descriptor) {
    patched = true;
    return ObjectDefineProperty(target, property, descriptor);
  },
});

ObjectDefineProperty(Module, 'wrap', {
  __proto__: null,
  get() {
    return wrap;
  },

  set(value) {
    patched = true;
    wrap = value;
  },
});

ObjectDefineProperty(Module, 'wrapper', {
  __proto__: null,
  get() {
    return wrapperProxy;
  },

  set(value) {
    patched = true;
    wrapperProxy = value;
  },
});

const isPreloadingDesc = { get() { return isPreloading; } };
ObjectDefineProperty(Module.prototype, 'isPreloading', isPreloadingDesc);
ObjectDefineProperty(BuiltinModule.prototype, 'isPreloading', isPreloadingDesc);

/**
 * Get the parent of the current module from our cache.
 * @this {Module}
 * @returns {object}
 */
function getModuleParent() {
  return this[kFirstModuleParent];
}

/**
 * Set the parent of the current module in our cache.
 * @this {Module}
 * @param {Module} value
 * @returns {void}
 */
function setModuleParent(value) {
  this[kFirstModuleParent] = value;
}

let debug = debuglog('module', (fn) => {
  debug = fn;
});

ObjectDefineProperty(Module.prototype, 'parent', {
  __proto__: null,
  get: pendingDeprecate(
    getModuleParent,
    'module.parent is deprecated due to accuracy issues. Please use ' +
      'require.main to find program entry point instead.',
    'DEP0144',
  ),
  set: pendingDeprecate(
    setModuleParent,
    'module.parent is deprecated due to accuracy issues. Please use ' +
      'require.main to find program entry point instead.',
    'DEP0144',
  ),
});
Module.isBuiltin = BuiltinModule.isBuiltin;

/**
 * Prepare to run CommonJS code.
 * This function is called during pre-execution, before any user code is run.
 * @returns {void}
 */
function initializeCJS() {
  // This need to be done at runtime in case --expose-internals is set.

  Module.builtinModules = ObjectFreeze(BuiltinModule.getAllBuiltinModuleIds());

  initializeCjsConditions();

  if (!getEmbedderOptions().noGlobalSearchPaths) {
    Module._initPaths();
  }

  // TODO(joyeecheung): deprecate this in favor of a proper hook?
  Module.runMain =
    require('internal/modules/run_main').executeUserEntryPoint;
}

// 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>

let _readPackage = (requestPath) => packageJsonReader.read(path.resolve(requestPath, 'package.json'));
ObjectDefineProperty(Module, '_readPackage', {
  __proto__: null,
  get() { return _readPackage; },
  set(readPackage) {
    emitExperimentalWarning('Module._readPackage');
    _readPackage = readPackage;
    return true;
  },
  configurable: true,
});

/**
 * Try to load a specifier as a package.
 * @param {string} requestPath The path to what we are trying to load
 * @param {string[]} exts File extensions to try appending in order to resolve the file
 * @param {boolean} isMain Whether the file is the main entry point of the app
 * @param {string} originalPath The specifier passed to `require`
 * @returns {any}
 */
function tryPackage(requestPath, exts, isMain, originalPath) {
  const { main: pkg, pjsonPath } = _readPackage(requestPath);

  if (!pkg) {
    return tryExtensions(path.resolve(requestPath, 'index'), exts, isMain);
  }

  const filename = path.resolve(requestPath, pkg);
  let actual = tryFile(filename, isMain) ||
    tryExtensions(filename, exts, isMain) ||
    tryExtensions(path.resolve(filename, 'index'), exts, isMain);
  if (actual === false) {
    actual = tryExtensions(path.resolve(requestPath, 'index'), exts, isMain);
    if (!actual) {
      // eslint-disable-next-line no-restricted-syntax
      const err = new Error(
        `Cannot find module '${filename}'. ` +
        'Please verify that the package.json has a valid "main" entry',
      );
      err.code = 'MODULE_NOT_FOUND';
      err.path = pjsonPath;
      err.requestPath = originalPath;
      // TODO(BridgeAR): Add the requireStack as well.
      throw err;
    } else {
      process.emitWarning(
        `Invalid 'main' field in '${pjsonPath}' of '${pkg}'. ` +
          'Please either fix that or report it to the module author',
        'DeprecationWarning',
        'DEP0128',
      );
    }
  }
  return actual;
}

/**
 * Check if the file exists and is not a directory if using `--preserve-symlinks` and `isMain` is false or
 * `--preserve-symlinks-main` and `isMain` is true , keep symlinks intact, otherwise resolve to the absolute realpath.
 * @param {string} requestPath The path to the file to load.
 * @param {boolean} isMain Whether the file is the main module.
 * @returns {string|undefined}
 */
function tryFile(requestPath, isMain) {
  const rc = _stat(requestPath);
  if (rc !== 0) { return; }
  if (getOptionValue(isMain ? '--preserve-symlinks-main' : '--preserve-symlinks')) {
    return path.resolve(requestPath);
  }
  return loaderMethods.realpathSync(requestPath);
}

/**
 * Given a path, check if the file exists with any of the set extensions.
 * @param {string} basePath The path and filename without extension
 * @param {string[]} exts The extensions to try
 * @param {boolean} isMain Whether the module is the main module
 * @returns {string|false}
 */
function tryExtensions(basePath, exts, isMain) {
  for (let i = 0; i < exts.length; i++) {
    const filename = tryFile(basePath + exts[i], isMain);

    if (filename) {
      return filename;
    }
  }
  return false;
}

/**
 * Find the longest (possibly multi-dot) extension registered in `Module._extensions`.
 * @param {string} filename The filename to find the longest registered extension for.
 * @returns {string}
 */
function findLongestRegisteredExtension(filename) {
  const name = path.basename(filename);
  let currentExtension;
  let index;
  let startIndex = 0;
  while ((index = StringPrototypeIndexOf(name, '.', startIndex)) !== -1) {
    startIndex = index + 1;
    if (index === 0) { continue; } // Skip dotfiles like .gitignore
    currentExtension = StringPrototypeSlice(name, index);
    if (Module._extensions[currentExtension]) { return currentExtension; }
  }
  return '.js';
}

/**
 * Tries to get the absolute file path of the parent module.
 * @param {Module} parent The parent module object.
 * @returns {string|false|void}
 */
function trySelfParentPath(parent) {
  if (!parent) { return false; }

  if (parent.filename) {
    return parent.filename;
  } else if (parent.id === '<repl>' || parent.id === 'internal/preload') {
    try {
      return process.cwd() + path.sep;
    } catch {
      return false;
    }
  }
}

/**
 * Attempt to resolve a module request using the parent module package metadata.
 * @param {string} parentPath The path of the parent module
 * @param {string} request The module request to resolve
 * @param {unknown} conditions
 * @returns {false|string}
 */
function trySelf(parentPath, request, conditions) {
  if (!parentPath) { return false; }

  const pkg = packageJsonReader.getNearestParentPackageJSON(parentPath);
  if (pkg?.data.exports === undefined || pkg.data.name === undefined) {
    return false;
  }

  let expansion;
  if (request === pkg.data.name) {
    expansion = '.';
  } else if (StringPrototypeStartsWith(request, `${pkg.data.name}/`)) {
    expansion = '.' + StringPrototypeSlice(request, pkg.data.name.length);
  } else {
    return false;
  }

  return resolveExpansion(expansion, pkg.path, pkg.data, parentPath, conditions);
}

/**
 * Try to resolve using package map (if enabled via --experimental-package-map).
 * @param {string} request - The bare specifier
 * @param {Module} parent - The parent module
 * @param {Set<string>} conditions - Export conditions
 * @returns {string|undefined}
 */
function tryPackageMapResolveCJS(request, parent, conditions) {
  if (!hasPackageMap()) { return undefined; }

  const parentPath = trySelfParentPath(parent);
  if (!parentPath) { return undefined; }

  const mapped = packageMapResolve(request, parentPath);
  if (mapped === undefined) {
    const requireStack = getRequireStack(parent);
    const message = getRequireStackMessage(request, requireStack);
    // eslint-disable-next-line no-restricted-syntax
    const err = new Error(message);
    setOwnProperty(err, 'code', 'MODULE_NOT_FOUND');
    setOwnProperty(err, 'requireStack', requireStack);
    throw err;
  }

  const { packagePath, subpath } = mapped;

  const packageJSONPath = path.resolve(packagePath, 'package.json');
  const pkg = packageJsonReader.read(packageJSONPath);
  if (pkg.exports !== undefined) {
    return resolveExpansion(subpath, packageJSONPath, pkg, parentPath, conditions);
  }

  // No exports - try standard path resolution within the package
  return Module._findPath(subpath, [packagePath], false, conditions);
}

function resolveExpansion(expansion, pkgJsonPath, pkgData, parentPath, conditions) {
  const pkgPath = path.dirname(pkgJsonPath);
  try {
    const { packageExportsResolve } = require('internal/modules/esm/resolve');
    return finalizeEsmResolution(packageExportsResolve(
      pathToFileURL(pkgJsonPath), expansion, pkgData,
      pathToFileURL(parentPath), conditions), parentPath, pkgPath);
  } catch (e) {
    if (e.code === 'ERR_MODULE_NOT_FOUND') {
      throw createEsmNotFoundErr(expansion, pkgPath);
    }
    throw e;
  }
}

/**
 * This only applies to requests of a specific form:
 * 1. `name/.*`
 * 2. `@scope/name/.*`
 */
const EXPORTS_PATTERN = /^((?:@[^/\\%]+\/)?[^./\\%][^/\\%]*)(\/.*)?$/;

/**
 * Resolves the exports for a given module path and request.
 * @param {string} nmPath The path to the module.
 * @param {string} request The request for the module.
 * @param {Set<string>} conditions The conditions to use for resolution.
 * @returns {undefined|string}
 */
function resolveExports(nmPath, request, conditions) {
  // The implementation's behavior is meant to mirror resolution in ESM.
  const { 1: name, 2: expansion = '' } =
    RegExpPrototypeExec(EXPORTS_PATTERN, request) || kEmptyObject;
  if (!name) { return; }
  const pkgPath = path.resolve(nmPath, name);
  const pkg = _readPackage(pkgPath);
  if (pkg.exists && pkg.exports != null) {
    try {
      const { packageExportsResolve } = require('internal/modules/esm/resolve');
      return finalizeEsmResolution(packageExportsResolve(
        pathToFileURL(pkgPath + '/package.json'), '.' + expansion, pkg, null,
        conditions), null, pkgPath);
    } catch (e) {
      if (e.code === 'ERR_MODULE_NOT_FOUND') {
        throw createEsmNotFoundErr(request, pkgPath + '/package.json');
      }
      throw e;
    }
  }
}

/**
 * Get the absolute path to a module.
 * @param {string} request Relative or absolute file path
 * @param {Array<string>} paths Folders to search as file paths
 * @param {boolean} isMain Whether the request is the main app entry point
 * @returns {string | false}
 */
Module._findPath = function(request, paths, isMain, conditions = getCjsConditions()) {
  const absoluteRequest = path.isAbsolute(request);
  if (absoluteRequest) {
    paths = [''];
  } else if (!paths || paths.length === 0) {
    return false;
  }

  const cacheKey = request + '\x00' + ArrayPrototypeJoin(paths, '\x00');
  const entry = Module._pathCache[cacheKey];
  if (entry) {
    return entry;
  }

  let exts;
  const trailingSlash = request.length > 0 &&
    (StringPrototypeCharCodeAt(request, request.length - 1) === CHAR_FORWARD_SLASH || (
      StringPrototypeCharCodeAt(request, request.length - 1) === CHAR_DOT &&
      (
        request.length === 1 ||
        StringPrototypeCharCodeAt(request, request.length - 2) === CHAR_FORWARD_SLASH ||
        (StringPrototypeCharCodeAt(request, request.length - 2) === CHAR_DOT && (
          request.length === 2 ||
          StringPrototypeCharCodeAt(request, request.length - 3) === CHAR_FORWARD_SLASH
        ))
      )
    ));

  let insidePath = true;
  if (isRelative(request)) {
    const normalizedRequest = path.normalize(request);
    if (StringPrototypeStartsWith(normalizedRequest, '..')) {
      insidePath = false;
    }
  }

  // For each path
  for (let i = 0; i < paths.length; i++) {
    // Don't search further if path doesn't exist
    const curPath = paths[i];
    if (typeof curPath !== 'string') {
      throw new ERR_INVALID_ARG_TYPE('paths', 'array of strings', paths);
    }
    if (insidePath && curPath && _stat(curPath) < 1) {
      continue;
    }

    if (!absoluteRequest) {
      const exportsResolved = resolveExports(curPath, request, conditions);
      if (exportsResolved) {
        return exportsResolved;
      }
    }

    const basePath = path.resolve(curPath, request);
    let filename;

    const rc = _stat(basePath);
    if (!trailingSlash) {
      if (rc === 0) {  // File.
        if (!isMain) {
          if (getOptionValue('--preserve-symlinks')) {
            filename = path.resolve(basePath);
          } else {
            filename = loaderMethods.realpathSync(basePath);
          }
        } else if (getOptionValue('--preserve-symlinks-main')) {
          // For the main module, we use the --preserve-symlinks-main flag instead
          // mainly for backward compatibility, as the preserveSymlinks flag
          // historically has not applied to the main module.  Most likely this
          // was intended to keep .bin/ binaries working, as following those
          // symlinks is usually required for the imports in the corresponding
          // files to resolve; that said, in some use cases following symlinks
          // causes bigger problems which is why the --preserve-symlinks-main option
          // is needed.
          filename = path.resolve(basePath);
        } else {
          filename = loaderMethods.realpathSync(basePath);
        }
      }

      if (!filename) {
        // Try it with each of the extensions
        if (exts === undefined) {
          exts = ObjectKeys(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 = ObjectKeys(Module._extensions);
      }
      filename = tryPackage(basePath, exts, isMain, request);
    }

    if (filename) {
      Module._pathCache[cacheKey] = filename;
      return filename;
    }

    const extensions = [''];
    if (exts !== undefined) {
      ArrayPrototypePushApply(extensions, exts);
    }
    reportModuleNotFoundToWatchMode(basePath, extensions);
  }

  return false;
};

/** `node_modules` character codes reversed */
const nmChars = [ 115, 101, 108, 117, 100, 111, 109, 95, 101, 100, 111, 110 ];
const nmLen = nmChars.length;
if (isWindows) {
  /**
   * Get the paths to the `node_modules` folder for a given path.
   * @param {string} from `__dirname` of the module
   * @returns {string[]}
   */
  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 (StringPrototypeCharCodeAt(from, from.length - 1) ===
          CHAR_BACKWARD_SLASH &&
        StringPrototypeCharCodeAt(from, from.length - 2) === CHAR_COLON) {
      return [from + 'node_modules'];
    }

    // The walk stops at the resolution root (e.g. a VFS mount point)
    // instead of continuing to the file system root.
    const resolutionRoot = loaderMethods.getResolutionRoot(from);
    const stopLen = resolutionRoot === undefined ? -1 : resolutionRoot.length;

    /** @type {string[]} */
    const paths = [];
    for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
      const code = StringPrototypeCharCodeAt(from, 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) {
          ArrayPrototypePush(
            paths,
            StringPrototypeSlice(from, 0, last) + '\\node_modules',
          );
        }
        if (last === stopLen) {
          return paths;
        }
        last = i;
        p = 0;
      } else if (p !== -1) {
        if (nmChars[p] === code) {
          ++p;
        } else {
          p = -1;
        }
      }
    }

    return paths;
  };
} else { // posix
  /**
   * Get the paths to the `node_modules` folder for a given path.
   * @param {string} from `__dirname` of the module
   * @returns {string[]}
   */
  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'];
    }

    // The walk stops at the resolution root (e.g. a VFS mount point)
    // instead of continuing to the file system root.
    const resolutionRoot = loaderMethods.getResolutionRoot(from);
    const stopLen = resolutionRoot === undefined ? -1 : resolutionRoot.length;

    // 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.
    /** @type {string[]} */
    const paths = [];
    for (let i = from.length - 1, p = 0, last = from.length; i >= 0; --i) {
      const code = StringPrototypeCharCodeAt(from, i);
      if (code === CHAR_FORWARD_SLASH) {
        if (p !== nmLen) {
          ArrayPrototypePush(
            paths,
            StringPrototypeSlice(from, 0, last) + '/node_modules',
          );
        }
        if (last === stopLen) {
          return paths;
        }
        last = i;
        p = 0;
      } else if (p !== -1) {
        if (nmChars[p] === code) {
          ++p;
        } else {
          p = -1;
        }
      }
    }

    // Append /node_modules to handle root paths.
    ArrayPrototypePush(paths, '/node_modules');

    return paths;
  };
}

/**
 * Get the paths for module resolution.
 * @param {string} request
 * @param {Module} parent
 * @returns {null|string[]}
 */
Module._resolveLookupPaths = function(request, parent) {
  if (BuiltinModule.normalizeRequirableId(request)) {
    debug('looking for %j in []', request);
    return null;
  }

  // Check for node modules paths.
  if (StringPrototypeCharAt(request, 0) !== '.' ||
      (request.length > 1 &&
      StringPrototypeCharAt(request, 1) !== '.' &&
      StringPrototypeCharAt(request, 1) !== '/' &&
      (!isWindows || StringPrototypeCharAt(request, 1) !== '\\'))) {

    /** @type {string[]} */
    let paths;
    if (parent?.paths?.length) {
      paths = ArrayPrototypeSlice(modulePaths);
      ArrayPrototypeUnshiftApply(paths, parent.paths);
    } else {
      paths = modulePaths;
    }

    debug('looking for %j in %j', request, paths);
    return paths.length > 0 ? paths : null;
  }

  // In REPL, 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 in REPL there is no filename
    const mainPaths = ['.'];

    debug('looking for %j in %j', request, mainPaths);
    return mainPaths;
  }

  debug('RELATIVE: requested: %s from parent.id %s', request, parent.id);

  const parentDir = [path.dirname(parent.filename)];
  debug('looking for %j', parentDir);
  return parentDir;
};

/**
 * Emits a warning when a non-existent property of module exports is accessed inside a circular dependency.
 * @param {string} prop The name of the non-existent property.
 * @returns {void}
 */
function emitCircularRequireWarning(prop) {
  process.emitWarning(
    `Accessing non-existent property '${String(prop)}' of module exports ` +
    'inside circular dependency',
  );
}

// A Proxy that can be used as the prototype of a module.exports object and
// warns when non-existent properties are accessed.
const CircularRequirePrototypeWarningProxy = new Proxy({}, {
  __proto__: null,

  get(target, prop) {
    // Allow __esModule access in any case because it is used in the output
    // of transpiled code to determine whether something comes from an
    // ES module, and is not used as a regular key of `module.exports`.
    if (prop in target || prop === '__esModule') { return target[prop]; }
    emitCircularRequireWarning(prop);
    return undefined;
  },

  getOwnPropertyDescriptor(target, prop) {
    if (ObjectPrototypeHasOwnProperty(target, prop) || prop === '__esModule') {
      return ObjectGetOwnPropertyDescriptor(target, prop);
    }
    emitCircularRequireWarning(prop);
    return undefined;
  },
});

/**
 * Returns the exports object for a module that has a circular `require`.
 * If the exports object is a plain object, it is wrapped in a proxy that warns
 * about circular dependencies.
 * @param {Module} module The module instance
 * @returns {object}
 */
function getExportsForCircularRequire(module) {
  const requiredESM = module[kRequiredModuleSymbol];
  if (requiredESM && requiredESM.getStatus() !== kEvaluated) {
    let message = `Cannot require() ES Module ${module.id} in a cycle.`;
    const parent = module[kLastModuleParent];
    if (parent) {
      message += ` (from ${parent.filename})`;
    }
    throw new ERR_REQUIRE_CYCLE_MODULE(message);
  }

  if (module.exports &&
      !isProxy(module.exports) &&
      ObjectGetPrototypeOf(module.exports) === ObjectPrototype &&
      // Exclude transpiled ES6 modules / TypeScript code because those may
      // employ unusual patterns for accessing 'module.exports'. That should
      // be okay because ES6 modules have a different approach to circular
      // dependencies anyway.
      !module.exports.__esModule) {
    // This is later unset once the module is done loading.
    ObjectSetPrototypeOf(
      module.exports, CircularRequirePrototypeWarningProxy);
  }

  return module.exports;
}


/**
 * Wraps result of Module._resolveFilename to include additional fields for hooks.
 * See resolveForCJSWithHooks.
 * @param {string} specifier
 * @param {Module|undefined} parent
 * @param {boolean} isMain
 * @param {ResolveFilenameOptions} options
 * @returns {{url?: string, format?: string, parentURL?: string, filename: string}}
 */
function wrapResolveFilename(specifier, parent, isMain, options) {
  const filename = Module._resolveFilename(specifier, parent, isMain, options).toString();
  return { __proto__: null, url: undefined, format: undefined, filename };
}

/**
 * See resolveForCJSWithHooks.
 * @param {string} specifier
 * @param {Module|undefined} parent
 * @param {boolean} isMain
 * @param {ResolveFilenameOptions} options
 * @returns {{url?: string, format?: string, parentURL?: string, filename: string}}
 */
function defaultResolveImplForCJSLoading(specifier, parent, isMain, options) {
  // For backwards compatibility, when encountering requests starting with node:,
  // throw ERR_UNKNOWN_BUILTIN_MODULE on failure or return the normalized ID on success
  // without going into Module._resolveFilename.
  let normalized;
  if (StringPrototypeStartsWith(specifier, 'node:')) {
    normalized = BuiltinModule.normalizeRequirableId(specifier);
    if (!normalized) {
      throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier);
    }
    return { __proto__: null, url: specifier, format: 'builtin', filename: normalized };
  }
  return wrapResolveFilename(specifier, parent, isMain, options);
}

/**
 * @typedef {{
 *   resolved?: {url?: string, format?: string, filename: string},
 *   shouldSkipModuleHooks?: boolean,
 *   source?: string|ArrayBufferView|ArrayBuffer,
 *   requireResolveOptions?: ResolveFilenameOptions,
 * }} CJSModuleLoadInternalOptions
 */

/**
 * Resolve a module request for CommonJS, invoking hooks from module.registerHooks()
 * if necessary.
 * @param {string} specifier
 * @param {Module|undefined} parent
 * @param {boolean} isMain
 * @param {CJSModuleLoadInternalOptions} internalOptions
 * @returns {{url?: string, format?: string, parentURL?: string, filename: string}}
 */
function resolveForCJSWithHooks(specifier, parent, isMain, internalOptions) {
  const { requireResolveOptions, shouldSkipModuleHooks } = internalOptions;
  const defaultResolveImpl = requireResolveOptions ?
    wrapResolveFilename : defaultResolveImplForCJSLoading;
  // Fast path: no hooks, just return simple results.
  if (!resolveHooks.length || shouldSkipModuleHooks) {
    return defaultResolveImpl(specifier, parent, isMain, requireResolveOptions);
  }

  // Slow path: has hooks, do the URL conversions and invoke hooks with contexts.
  let parentURL;
  if (parent) {
    if (!parent[kURL] && parent.filename) {
      parent[kURL] = convertCJSFilenameToURL(parent.filename);
    }
    parentURL = parent[kURL];
  }

  // This is used as the last nextResolve for the resolve hooks.
  function defaultResolve(specifier, context) {
    // TODO(joyeecheung): parent and isMain should be part of context, then we
    // no longer need to use a different defaultResolve for every resolution.
    // In the hooks, context.conditions is passed around as an array, but internally
    // the resolution helpers expect a SafeSet. Do the conversion here.
    let conditionSet;
    const conditions = context.conditions;
    if (conditions !== undefined && conditions !== getCjsConditionsArray()) {
      if (!ArrayIsArray(conditions)) {
        throw new ERR_INVALID_ARG_VALUE('context.conditions', conditions,
                                        'expected an array');
      }
      conditionSet = new SafeSet(conditions);
    } else {
      conditionSet = getCjsConditions();
    }

    const result = defaultResolveImpl(specifier, parent, isMain, {
      __proto__: null,
      paths: requireResolveOptions?.paths,
      conditions: conditionSet,
    });
    // If the default resolver does not return a URL, convert it for the public API.
    result.url ??= convertCJSFilenameToURL(result.filename);

    // Remove filename because it's not part of the public API.
    // TODO(joyeecheung): maybe expose it in the public API to avoid re-conversion for users too.
    return { __proto__: null, url: result.url, format: result.format };
  }

  const resolveResult = resolveWithHooks(specifier, parentURL, /* importAttributes */ undefined,
                                         getCjsConditionsArray(), defaultResolve);
  const { url, format } = resolveResult;
  // Convert the URL from the hook chain back to a filename for internal use.
  const filename = convertURLToCJSFilename(url);
  const result = { __proto__: null, url, format, filename, parentURL };
  debug('resolveForCJSWithHooks', specifier, parent?.id, isMain, shouldSkipModuleHooks, '->', result);
  return result;
}

/**
 * @typedef {import('internal/modules/customization_hooks').ModuleLoadContext} ModuleLoadContext
 * @typedef {import('internal/modules/customization_hooks').ModuleLoadResult} ModuleLoadResult
 */

/**
 * Load the source code of a module based on format.
 * @param {string} filename Filename of the module.
 * @param {string|undefined|null} format Format of the module.
 * @returns {string|null}
 */
function defaultLoadImpl(filename, format) {
  switch (format) {
    case undefined:
    case null:
    case 'module':
    case 'commonjs':
    case 'json':
    case 'module-typescript':
    case 'commonjs-typescript':
    case 'typescript': {
      return loaderMethods.readFileSync(filename, 'utf8');
    }
    case 'builtin':
      return null;
    default:
      // URL is not necessarily necessary/available - convert it on the spot for errors.
      throw new ERR_UNKNOWN_MODULE_FORMAT(format, convertCJSFilenameToURL(filename));
  }
}

/**
 * Construct a last nextLoad() for load hooks invoked for the CJS loader.
 * @param {string} url URL passed from the hook.
 * @param {string} filename Filename inferred from the URL.
 * @returns {(url: string, context: ModuleLoadContext) => ModuleLoadResult}
 */
function getDefaultLoad(url, filename) {
  return function defaultLoad(urlFromHook, context) {
    // If the url is the same as the original one, save the conversion.
    const isLoadingOriginalModule = (urlFromHook === url);
    const filenameFromHook = isLoadingOriginalModule ? filename : convertURLToCJSFilename(urlFromHook);
    const source = defaultLoadImpl(filenameFromHook, context.format);
    // Format from context is directly returned, because format detection should only be
    // done after the entire load chain is completed.
    return { source, format: context.format };
  };
}

/**
 * Load a specified builtin module, invoking load hooks if necessary.
 * @param {string} id The module ID (without the node: prefix)
 * @param {string} url The module URL (with the node: prefix)
 * @param {string} format Format from resolution.
 * @returns {{builtinExports: any, resultFromHook: undefined|ModuleLoadResult}} If there are no load
 *   hooks or the load hooks do not override the format of the builtin, load and return the exports
 *   of the builtin module. Otherwise, return the loadResult for the caller to continue loading.
 */
function loadBuiltinWithHooks(id, url, format) {
  let resultFromHook;
  if (loadHooks.length) {
    url ??= `node:${id}`;
    debug('loadBuiltinWithHooks ', loadHooks.length, id, url, format);
    // TODO(joyeecheung): do we really want to invoke the load hook for the builtins?
    resultFromHook = loadWithHooks(url, format || 'builtin', /* importAttributes */ undefined,
                                   getCjsConditionsArray(), getDefaultLoad(url, id), validateLoadStrict);
    if (resultFromHook.format && resultFromHook.format !== 'builtin') {
      debug('loadBuiltinWithHooks overriding module', id, url, resultFromHook);
      // Format has been overridden, return result for the caller to continue loading.
      return { builtinExports: undefined, resultFromHook };
    }
  }

  // No hooks or the hooks have not overridden the format. Load it as a builtin module and return the
  // exports.
  const mod = loadBuiltinModule(id);
  return { builtinExports: mod.exports, resultFromHook: undefined };
}

/**
 * Load a module from cache if it exists, otherwise create a new module instance.
 * 1. If a module already exists in the cache: return its exports object.
 * 2. If the module is native: call
 *    `BuiltinModule.prototype.compileForPublicLoader()` and return the exports.
 * 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.
 * @param {string} request Specifier of module to load via `require`
 * @param {Module} parent Absolute path of the module importing the child
 * @param {boolean} isMain Whether the module is the main entry point
 * @param {CJSModuleLoadInternalOptions|undefined} internalOptions Additional options for loading the module
 * @returns {object}
 */
Module._load = function(request, parent, isMain, internalOptions = kEmptyObject) {
  let parentPath;
  let relResolveCacheByDir;
  if (parent) {
    debug('Module._load REQUEST %s parent: %s', request, parent.id);
    // Fast path for (lazy loaded) modules in the same directory. Keyed by
    // parent directory and then request, so no concatenated cache key
    // string is allocated per require() call.
    parentPath = parent.path;
    relResolveCacheByDir = relativeResolveCache.get(parentPath);
    const filename = relResolveCacheByDir?.[request];
    if (filename !== undefined) {
      reportModuleToWatchMode(filename);
      reportModuleToWatchModeFromWorker(filename);
      const cachedModule = Module._cache[filename];
      if (cachedModule !== undefined) {
        updateChildren(parent, cachedModule, true);
        if (!cachedModule.loaded) {
          return getExportsForCircularRequire(cachedModule);
        }
        return cachedModule.exports;
      }
      delete relResolveCacheByDir[request];
    }
  }

  // If the module has been resolved by a short-circuiting synchronous resolve hook,
  // avoid running the default resolution from disk again.
  const resolveResult = internalOptions.resolved ??
    resolveForCJSWithHooks(request, parent, isMain, internalOptions);
  let { format } = resolveResult;
  const { url, filename } = resolveResult;

  let resultFromLoadHook;
  // For backwards compatibility, if the request itself starts with node:, load it before checking
  // Module._cache. Otherwise, load it after the check.
  // TODO(joyeecheung): a more sensible handling is probably, if there are hooks, always go through the hooks
  // first before checking the cache. Otherwise, check the cache first, then proceed to default loading.
  if (request === url && StringPrototypeStartsWith(request, 'node:')) {
    const normalized = BuiltinModule.normalizeRequirableId(request);
    if (normalized) {  // It's a builtin module.
      const { resultFromHook, builtinExports } = loadBuiltinWithHooks(normalized, url, format);
      if (builtinExports) {
        return builtinExports;
      }
      // The format of the builtin has been overridden by user hooks. Continue loading.
      resultFromLoadHook = resultFromHook;
      format = resultFromLoadHook.format;
    }
  }

  // If load hooks overrides the format for a built-in, bypass the cache.
  let cachedModule;
  if (resultFromLoadHook === undefined) {
    cachedModule = Module._cache[filename];
    debug('Module._load checking cache for', filename, !!cachedModule);
    if (cachedModule !== undefined) {
      updateChildren(parent, cachedModule, true);
      if (cachedModule.loaded) {
        return cachedModule.exports;
      }
      // If it's not cached by the ESM loader, the loading request
      // comes from required CJS, and we can consider it a circular
      // dependency when it's cached.
      if (!cachedModule[kIsCachedByESMLoader]) {
        return getExportsForCircularRequire(cachedModule);
      }
      // If it's cached by the ESM loader as a way to indirectly pass
      // the module in to avoid creating it twice, the loading request
      // came from imported CJS. In that case use the kModuleCircularVisited
      // to determine if it's loading or not.
      if (cachedModule[kModuleCircularVisited]) {
        return getExportsForCircularRequire(cachedModule);
      }
      // This is an ESM loader created cache entry, mark it as visited and fallthrough to loading the module.
      cachedModule[kModuleCircularVisited] = true;
    }
  }

  if (resultFromLoadHook === undefined && BuiltinModule.canBeRequiredWithoutScheme(filename)) {
    const { resultFromHook, builtinExports } = loadBuiltinWithHooks(filename, url, format);
    if (builtinExports) {
      return builtinExports;
    }
    // The format of the builtin has been overridden by user hooks. Continue loading.
    resultFromLoadHook = resultFromHook;
    format = resultFromLoadHook.format;
  }

  // Don't call updateChildren(), Module constructor already does.
  const module = cachedModule || new Module(filename, parent);

  if (!cachedModule) {
    if (isMain) {
      setOwnProperty(process, 'mainModule', module);
      setOwnProperty(module.require, 'main', process.mainModule);
      module.id = '.';
      module[kIsMainSymbol] = true;
    } else {
      module[kIsMainSymbol] = false;
    }
    if (resultFromLoadHook !== undefined) {
      module[kModuleSource] = resultFromLoadHook.source;
    }

    reportModuleToWatchMode(filename);
    reportModuleToWatchModeFromWorker(filename);
    Module._cache[filename] = module;
    module[kIsCachedByESMLoader] = false;
    // If there are resolve hooks, carry the context information into the
    // load hooks for the module keyed by the (potentially customized) filename.
    module[kURL] = url;
    module[kFormat] = format;
  } else {
    module[kLastModuleParent] = parent;
  }

  // The module source was provided by a short-circuiting synchronous hook,
  // assign them into the module to avoid triggering the default load step again.
  if (internalOptions.source !== undefined) {
    module[kModuleSource] ??= internalOptions.source;
    module[kURL] ??= url;
    module[kFormat] ??= format;
  }

  if (parent) {
    // Only create the per-directory bucket once there is an entry to store,
    // so builtins and failed resolutions don't leave empty buckets behind.
    if (relResolveCacheByDir === undefined) {
      // A plain object handles dynamically built specifier strings
      // better than a Map here.
      relResolveCacheByDir = { __proto__: null };
      relativeResolveCache.set(parentPath, relResolveCacheByDir);
    }
    relResolveCacheByDir[request] = filename;
  }

  let threw = true;
  try {
    module.load(filename);
    threw = false;
  } finally {
    if (threw) {
      delete Module._cache[filename];
      if (parent !== undefined) {
        if (relResolveCacheByDir !== undefined) {
          delete relResolveCacheByDir[request];
        }
        const children = parent?.children;
        if (ArrayIsArray(children)) {
          const index = ArrayPrototypeIndexOf(children, module);
          if (index !== -1) {
            ArrayPrototypeSplice(children, index, 1);
          }
        }
      }
    } else if (module.exports &&
               !isProxy(module.exports) &&
               ObjectGetPrototypeOf(module.exports) ===
                 CircularRequirePrototypeWarningProxy) {
      ObjectSetPrototypeOf(module.exports, ObjectPrototype);
    }
  }

  return module.exports;
};

/**
 * Given a `require` string and its context, get its absolute file path.
 * @param {string} request The specifier to resolve
 * @param {Module} parent The module containing the `require` call
 * @param {boolean} isMain Whether the module is the main entry point
 * @param {ResolveFilenameOptions} options Options object
 * @typedef {object} ResolveFilenameOptions
 * @property {string[]} paths Paths to search for modules in
 * @property {Set<string>?} conditions The conditions to use for resolution.
 * @returns {void|string}
 */
Module._resolveFilename = function(request, parent, isMain, options) {
  if (BuiltinModule.normalizeRequirableId(request)) {
    return request;
  }
  const conditions = (options?.conditions) || getCjsConditions();

  // Try package map resolution for bare specifiers (if --experimental-package-map is set)
  if (request[0] !== '#' && !isRelative(request) && !path.isAbsolute(request)) {
    const resolved = tryPackageMapResolveCJS(request, parent, conditions);
    if (resolved !== undefined) {
      return resolved;
    }
  }

  let paths;

  if (typeof options === 'object' && options !== null) {
    if (ArrayIsArray(options.paths)) {
      if (isRelative(request)) {
        paths = options.paths;
      } else {
        const fakeParent = new Module('', null);

        paths = [];

        for (let i = 0; i < options.paths.length; i++) {
          const path = options.paths[i];
          fakeParent.paths = Module._nodeModulePaths(path);
          const lookupPaths = Module._resolveLookupPaths(request, fakeParent);

          for (let j = 0; j < lookupPaths.length; j++) {
            if (!ArrayPrototypeIncludes(paths, lookupPaths[j])) {
              ArrayPrototypePush(paths, lookupPaths[j]);
            }
          }
        }
      }
    } else if (options.paths === undefined) {
      paths = Module._resolveLookupPaths(request, parent);
    } else {
      throw new ERR_INVALID_ARG_VALUE('options.paths', options.paths);
    }
  } else {
    paths = Module._resolveLookupPaths(request, parent);
  }

  const parentPath = trySelfParentPath(parent);

  if (request[0] === '#' && (parent.filename || parent.id === '<repl>')) {
    const pkg = packageJsonReader.getNearestParentPackageJSON(parentPath);
    if (pkg?.data.imports != null) {
      try {
        const { packageImportsResolve } = require('internal/modules/esm/resolve');
        return finalizeEsmResolution(
          packageImportsResolve(request, pathToFileURL(parentPath), conditions),
          parentPath,
          pkg.path,
        );
      } catch (e) {
        if (e.code === 'ERR_MODULE_NOT_FOUND') {
          throw createEsmNotFoundErr(request);
        }
        throw e;
      }
    }
  }

  // Try module self resolution first
  const selfResolved = trySelf(parentPath, request, conditions);
  if (selfResolved) {
    const cacheKey = request + '\x00' +
         (paths.length === 1 ? paths[0] : ArrayPrototypeJoin(paths, '\x00'));
    Module._pathCache[cacheKey] = selfResolved;
    return selfResolved;
  }

  // Look up the filename first, since that's the cache key.
  const filename = Module._findPath(request, paths, isMain, conditions);
  if (filename) { return filename; }

  const requireStack = getRequireStack(parent);
  const message = getRequireStackMessage(request, requireStack);

  // eslint-disable-next-line no-restricted-syntax
  const err = new Error(message);
  setOwnProperty(err, 'code', 'MODULE_NOT_FOUND');
  setOwnProperty(err, 'requireStack', requireStack);

  throw err;
};

function getRequireStackMessage(request, requireStack) {
  let message = `Cannot find module '${request}'`;
  if (requireStack.length > 0) {
    message = message + '\nRequire stack:\n- ' +
              ArrayPrototypeJoin(requireStack, '\n- ');
  }
  return message;
}

/**
 * Finishes resolving an ES module specifier into an absolute file path.
 * @param {string} resolved The resolved module specifier
 * @param {string} parentPath The path of the parent module
 * @param {string} pkgPath The path of the package.json file
 * @throws {ERR_INVALID_MODULE_SPECIFIER} If the resolved module specifier contains encoded `/` or `\\` characters
 * @throws {Error} If the module cannot be found
 * @returns {void|string|undefined}
 */
function finalizeEsmResolution(resolved, parentPath, pkgPath) {
  const { encodedSepRegEx } = require('internal/modules/esm/resolve');
  if (RegExpPrototypeExec(encodedSepRegEx, resolved) !== null) {
    throw new ERR_INVALID_MODULE_SPECIFIER(
      resolved, 'must not include encoded "/" or "\\" characters', parentPath);
  }
  const filename = fileURLToPath(resolved);
  const actual = tryFile(filename);
  if (actual) {
    return actual;
  }
  throw createEsmNotFoundErr(filename, pkgPath);
}

/**
 * Creates an error object for when a requested ES module cannot be found.
 * @param {string} request The name of the requested module
 * @param {string} [path] The path to the requested module
 * @returns {Error}
 */
function createEsmNotFoundErr(request, path) {
  // eslint-disable-next-line no-restricted-syntax
  const err = new Error(`Cannot find module '${request}'`);
  err.code = 'MODULE_NOT_FOUND';
  if (path) {
    err.path = path;
  }
  // TODO(BridgeAR): Add the requireStack as well.
  return err;
}

function getExtensionForFormat(format) {
  switch (format) {
    case 'addon':
      return '.node';
    case 'json':
      return '.json';
    default:
      return '.js';
  }
}

/**
 * Given a file name, pass it to the proper extension handler.
 * @param {string} filename The `require` specifier
 * @returns {void}
 */
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));

  // If the format is already overridden by hooks, convert that back to extension.
  let extension;
  if (this[kFormat] !== undefined) {
    extension = getExtensionForFormat(this[kFormat]);
  } else {
    extension = findLongestRegisteredExtension(filename);
  }

  Module._extensions[extension](this, filename);
  this.loaded = true;

  // Create module entry at load time to snapshot exports correctly
  const exports = this.exports;
  // Preemptively cache for ESM loader.
  this[kModuleExport] = exports;
};

/**
 * Loads a module at the given file path. Returns that module's `exports` property.
 * @param {string} id
 * @throws {ERR_INVALID_ARG_TYPE} When `id` is not a string
 * @returns {any}
 */
Module.prototype.require = function(id) {
  validateString(id, 'id');
  if (id === '') {
    throw new ERR_INVALID_ARG_VALUE('id', id,
                                    'must be a non-empty string');
  }
  requireDepth++;
  try {
    return wrapModuleLoad(id, this, /* isMain */ false);
  } finally {
    requireDepth--;
  }
};

let requireModuleWarningMode;
/**
 * Resolve and evaluate it synchronously as ESM if it's ESM.
 * @param {Module} mod CJS module instance
 * @param {string} filename Absolute path of the file.
 * @param {string} format Format of the module. If it had types, this would be what it is after type-stripping.
 * @param {string} source Source the module. If it had types, this would have the type stripped.
 */
function loadESMFromCJS(mod, filename, format, source) {
  const cascadedLoader = require('internal/modules/esm/loader').getOrInitializeCascadedLoader();
  const isMain = mod[kIsMainSymbol];
  if (isMain) {
    require('internal/modules/run_main').runEntryPointWithESMLoader((cascadedLoader) => {
      const mainURL = pathToFileURL(filename).href;
      return cascadedLoader.import(mainURL, undefined, { __proto__: null }, undefined, true);
    });
    // ESM won't be accessible via process.mainModule.
    setOwnProperty(process, 'mainModule', undefined);
  } else {
    const parent = mod[kLastModuleParent];

    requireModuleWarningMode ??= getOptionValue('--trace-require-module');
    if (requireModuleWarningMode) {
      let shouldEmitWarning = false;
      if (requireModuleWarningMode === 'no-node-modules') {
        // Check if the require() comes from node_modules.
        if (parent) {
          shouldEmitWarning = !isUnderNodeModules(parent.filename);
        } else if (mod[kIsCachedByESMLoader]) {
          // It comes from the require() built for `import cjs` and doesn't have a parent recorded
          // in the CJS module instance. Inspect the stack trace to see if the require()
          // comes from node_modules as a direct call and reduce the noise.
          shouldEmitWarning = !isInsideNodeModules();
        }
      } else {
        shouldEmitWarning = true;
      }
      if (shouldEmitWarning) {
        let messagePrefix;
        if (parent) {
          // In the case of the module calling `require()`, it's more useful to know its absolute path.
          let from = parent.filename || parent.id;
          // In the case of the module being require()d, it's more useful to know the id passed into require().
          const to = mod.id || mod.filename;
          if (from === 'internal/preload') {
            from = '--require';
          } else if (from === '<repl>') {
            from = 'The REPL';
          } else if (from === '.') {
            from = 'The entry point';
          } else {
            from &&= `CommonJS module ${from}`;
          }
          if (from && to) {
            messagePrefix = `${from} is loading ES Module ${to} using require().\n`;
          }
        }
        emitExperimentalWarning('Support for loading ES Module in require()',
                                messagePrefix,
                                undefined,
                                parent?.require);
        requireModuleWarningMode = true;
      }
    }
    const {
      wrap,
      namespace,
    } = cascadedLoader.importSyncForRequire(mod, filename, source, isMain, parent);

    populateCJSExportsFromESM(mod, wrap, namespace);
  }
}

/**
 * Populate the exports of a CJS module entry from an ESM module's namespace object for
 * require(esm).
 * @param {Module} mod CJS module instance
 * @param {ModuleWrap} wrap ESM ModuleWrap instance.
 * @param {object} namespace The ESM namespace object.
 */
function populateCJSExportsFromESM(mod, wrap, namespace) {
  // Tooling in the ecosystem have been using the __esModule property to recognize
  // transpiled ESM in consuming code. For example, a 'log' package written in ESM:
  //
  // export default function log(val) { console.log(val); }
  //
  // Can be transpiled as:
  //
  // exports.__esModule = true;
  // exports.default = function log(val) { console.log(val); }
  //
  // The consuming code may be written like this in ESM:
  //
  // import log from 'log'
  //
  // Which gets transpiled to:
  //
  // const _mod = require('log');
  // const log = _mod.__esModule ? _mod.default : _mod;
  //
  // So to allow transpiled consuming code to recognize require()'d real ESM
  // as ESM and pick up the default exports, we add a __esModule property by
  // building a source text module facade for any module that has a default
  // export and add .__esModule = true to the exports. This maintains the
  // enumerability of the re-exported names and the live binding of the exports,
  // without incurring a non-trivial per-access overhead on the exports.
  //
  // The source of the facade is defined as a constant per-isolate property
  // required_module_default_facade_source_string, which looks like this
  //
  // export * from 'original';
  // export { default } from 'original';
  // export const __esModule = true;
  //
  // And the 'original' module request is always resolved by
  // createRequiredModuleFacade() to `wrap` which is a ModuleWrap wrapping
  // over the original module.

  // We don't do this to modules that are marked as CJS ESM or that
  // don't have default exports to avoid the unnecessary overhead.
  // If __esModule is already defined, we will also skip the extension
  // to allow users to override it.
  if (ObjectHasOwn(namespace, 'module.exports')) {
    mod.exports = namespace['module.exports'];
  } else if (!ObjectHasOwn(namespace, 'default') || ObjectHasOwn(namespace, '__esModule')) {
    mod.exports = namespace;
  } else {
    mod.exports = createRequiredModuleFacade(wrap);
  }
}

/**
 * Wraps the given content in a script and runs it in a new context.
 * @param {string} filename The name of the file being loaded
 * @param {string} content The content of the file being loaded
 * @param {Module|undefined} cjsModuleInstance The CommonJS loader instance
 * @param {'commonjs'|undefined} format Intended format of the module.
 * @returns {object}
 */
function wrapSafe(filename, content, cjsModuleInstance, format) {
  assert(format !== 'module', 'ESM should be handled in loadESMFromCJS()');
  const hostDefinedOptionId = vm_dynamic_import_default_internal;
  const importModuleDynamically = vm_dynamic_import_default_internal;
  if (patched) {
    const wrapped = Module.wrap(content);
    const script = makeContextifyScript(
      wrapped,                 // code
      filename,                // filename
      0,                       // lineOffset
      0,                       // columnOffset
      undefined,               // cachedData
      false,                   // produceCachedData
      undefined,               // parsingContext
      hostDefinedOptionId,     // hostDefinedOptionId
      importModuleDynamically, // importModuleDynamically
    );

    // Cache the source map for the module if present.
    const { sourceMapURL, sourceURL } = script;
    if (sourceMapURL) {
      maybeCacheSourceMap(filename, content, cjsModuleInstance, false, sourceURL, sourceMapURL);
    }

    return {
      __proto__: null,
      function: runScriptInThisContext(script, true, false),
      sourceMapURL,
    };
  }

  let shouldDetectModule = false;
  if (format !== 'commonjs') {
    if (cjsModuleInstance?.[kIsMainSymbol]) {
      // For entry points, format detection is used unless explicitly disabled.
      shouldDetectModule = getOptionValue('--experimental-detect-module');
    } else {
      // For modules being loaded by `require()`, if require(esm) is disabled,
      // don't try to reparse to detect format and just throw for ESM syntax.
      shouldDetectModule = getOptionValue('--require-module');
    }
  }
  const result = compileFunctionForCJSLoader(content, filename, false /* is_sea_main */, shouldDetectModule);

  // Cache the source map for the module if present.
  if (result.sourceMapURL) {
    maybeCacheSourceMap(filename, content, cjsModuleInstance, false, result.sourceURL, result.sourceMapURL);
  }

  return result;
}

/**
 * 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.
 * @param {string} content The source code of the module
 * @param {string} filename The file path of the module
 * @param {'module'|'commonjs'|'commonjs-typescript'|'module-typescript'|'typescript'} format
 *   Intended format of the module.
 * @returns {any}
 */
Module.prototype._compile = function(content, filename, format) {
  if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') {
    this[kURL] ??= convertCJSFilenameToURL(filename);
    content = lazyTypeScript().stripTypeScriptModuleTypes(content, filename, this[kURL]);
    switch (format) {
      case 'commonjs-typescript': {
        format = 'commonjs';
        break;
      }
      case 'module-typescript': {
        format = 'module';
        break;
      }
      // If the format is still unknown i.e. 'typescript', detect it in
      // wrapSafe using the type-stripped source.
      default:
        format = undefined;
        break;
    }
  }

  let compiledWrapper;
  if (format !== 'module') {
    const result = wrapSafe(filename, content, this, format);
    compiledWrapper = result.function;
    if (result.canParseAsESM) {
      format = 'module';
    }
  }

  if (format === 'module') {
    loadESMFromCJS(this, filename, format, content);
    return;
  }

  const dirname = path.dirname(filename);
  const require = makeRequireFunction(this);
  let result;
  const exports = this.exports;
  const thisValue = exports;
  const module = this;
  if (requireDepth === 0) { statCache = new SafeMap(); }
  setHasStartedUserCJSExecution();
  this[kIsExecuting] = true;
  if (this[kIsMainSymbol] && getOptionValue('--inspect-brk')) {
    const { callAndPauseOnStart } = internalBinding('inspector');
    result = callAndPauseOnStart(compiledWrapper, thisValue, exports,
                                 require, module, filename, dirname);
  } else {
    result = FunctionPrototypeCall(compiledWrapper, thisValue, exports, require, module, filename, dirname);
  }
  this[kIsExecuting] = false;
  if (requireDepth === 0) { statCache = null; }
  return result;
};

/**
 * Get the source code of a module, using cached ones if it's cached. This is used
 * for TypeScript, JavaScript and JSON loading.
 * After this returns, mod[kFormat], mod[kModuleSource] and mod[kURL] will be set.
 * @param {Module} mod Module instance whose source is potentially already cached.
 * @param {string} filename Absolute path to the file of the module.
 * @returns {{source: string, format?: string}}
 */
function loadSource(mod, filename, formatFromNode) {
  if (mod[kFormat] === undefined) {
    mod[kFormat] = formatFromNode;
  }
  // If the module was loaded before, just return.
  if (mod[kModuleSource] !== undefined) {
    return { source: mod[kModuleSource], format: mod[kFormat] };
  }

  // Fast path: no hooks, just load it and return.
  if (!loadHooks.length) {
    const source = defaultLoadImpl(filename, formatFromNode);
    return { source, format: formatFromNode };
  }

  if (mod[kURL] === undefined) {
    mod[kURL] = convertCJSFilenameToURL(filename);
  }

  const defaultLoad = getDefaultLoad(mod[kURL], filename);
  const loadResult = loadWithHooks(mod[kURL], mod[kFormat], /* importAttributes */ undefined,
                                   getCjsConditionsArray(), defaultLoad, validateLoadStrict);
  // Reset the module properties with load hook results.
  if (loadResult.format !== undefined) {
    mod[kFormat] = loadResult.format;
  }
  mod[kModuleSource] = loadResult.source;
  return { source: mod[kModuleSource], format: mod[kFormat] };
}

function reconstructErrorStack(err, parentPath, parentSource) {
  const errLine = StringPrototypeSplit(
    StringPrototypeSlice(err.stack, StringPrototypeIndexOf(
      err.stack, '    at ')), '\n', 1)[0];
  const { 1: line, 2: col } =
    RegExpPrototypeExec(/(\d+):(\d+)\)/, errLine) || [];
  if (line && col) {
    const srcLine = StringPrototypeSplit(parentSource, '\n', line)[line - 1];
    const frame = `${parentPath}:${line}\n${srcLine}\n${StringPrototypeRepeat(' ', col - 1)}^\n`;
    setArrowMessage(err, frame);
  }
}

/**
 * Generate the legacy ERR_REQUIRE_ESM for the cases where require(esm) is disabled.
 * @param {Module} mod The module being required.
 * @param {undefined|object} pkg Data of the nearest package.json of the module.
 * @param {string} content Source code of the module.
 * @param {string} filename Filename of the module
 * @returns {Error}
 */
function getRequireESMError(mod, pkg, content, filename) {
  // This is an error path because `require` of a `.js` file in a `"type": "module"` scope is not allowed.
  const parent = mod[kFirstModuleParent];
  const parentPath = parent?.filename;
  const packageJsonPath = pkg?.path;
  const usesEsm = containsModuleSyntax(content, filename);
  const err = new ERR_REQUIRE_ESM(filename, usesEsm, parentPath,
                                  packageJsonPath);
  // Attempt to reconstruct the parent require frame.
  const parentModule = Module._cache[parentPath];
  if (parentModule) {
    let parentSource;
    try {
      ({ source: parentSource } = loadSource(parentModule, parentPath));
    } catch {
      // Continue regardless of error.
    }
    if (parentSource) {
      // TODO(joyeecheung): trim off internal frames from the stack.
      reconstructErrorStack(err, parentPath, parentSource);
    }
  }
  return err;
}

/**
 * Built-in handler for `.js` files.
 * @param {Module} module The module to compile
 * @param {string} filename The file path of the module
 */
Module._extensions['.js'] = function(module, filename) {
  let format, pkg;
  const tsEnabled = getOptionValue('--strip-types');
  if (StringPrototypeEndsWith(filename, '.cjs')) {
    format = 'commonjs';
  } else if (StringPrototypeEndsWith(filename, '.mjs')) {
    format = 'module';
  } else if (StringPrototypeEndsWith(filename, '.js')) {
    pkg = packageJsonReader.getNearestParentPackageJSON(filename);
    const typeFromPjson = pkg?.data.type;
    if (typeFromPjson === 'module' || typeFromPjson === 'commonjs' || !typeFromPjson) {
      format = typeFromPjson;
    }
  } else if (StringPrototypeEndsWith(filename, '.mts') && tsEnabled) {
    format = 'module-typescript';
  } else if (StringPrototypeEndsWith(filename, '.cts') && tsEnabled) {
    format = 'commonjs-typescript';
  } else if (StringPrototypeEndsWith(filename, '.ts') && tsEnabled) {
    pkg = packageJsonReader.getNearestParentPackageJSON(filename);
    const typeFromPjson = pkg?.data.type;
    if (typeFromPjson === 'module') {
      format = 'module-typescript';
    } else if (typeFromPjson === 'commonjs') {
      format = 'commonjs-typescript';
    } else {
      format = 'typescript';
    }
  } else if (path.extname(filename) === '') {
    // Extensionless files skip the .js suffix check above. When type is explicit,
    // follow it so ESM syntax surfaces as SyntaxError for commonjs instead of
    // silently delegating to ESM.
    pkg = packageJsonReader.getNearestParentPackageJSON(filename);
    const typeFromPjson = pkg?.data?.type;
    if (typeFromPjson === 'commonjs' || typeFromPjson === 'module') {
      format = typeFromPjson;
    }
  }
  const { source, format: loadedFormat } = loadSource(module, filename, format);
  // Function require shouldn't be used in ES modules when require(esm) is disabled.
  if ((loadedFormat === 'module' || loadedFormat === 'module-typescript') &&
    !getOptionValue('--require-module')) {
    const err = getRequireESMError(module, pkg, source, filename);
    throw err;
  }
  module._compile(source, filename, loadedFormat);
};

/**
 * Native handler for `.json` files.
 * @param {Module} module The module to compile
 * @param {string} filename The file path of the module
 */
Module._extensions['.json'] = function(module, filename) {
  const { source: content } = loadSource(module, filename, 'json');

  try {
    setOwnProperty(module, 'exports', JSONParse(stripBOM(content)));
  } catch (err) {
    err.message = filename + ': ' + err.message;
    throw err;
  }
};

/**
 * Native handler for `.node` files.
 * @param {Module} module The module to compile
 * @param {string} filename The file path of the module
 * @returns {any}
 */
Module._extensions['.node'] = function(module, filename) {
  // Be aware this doesn't use `content`
  return process.dlopen(module, path.toNamespacedPath(filename));
};

/**
 * Creates a `require` function that can be used to load modules from the specified path.
 * @param {string} filename The path to the module
 * @returns {any}
 */
function createRequireFromPath(filename, fileURL) {
  // Allow a directory to be passed as the filename
  const trailingSlash =
    StringPrototypeEndsWith(filename, '/') ||
    (isWindows && StringPrototypeEndsWith(filename, '\\'));

  const proxyPath = trailingSlash ?
    path.join(filename, 'noop.js') :
    filename;

  const m = new Module(proxyPath);
  m.filename = proxyPath;
  if (fileURL !== undefined) {
    // Save the URL if createRequire() was given a URL, to preserve search params, if any.
    m[kURL] = fileURL.href;
  }

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

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

/**
 * Creates a new `require` function that can be used to load modules.
 * @param {string | URL} filenameOrURL The path or URL to the module context for this `require`
 * @throws {ERR_INVALID_ARG_VALUE} If `filename` is not a string or URL, or if it is a relative path that cannot be
 * resolved to an absolute path.
 * @returns {object}
 */
function createRequire(filenameOrURL) {
  let filepath, fileURL;

  if (isURL(filenameOrURL) ||
      (typeof filenameOrURL === 'string' && !path.isAbsolute(filenameOrURL))) {
    try {
      // It might be an URL, try to convert it.
      // If it's a relative path, it would not parse and would be considered invalid per
      // the documented contract.
      fileURL = new URL(filenameOrURL);
      filepath = fileURLToPath(fileURL);
    } catch {
      throw new ERR_INVALID_ARG_VALUE('filename', filenameOrURL,
                                      createRequireError);
    }
  } else if (typeof filenameOrURL !== 'string') {
    throw new ERR_INVALID_ARG_VALUE('filename', filenameOrURL, createRequireError);
  } else {
    filepath = filenameOrURL;
  }
  return createRequireFromPath(filepath, fileURL);
}

/**
 * Checks if a path is relative
 * @param {string} path the target path
 * @returns {boolean} true if the path is relative, false otherwise
 */
function isRelative(path) {
  if (StringPrototypeCharCodeAt(path, 0) !== CHAR_DOT) { return false; }

  return path.length === 1 || path === '..' ||
  StringPrototypeStartsWith(path, './') ||
  StringPrototypeStartsWith(path, '../') ||
  ((isWindows && StringPrototypeStartsWith(path, '.\\')) ||
  StringPrototypeStartsWith(path, '..\\'));
}

Module.createRequire = createRequire;

/**
 * Define the paths to use for resolving a module.
 */
Module._initPaths = function() {
  const homeDir = isWindows ? process.env.USERPROFILE : safeGetenv('HOME');
  const nodePath = isWindows ? process.env.NODE_PATH : safeGetenv('NODE_PATH');

  // process.execPath is $PREFIX/bin/node except on Windows where it is
  // $PREFIX\node.exe where $PREFIX is the root of the Node.js installation.
  const prefixDir = isWindows ?
    path.resolve(process.execPath, '..') :
    path.resolve(process.execPath, '..', '..');

  const paths = [path.resolve(prefixDir, 'lib', 'node')];

  if (homeDir) {
    ArrayPrototypeUnshift(paths, path.resolve(homeDir, '.node_libraries'));
    ArrayPrototypeUnshift(paths, path.resolve(homeDir, '.node_modules'));
  }

  if (nodePath) {
    ArrayPrototypeUnshiftApply(paths, ArrayPrototypeFilter(
      StringPrototypeSplit(nodePath, path.delimiter),
      Boolean,
    ));
  }

  modulePaths = paths;

  // Clone as a shallow copy, for introspection.
  Module.globalPaths = ArrayPrototypeSlice(modulePaths);
};

/**
 * Handle modules loaded via `--require`.
 * @param {string[]} requests The values of `--require`
 */
Module._preloadModules = function(requests) {
  if (!ArrayIsArray(requests)) { return; }

  isPreloading = true;

  // 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.
  const parent = new Module('internal/preload', null);
  try {
    parent.paths = Module._nodeModulePaths(process.cwd());
  } catch (e) {
    if (e.code !== 'ENOENT') {
      isPreloading = false;
      throw e;
    }
  }
  for (let n = 0; n < requests.length; n++) {
    parent.require(requests[n]);
  }
  isPreloading = false;
};

/**
 * If the user has overridden an export from a builtin module, this function can ensure that the override is used in
 * both CommonJS and ES module contexts.
 */
Module.syncBuiltinESMExports = function syncBuiltinESMExports() {
  for (const mod of BuiltinModule.map.values()) {
    if (BuiltinModule.canBeRequiredWithoutScheme(mod.id)) {
      mod.syncExports();
    }
  }
};

ObjectDefineProperty(Module.prototype, 'constructor', {
  __proto__: null,
  get: function() {
    return Module;
  },
  configurable: false,
  enumerable: false,
});

// Backwards compatibility
Module.Module = Module;
Module.registerHooks = registerHooks;