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