11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayPrototypeForEach,
51cb0ef41Sopenharmony_ci  ArrayPrototypeJoin,
61cb0ef41Sopenharmony_ci  ArrayPrototypeSome,
71cb0ef41Sopenharmony_ci  ObjectDefineProperty,
81cb0ef41Sopenharmony_ci  ObjectPrototypeHasOwnProperty,
91cb0ef41Sopenharmony_ci  SafeMap,
101cb0ef41Sopenharmony_ci  SafeSet,
111cb0ef41Sopenharmony_ci  StringPrototypeCharCodeAt,
121cb0ef41Sopenharmony_ci  StringPrototypeIncludes,
131cb0ef41Sopenharmony_ci  StringPrototypeSlice,
141cb0ef41Sopenharmony_ci  StringPrototypeStartsWith,
151cb0ef41Sopenharmony_ci} = primordials;
161cb0ef41Sopenharmony_ciconst {
171cb0ef41Sopenharmony_ci  ERR_INVALID_ARG_TYPE,
181cb0ef41Sopenharmony_ci  ERR_MANIFEST_DEPENDENCY_MISSING,
191cb0ef41Sopenharmony_ci  ERR_UNKNOWN_BUILTIN_MODULE,
201cb0ef41Sopenharmony_ci} = require('internal/errors').codes;
211cb0ef41Sopenharmony_ciconst { BuiltinModule } = require('internal/bootstrap/realm');
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciconst { validateString } = require('internal/validators');
241cb0ef41Sopenharmony_ciconst fs = require('fs'); // Import all of `fs` so that it can be monkey-patched.
251cb0ef41Sopenharmony_ciconst internalFS = require('internal/fs/utils');
261cb0ef41Sopenharmony_ciconst path = require('path');
271cb0ef41Sopenharmony_ciconst { pathToFileURL, fileURLToPath, URL } = require('internal/url');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options');
301cb0ef41Sopenharmony_ciconst { setOwnProperty } = require('internal/util');
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ciconst {
331cb0ef41Sopenharmony_ci  privateSymbols: {
341cb0ef41Sopenharmony_ci    require_private_symbol,
351cb0ef41Sopenharmony_ci  },
361cb0ef41Sopenharmony_ci} = internalBinding('util');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cilet debug = require('internal/util/debuglog').debuglog('module', (fn) => {
391cb0ef41Sopenharmony_ci  debug = fn;
401cb0ef41Sopenharmony_ci});
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci/** @typedef {import('internal/modules/cjs/loader.js').Module} Module */
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci/**
451cb0ef41Sopenharmony_ci * Cache for storing resolved real paths of modules.
461cb0ef41Sopenharmony_ci * In order to minimize unnecessary lstat() calls, this cache is a list of known-real paths.
471cb0ef41Sopenharmony_ci * Set to an empty Map to reset.
481cb0ef41Sopenharmony_ci * @type {Map<string, string>}
491cb0ef41Sopenharmony_ci */
501cb0ef41Sopenharmony_ciconst realpathCache = new SafeMap();
511cb0ef41Sopenharmony_ci/**
521cb0ef41Sopenharmony_ci * Resolves the path of a given `require` specifier, following symlinks.
531cb0ef41Sopenharmony_ci * @param {string} requestPath The `require` specifier
541cb0ef41Sopenharmony_ci */
551cb0ef41Sopenharmony_cifunction toRealPath(requestPath) {
561cb0ef41Sopenharmony_ci  return fs.realpathSync(requestPath, {
571cb0ef41Sopenharmony_ci    [internalFS.realpathCacheKey]: realpathCache,
581cb0ef41Sopenharmony_ci  });
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci/** @type {Set<string>} */
621cb0ef41Sopenharmony_cilet cjsConditions;
631cb0ef41Sopenharmony_ci/**
641cb0ef41Sopenharmony_ci * Define the conditions that apply to the CommonJS loader.
651cb0ef41Sopenharmony_ci */
661cb0ef41Sopenharmony_cifunction initializeCjsConditions() {
671cb0ef41Sopenharmony_ci  const userConditions = getOptionValue('--conditions');
681cb0ef41Sopenharmony_ci  const noAddons = getOptionValue('--no-addons');
691cb0ef41Sopenharmony_ci  const addonConditions = noAddons ? [] : ['node-addons'];
701cb0ef41Sopenharmony_ci  // TODO: Use this set when resolving pkg#exports conditions in loader.js.
711cb0ef41Sopenharmony_ci  cjsConditions = new SafeSet([
721cb0ef41Sopenharmony_ci    'require',
731cb0ef41Sopenharmony_ci    'node',
741cb0ef41Sopenharmony_ci    ...addonConditions,
751cb0ef41Sopenharmony_ci    ...userConditions,
761cb0ef41Sopenharmony_ci  ]);
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci/**
801cb0ef41Sopenharmony_ci * Get the conditions that apply to the CommonJS loader.
811cb0ef41Sopenharmony_ci */
821cb0ef41Sopenharmony_cifunction getCjsConditions() {
831cb0ef41Sopenharmony_ci  if (cjsConditions === undefined) {
841cb0ef41Sopenharmony_ci    initializeCjsConditions();
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci  return cjsConditions;
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci/**
901cb0ef41Sopenharmony_ci * Provide one of Node.js' public modules to user code.
911cb0ef41Sopenharmony_ci * @param {string} id - The identifier/specifier of the builtin module to load
921cb0ef41Sopenharmony_ci * @param {string} request - The module requiring or importing the builtin module
931cb0ef41Sopenharmony_ci */
941cb0ef41Sopenharmony_cifunction loadBuiltinModule(id, request) {
951cb0ef41Sopenharmony_ci  if (!BuiltinModule.canBeRequiredByUsers(id)) {
961cb0ef41Sopenharmony_ci    return;
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  /** @type {import('internal/bootstrap/realm.js').BuiltinModule} */
991cb0ef41Sopenharmony_ci  const mod = BuiltinModule.map.get(id);
1001cb0ef41Sopenharmony_ci  debug('load built-in module %s', request);
1011cb0ef41Sopenharmony_ci  // compileForPublicLoader() throws if canBeRequiredByUsers is false:
1021cb0ef41Sopenharmony_ci  mod.compileForPublicLoader();
1031cb0ef41Sopenharmony_ci  return mod;
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci/** @type {Module} */
1071cb0ef41Sopenharmony_cilet $Module = null;
1081cb0ef41Sopenharmony_ci/**
1091cb0ef41Sopenharmony_ci * Import the Module class on first use.
1101cb0ef41Sopenharmony_ci */
1111cb0ef41Sopenharmony_cifunction lazyModule() {
1121cb0ef41Sopenharmony_ci  $Module = $Module || require('internal/modules/cjs/loader').Module;
1131cb0ef41Sopenharmony_ci  return $Module;
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci/**
1171cb0ef41Sopenharmony_ci * Invoke with `makeRequireFunction(module)` where `module` is the `Module` object to use as the context for the
1181cb0ef41Sopenharmony_ci * `require()` function.
1191cb0ef41Sopenharmony_ci * Use redirects to set up a mapping from a policy and restrict dependencies.
1201cb0ef41Sopenharmony_ci */
1211cb0ef41Sopenharmony_ciconst urlToFileCache = new SafeMap();
1221cb0ef41Sopenharmony_ci/**
1231cb0ef41Sopenharmony_ci * Create the module-scoped `require` function to pass into CommonJS modules.
1241cb0ef41Sopenharmony_ci * @param {Module} mod - The module to create the `require` function for.
1251cb0ef41Sopenharmony_ci * @param {ReturnType<import('internal/policy/manifest.js').Manifest['getDependencyMapper']>} redirects
1261cb0ef41Sopenharmony_ci * @typedef {(specifier: string) => unknown} RequireFunction
1271cb0ef41Sopenharmony_ci */
1281cb0ef41Sopenharmony_cifunction makeRequireFunction(mod, redirects) {
1291cb0ef41Sopenharmony_ci  // lazy due to cycle
1301cb0ef41Sopenharmony_ci  const Module = lazyModule();
1311cb0ef41Sopenharmony_ci  if (mod instanceof Module !== true) {
1321cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE('mod', 'Module', mod);
1331cb0ef41Sopenharmony_ci  }
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  /** @type {RequireFunction} */
1361cb0ef41Sopenharmony_ci  let require;
1371cb0ef41Sopenharmony_ci  if (redirects) {
1381cb0ef41Sopenharmony_ci    const id = mod.filename || mod.id;
1391cb0ef41Sopenharmony_ci    const conditions = getCjsConditions();
1401cb0ef41Sopenharmony_ci    const { resolve, reaction } = redirects;
1411cb0ef41Sopenharmony_ci    require = function require(specifier) {
1421cb0ef41Sopenharmony_ci      let missing = true;
1431cb0ef41Sopenharmony_ci      const destination = resolve(specifier, conditions);
1441cb0ef41Sopenharmony_ci      if (destination === true) {
1451cb0ef41Sopenharmony_ci        missing = false;
1461cb0ef41Sopenharmony_ci      } else if (destination) {
1471cb0ef41Sopenharmony_ci        const { href, protocol } = destination;
1481cb0ef41Sopenharmony_ci        if (protocol === 'node:') {
1491cb0ef41Sopenharmony_ci          const specifier = destination.pathname;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci          if (BuiltinModule.canBeRequiredByUsers(specifier)) {
1521cb0ef41Sopenharmony_ci            const mod = loadBuiltinModule(specifier, href);
1531cb0ef41Sopenharmony_ci            return mod.exports;
1541cb0ef41Sopenharmony_ci          }
1551cb0ef41Sopenharmony_ci          throw new ERR_UNKNOWN_BUILTIN_MODULE(specifier);
1561cb0ef41Sopenharmony_ci        } else if (protocol === 'file:') {
1571cb0ef41Sopenharmony_ci          let filepath = urlToFileCache.get(href);
1581cb0ef41Sopenharmony_ci          if (!filepath) {
1591cb0ef41Sopenharmony_ci            filepath = fileURLToPath(destination);
1601cb0ef41Sopenharmony_ci            urlToFileCache.set(href, filepath);
1611cb0ef41Sopenharmony_ci          }
1621cb0ef41Sopenharmony_ci          return mod[require_private_symbol](mod, filepath);
1631cb0ef41Sopenharmony_ci        }
1641cb0ef41Sopenharmony_ci      }
1651cb0ef41Sopenharmony_ci      if (missing) {
1661cb0ef41Sopenharmony_ci        reaction(new ERR_MANIFEST_DEPENDENCY_MISSING(
1671cb0ef41Sopenharmony_ci          id,
1681cb0ef41Sopenharmony_ci          specifier,
1691cb0ef41Sopenharmony_ci          ArrayPrototypeJoin([...conditions], ', '),
1701cb0ef41Sopenharmony_ci        ));
1711cb0ef41Sopenharmony_ci      }
1721cb0ef41Sopenharmony_ci      return mod[require_private_symbol](mod, specifier);
1731cb0ef41Sopenharmony_ci    };
1741cb0ef41Sopenharmony_ci  } else {
1751cb0ef41Sopenharmony_ci    require = function require(path) {
1761cb0ef41Sopenharmony_ci      // When no policy manifest, the original prototype.require is sustained
1771cb0ef41Sopenharmony_ci      return mod.require(path);
1781cb0ef41Sopenharmony_ci    };
1791cb0ef41Sopenharmony_ci  }
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  /**
1821cb0ef41Sopenharmony_ci   * The `resolve` method that gets attached to module-scope `require`.
1831cb0ef41Sopenharmony_ci   * @param {string} request
1841cb0ef41Sopenharmony_ci   * @param {Parameters<Module['_resolveFilename']>[3]} options
1851cb0ef41Sopenharmony_ci   */
1861cb0ef41Sopenharmony_ci  function resolve(request, options) {
1871cb0ef41Sopenharmony_ci    validateString(request, 'request');
1881cb0ef41Sopenharmony_ci    return Module._resolveFilename(request, mod, false, options);
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  require.resolve = resolve;
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  /**
1941cb0ef41Sopenharmony_ci   * The `paths` method that gets attached to module-scope `require`.
1951cb0ef41Sopenharmony_ci   * @param {string} request
1961cb0ef41Sopenharmony_ci   */
1971cb0ef41Sopenharmony_ci  function paths(request) {
1981cb0ef41Sopenharmony_ci    validateString(request, 'request');
1991cb0ef41Sopenharmony_ci    return Module._resolveLookupPaths(request, mod);
2001cb0ef41Sopenharmony_ci  }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  resolve.paths = paths;
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  setOwnProperty(require, 'main', process.mainModule);
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  // Enable support to add extra extension types.
2071cb0ef41Sopenharmony_ci  require.extensions = Module._extensions;
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  require.cache = Module._cache;
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  return require;
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci/**
2151cb0ef41Sopenharmony_ci * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
2161cb0ef41Sopenharmony_ci * because the buffer-to-string conversion in `fs.readFileSync()`
2171cb0ef41Sopenharmony_ci * translates it to FEFF, the UTF-16 BOM.
2181cb0ef41Sopenharmony_ci * @param {string} content
2191cb0ef41Sopenharmony_ci */
2201cb0ef41Sopenharmony_cifunction stripBOM(content) {
2211cb0ef41Sopenharmony_ci  if (StringPrototypeCharCodeAt(content) === 0xFEFF) {
2221cb0ef41Sopenharmony_ci    content = StringPrototypeSlice(content, 1);
2231cb0ef41Sopenharmony_ci  }
2241cb0ef41Sopenharmony_ci  return content;
2251cb0ef41Sopenharmony_ci}
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci/**
2281cb0ef41Sopenharmony_ci * Add built-in modules to a global or REPL scope object.
2291cb0ef41Sopenharmony_ci * @param {Record<string, unknown>} object - The object such as `globalThis` to add the built-in modules to.
2301cb0ef41Sopenharmony_ci * @param {string} dummyModuleName - The label representing the set of built-in modules to add.
2311cb0ef41Sopenharmony_ci */
2321cb0ef41Sopenharmony_cifunction addBuiltinLibsToObject(object, dummyModuleName) {
2331cb0ef41Sopenharmony_ci  // Make built-in modules available directly (loaded lazily).
2341cb0ef41Sopenharmony_ci  const Module = require('internal/modules/cjs/loader').Module;
2351cb0ef41Sopenharmony_ci  const { builtinModules } = Module;
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  // To require built-in modules in user-land and ignore modules whose
2381cb0ef41Sopenharmony_ci  // `canBeRequiredByUsers` is false. So we create a dummy module object and not
2391cb0ef41Sopenharmony_ci  // use `require()` directly.
2401cb0ef41Sopenharmony_ci  const dummyModule = new Module(dummyModuleName);
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  ArrayPrototypeForEach(builtinModules, (name) => {
2431cb0ef41Sopenharmony_ci    // Neither add underscored modules, nor ones that contain slashes (e.g.,
2441cb0ef41Sopenharmony_ci    // 'fs/promises') or ones that are already defined.
2451cb0ef41Sopenharmony_ci    if (StringPrototypeStartsWith(name, '_') ||
2461cb0ef41Sopenharmony_ci        StringPrototypeIncludes(name, '/') ||
2471cb0ef41Sopenharmony_ci        ObjectPrototypeHasOwnProperty(object, name)) {
2481cb0ef41Sopenharmony_ci      return;
2491cb0ef41Sopenharmony_ci    }
2501cb0ef41Sopenharmony_ci    // Goals of this mechanism are:
2511cb0ef41Sopenharmony_ci    // - Lazy loading of built-in modules
2521cb0ef41Sopenharmony_ci    // - Having all built-in modules available as non-enumerable properties
2531cb0ef41Sopenharmony_ci    // - Allowing the user to re-assign these variables as if there were no
2541cb0ef41Sopenharmony_ci    //   pre-existing globals with the same name.
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci    const setReal = (val) => {
2571cb0ef41Sopenharmony_ci      // Deleting the property before re-assigning it disables the
2581cb0ef41Sopenharmony_ci      // getter/setter mechanism.
2591cb0ef41Sopenharmony_ci      delete object[name];
2601cb0ef41Sopenharmony_ci      object[name] = val;
2611cb0ef41Sopenharmony_ci    };
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci    ObjectDefineProperty(object, name, {
2641cb0ef41Sopenharmony_ci      __proto__: null,
2651cb0ef41Sopenharmony_ci      get: () => {
2661cb0ef41Sopenharmony_ci        const lib = dummyModule.require(name);
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci        try {
2691cb0ef41Sopenharmony_ci          // Override the current getter/setter and set up a new
2701cb0ef41Sopenharmony_ci          // non-enumerable property.
2711cb0ef41Sopenharmony_ci          ObjectDefineProperty(object, name, {
2721cb0ef41Sopenharmony_ci            __proto__: null,
2731cb0ef41Sopenharmony_ci            get: () => lib,
2741cb0ef41Sopenharmony_ci            set: setReal,
2751cb0ef41Sopenharmony_ci            configurable: true,
2761cb0ef41Sopenharmony_ci            enumerable: false,
2771cb0ef41Sopenharmony_ci          });
2781cb0ef41Sopenharmony_ci        } catch {
2791cb0ef41Sopenharmony_ci          // If the property is no longer configurable, ignore the error.
2801cb0ef41Sopenharmony_ci        }
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci        return lib;
2831cb0ef41Sopenharmony_ci      },
2841cb0ef41Sopenharmony_ci      set: setReal,
2851cb0ef41Sopenharmony_ci      configurable: true,
2861cb0ef41Sopenharmony_ci      enumerable: false,
2871cb0ef41Sopenharmony_ci    });
2881cb0ef41Sopenharmony_ci  });
2891cb0ef41Sopenharmony_ci}
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci/**
2921cb0ef41Sopenharmony_ci * If a referrer is an URL instance or absolute path, convert it into an URL string.
2931cb0ef41Sopenharmony_ci * @param {string | URL} referrer
2941cb0ef41Sopenharmony_ci */
2951cb0ef41Sopenharmony_cifunction normalizeReferrerURL(referrer) {
2961cb0ef41Sopenharmony_ci  if (typeof referrer === 'string' && path.isAbsolute(referrer)) {
2971cb0ef41Sopenharmony_ci    return pathToFileURL(referrer).href;
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci  return new URL(referrer).href;
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci/**
3031cb0ef41Sopenharmony_ci * For error messages only, check if ESM syntax is in use.
3041cb0ef41Sopenharmony_ci * @param {string} code
3051cb0ef41Sopenharmony_ci */
3061cb0ef41Sopenharmony_cifunction hasEsmSyntax(code) {
3071cb0ef41Sopenharmony_ci  debug('Checking for ESM syntax');
3081cb0ef41Sopenharmony_ci  const parser = require('internal/deps/acorn/acorn/dist/acorn').Parser;
3091cb0ef41Sopenharmony_ci  let root;
3101cb0ef41Sopenharmony_ci  try {
3111cb0ef41Sopenharmony_ci    root = parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' });
3121cb0ef41Sopenharmony_ci  } catch {
3131cb0ef41Sopenharmony_ci    return false;
3141cb0ef41Sopenharmony_ci  }
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci  return ArrayPrototypeSome(root.body, (stmt) =>
3171cb0ef41Sopenharmony_ci    stmt.type === 'ExportDefaultDeclaration' ||
3181cb0ef41Sopenharmony_ci    stmt.type === 'ExportNamedDeclaration' ||
3191cb0ef41Sopenharmony_ci    stmt.type === 'ImportDeclaration' ||
3201cb0ef41Sopenharmony_ci    stmt.type === 'ExportAllDeclaration');
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_cimodule.exports = {
3241cb0ef41Sopenharmony_ci  addBuiltinLibsToObject,
3251cb0ef41Sopenharmony_ci  getCjsConditions,
3261cb0ef41Sopenharmony_ci  initializeCjsConditions,
3271cb0ef41Sopenharmony_ci  hasEsmSyntax,
3281cb0ef41Sopenharmony_ci  loadBuiltinModule,
3291cb0ef41Sopenharmony_ci  makeRequireFunction,
3301cb0ef41Sopenharmony_ci  normalizeReferrerURL,
3311cb0ef41Sopenharmony_ci  stripBOM,
3321cb0ef41Sopenharmony_ci  toRealPath,
3331cb0ef41Sopenharmony_ci};
334