diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js deleted file mode 100644 index 67ec47c424fbc4..00000000000000 --- a/lib/internal/modules/cjs/loader.js +++ /dev/null @@ -1,2001 +0,0 @@ -// 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, - JSONParse, - ObjectDefineProperty, - ObjectFreeze, - ObjectGetOwnPropertyDescriptor, - ObjectGetPrototypeOf, - ObjectHasOwn, - ObjectKeys, - ObjectPrototype, - ObjectPrototypeHasOwnProperty, - ObjectSetPrototypeOf, - Proxy, - ReflectApply, - ReflectSet, - RegExpPrototypeExec, - SafeMap, - 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_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} parent module. - */ -const kModuleParent = module_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 = { - kModuleSource, - kModuleExport, - kModuleExportNames, - kModuleCircularVisited, - initializeCJS, - Module, - findLongestRegisteredExtension, - resolveForCJSWithHooks, - loadSourceForCJSWithHooks: loadSource, - 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 } = 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 fs = require('fs'); -const path = require('path'); -const internalFsBinding = internalBinding('fs'); -const { safeGetenv } = internalBinding('credentials'); -const { - getCjsConditions, - initializeCjsConditions, - loadBuiltinModule, - makeRequireFunction, - setHasStartedUserCJSExecution, - stripBOM, - toRealPath, -} = require('internal/modules/helpers'); -const { - convertCJSFilenameToURL, - convertURLToCJSFilename, - loadHooks, - loadWithHooks, - registerHooks, - resolveHooks, - resolveWithHooks, -} = require('internal/modules/customization_hooks'); -const { stripTypeScriptModuleTypes } = 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 { - 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 = { __proto__: null }; - -let requireDepth = 0; -let isPreloading = false; -let statCache = null; - -/** - * Internal method to add tracing capabilities for Module._load. - * - * See more {@link Module._load} - */ -function wrapModuleLoad(request, parent, isMain) { - const logLabel = `[${parent?.id || ''}] [${request}]`; - const traceLabel = `require('${request}')`; - - startTimer(logLabel, traceLabel); - - try { - return onRequire().traceSync(Module._load, { - __proto__: null, - parentFilename: parent?.filename, - id: request, - }, Module, request, parent, isMain); - } 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 - */ -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 = internalFsBinding.internalModuleStat(filename); - if (statCache !== null && result >= 0) { - // Only set cache when `internalModuleStat(filename)` succeeds. - statCache.set(filename, result); - } - return result; -} - -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 - */ -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 - */ -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 - */ -function reportModuleNotFoundToWatchMode(basePath, extensions) { - if (shouldReportRequiredModules() && process.send) { - process.send({ 'watch:require': ArrayPrototypeMap(extensions, (ext) => path.resolve(`${basePath}${ext}`)) }); - } -} - -/** - * Create a new module instance. - * @param {string} id - * @param {Module} parent - */ -function Module(id = '', parent) { - this.id = id; - this.path = path.dirname(id); - setOwnProperty(this, 'exports', {}); - this[kModuleParent] = parent; - updateChildren(parent, this, false); - this.filename = null; - this.loaded = false; - this.children = []; -} - -/** @type {Record} */ -Module._cache = { __proto__: null }; -/** @type {Record} */ -Module._pathCache = { __proto__: null }; -/** @type {Record 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 - */ -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} - */ -function getModuleParent() { - return this[kModuleParent]; -} - -/** - * Set the parent of the current module in our cache. - * @this {Module} - * @param {Module} value - */ -function setModuleParent(value) { - this[kModuleParent] = 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. - */ -function initializeCJS() { - // This need to be done at runtime in case --expose-internals is set. - - let modules = Module.builtinModules = BuiltinModule.getAllBuiltinModuleIds(); - if (!getOptionValue('--experimental-quic')) { - modules = modules.filter((i) => i !== 'node:quic'); - } - Module.builtinModules = ObjectFreeze(modules); - - 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.") -// -> a. -// -// require("a") -// -> a -// -> a. -// -> a/index. - -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` - */ -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. - */ -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 toRealPath(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 - */ -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. - */ -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. - */ -function trySelfParentPath(parent) { - if (!parent) { return false; } - - if (parent.filename) { - return parent.filename; - } else if (parent.id === '' || 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 - */ -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; - } - - try { - const { packageExportsResolve } = require('internal/modules/esm/resolve'); - return finalizeEsmResolution(packageExportsResolve( - pathToFileURL(pkg.path), expansion, pkg.data, - pathToFileURL(parentPath), conditions), parentPath, pkg.path); - } catch (e) { - if (e.code === 'ERR_MODULE_NOT_FOUND') { - throw createEsmNotFoundErr(request, pkg.path); - } - 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. - */ -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} 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 = toRealPath(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 = toRealPath(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 - */ - 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']; - } - - /** @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', - ); - } - 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 - */ - Module._nodeModulePaths = function(from) { - // Guarantee that 'from' is absolute. - from = path.resolve(from); - // Return early not only to avoid unnecessary work, but to *avoid* returning - // an array of two items for a root: [ '//node_modules', '/node_modules' ] - if (from === '/') { - return ['/node_modules']; - } - - // note: this approach *only* works when the path is guaranteed - // to be absolute. Doing a fully-edge-case-correct path.split - // that works on both Windows and Posix is non-trivial. - /** @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', - ); - } - 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 - */ -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. - */ -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 - */ -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[kModuleParent]; - 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; -} - -/** - * Resolve a module request for CommonJS, invoking hooks from module.registerHooks() - * if necessary. - * @param {string} specifier - * @param {Module|undefined} parent - * @param {boolean} isMain - * @returns {{url?: string, format?: string, parentURL?: string, filename: string}} - */ -function resolveForCJSWithHooks(specifier, parent, isMain) { - let defaultResolvedURL; - let defaultResolvedFilename; - let format; - - function defaultResolveImpl(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); - } - defaultResolvedURL = specifier; - format = 'builtin'; - return normalized; - } - return Module._resolveFilename(specifier, parent, isMain, options).toString(); - } - - // Fast path: no hooks, just return simple results. - if (!resolveHooks.length) { - const filename = defaultResolveImpl(specifier, parent, isMain); - return { __proto__: null, url: defaultResolvedURL, filename, format }; - } - - // 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. - defaultResolvedFilename = defaultResolveImpl(specifier, parent, isMain, { - __proto__: null, - conditions: context.conditions, - }); - - defaultResolvedURL = convertCJSFilenameToURL(defaultResolvedFilename); - return { __proto__: null, url: defaultResolvedURL }; - } - - const resolveResult = resolveWithHooks(specifier, parentURL, /* importAttributes */ undefined, - getCjsConditions(), defaultResolve); - const { url } = resolveResult; - format = resolveResult.format; - - let filename; - if (url === defaultResolvedURL) { // Not overridden, skip the re-conversion. - filename = defaultResolvedFilename; - } else { - filename = convertURLToCJSFilename(url); - } - - return { __proto__: null, url, format, filename, parentURL }; -} - -/** - * @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 fs.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 {any} 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. Otherwise, return undefined. - */ -function loadBuiltinWithHooks(id, url, format) { - if (loadHooks.length) { - url ??= `node:${id}`; - // TODO(joyeecheung): do we really want to invoke the load hook for the builtins? - const loadResult = loadWithHooks(url, format || 'builtin', /* importAttributes */ undefined, - getCjsConditions(), getDefaultLoad(url, id)); - if (loadResult.format && loadResult.format !== 'builtin') { - return undefined; // Format has been overridden, return undefined for the caller to continue loading. - } - } - - // 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 mod.exports; -} - -/** - * 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 - */ -Module._load = function(request, parent, isMain) { - let relResolveCacheIdentifier; - if (parent) { - debug('Module._load REQUEST %s parent: %s', request, parent.id); - // Fast path for (lazy loaded) modules in the same directory. The indirect - // caching is required to allow cache invalidation without changing the old - // cache key names. - relResolveCacheIdentifier = `${parent.path}\x00${request}`; - const filename = relativeResolveCache[relResolveCacheIdentifier]; - reportModuleToWatchMode(filename); - if (filename !== undefined) { - const cachedModule = Module._cache[filename]; - if (cachedModule !== undefined) { - updateChildren(parent, cachedModule, true); - if (!cachedModule.loaded) { - return getExportsForCircularRequire(cachedModule); - } - return cachedModule.exports; - } - delete relativeResolveCache[relResolveCacheIdentifier]; - } - } - - const { url, format, filename } = resolveForCJSWithHooks(request, parent, isMain); - - // For backwards compatibility, if the request itself starts with node:, load it before checking - // Module._cache. Otherwise, load it after the check. - if (StringPrototypeStartsWith(request, 'node:')) { - const result = loadBuiltinWithHooks(filename, url, format); - if (result) { - return result; - } - // The format of the builtin has been overridden by user hooks. Continue loading. - } - - const cachedModule = Module._cache[filename]; - 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 (BuiltinModule.canBeRequiredWithoutScheme(filename)) { - const result = loadBuiltinWithHooks(filename, url, format); - if (result) { - return result; - } - // The format of the builtin has been overridden by user hooks. Continue loading. - } - - // 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; - } - - reportModuleToWatchMode(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; - } - - if (parent !== undefined) { - relativeResolveCache[relResolveCacheIdentifier] = filename; - } - - let threw = true; - try { - module.load(filename); - threw = false; - } finally { - if (threw) { - delete Module._cache[filename]; - if (parent !== undefined) { - delete relativeResolveCache[relResolveCacheIdentifier]; - 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 {string[]} conditions Conditions used for resolution. - */ -Module._resolveFilename = function(request, parent, isMain, options) { - if (BuiltinModule.normalizeRequirableId(request)) { - return request; - } - const conditions = (options?.conditions) || getCjsConditions(); - - 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); - } - - if (request[0] === '#' && (parent?.filename || parent?.id === '')) { - const parentPath = parent?.filename ?? process.cwd() + path.sep; - 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 parentPath = trySelfParentPath(parent); - 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 = []; - for (let cursor = parent; - cursor; - cursor = cursor[kModuleParent]) { - ArrayPrototypePush(requireStack, cursor.filename || cursor.id); - } - let message = `Cannot find module '${request}'`; - if (requireStack.length > 0) { - message = message + '\nRequire stack:\n- ' + - ArrayPrototypeJoin(requireStack, '\n- '); - } - // eslint-disable-next-line no-restricted-syntax - const err = new Error(message); - err.code = 'MODULE_NOT_FOUND'; - err.requireStack = requireStack; - throw err; -}; - -/** - * 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 - */ -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; - } - const err = createEsmNotFoundErr(filename, pkgPath); - throw err; -} - -/** - * 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 - */ -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; -} - -/** - * Given a file name, pass it to the proper extension handler. - * @param {string} filename The `require` specifier - */ -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)); - - const 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 - */ -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[kModuleParent]; - - 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 and reduce the noise. If there are more than 100 frames, - // just give up and assume it is under node_modules. - shouldEmitWarning = !isInsideNodeModules(100, true); - } - } 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 === '') { - 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); - // 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. - */ -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('--experimental-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. - */ -Module.prototype._compile = function(content, filename, format) { - if (format === 'commonjs-typescript' || format === 'module-typescript' || format === 'typescript') { - content = stripTypeScriptModuleTypes(content, filename); - 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 redirects; - - 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, redirects); - 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 = ReflectApply(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 loadResult = loadWithHooks(mod[kURL], mod[kFormat], /* importAttributes */ undefined, getCjsConditions(), - getDefaultLoad(mod[kURL], filename)); - - // 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[kModuleParent]; - 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('--experimental-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'; - } - } - 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('--experimental-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 - */ -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 - */ -function createRequireFromPath(filename) { - // 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; - - 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} filename 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. - */ -function createRequire(filename) { - let filepath; - - if (isURL(filename) || - (typeof filename === 'string' && !path.isAbsolute(filename))) { - try { - filepath = fileURLToPath(filename); - } catch { - throw new ERR_INVALID_ARG_VALUE('filename', filename, - createRequireError); - } - } else if (typeof filename !== 'string') { - throw new ERR_INVALID_ARG_VALUE('filename', filename, createRequireError); - } else { - filepath = filename; - } - return createRequireFromPath(filepath); -} - -/** - * 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; diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js deleted file mode 100644 index 859b6bfedac4bb..00000000000000 --- a/lib/internal/modules/esm/resolve.js +++ /dev/null @@ -1,1045 +0,0 @@ -'use strict'; - -const { - ArrayIsArray, - ArrayPrototypeJoin, - ArrayPrototypeMap, - JSONStringify, - ObjectGetOwnPropertyNames, - ObjectPrototypeHasOwnProperty, - RegExpPrototypeExec, - RegExpPrototypeSymbolReplace, - SafeMap, - SafeSet, - String, - StringPrototypeEndsWith, - StringPrototypeIncludes, - StringPrototypeIndexOf, - StringPrototypeLastIndexOf, - StringPrototypeReplace, - StringPrototypeSlice, - StringPrototypeSplit, - StringPrototypeStartsWith, - encodeURIComponent, -} = primordials; -const assert = require('internal/assert'); -const internalFS = require('internal/fs/utils'); -const { BuiltinModule } = require('internal/bootstrap/realm'); -const { realpathSync } = require('fs'); -const { getOptionValue } = require('internal/options'); -// Do not eagerly grab .manifest, it may be in TDZ -const { sep, posix: { relative: relativePosixPath }, resolve } = require('path'); -const preserveSymlinks = getOptionValue('--preserve-symlinks'); -const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); -const inputTypeFlag = getOptionValue('--input-type'); -const { URL, pathToFileURL, fileURLToPath, isURL, URLParse } = require('internal/url'); -const { getCWDURL, setOwnProperty } = require('internal/util'); -const { canParse: URLCanParse } = internalBinding('url'); -const { legacyMainResolve: FSLegacyMainResolve } = internalBinding('fs'); -const { - ERR_INPUT_TYPE_NOT_ALLOWED, - ERR_INVALID_ARG_TYPE, - ERR_INVALID_MODULE_SPECIFIER, - ERR_INVALID_PACKAGE_CONFIG, - ERR_INVALID_PACKAGE_TARGET, - ERR_MODULE_NOT_FOUND, - ERR_PACKAGE_IMPORT_NOT_DEFINED, - ERR_PACKAGE_PATH_NOT_EXPORTED, - ERR_UNSUPPORTED_DIR_IMPORT, - ERR_UNSUPPORTED_RESOLVE_REQUEST, -} = require('internal/errors').codes; - -const { Module: CJSModule } = require('internal/modules/cjs/loader'); -const { getConditionsSet } = require('internal/modules/esm/utils'); -const packageJsonReader = require('internal/modules/package_json_reader'); -const internalFsBinding = internalBinding('fs'); - -/** - * @typedef {import('internal/modules/esm/package_config.js').PackageConfig} PackageConfig - */ - - -const emittedPackageWarnings = new SafeSet(); - -/** - * Emits a deprecation warning for the use of a deprecated trailing slash pattern mapping in the "exports" field - * module resolution of a package. - * @param {string} match - The deprecated trailing slash pattern mapping. - * @param {string} pjsonUrl - The URL of the package.json file. - * @param {string} base - The URL of the module that imported the package. - */ -function emitTrailingSlashPatternDeprecation(match, pjsonUrl, base) { - if (process.noDeprecation) { - return; - } - const pjsonPath = fileURLToPath(pjsonUrl); - if (emittedPackageWarnings.has(pjsonPath + '|' + match)) { return; } - emittedPackageWarnings.add(pjsonPath + '|' + match); - process.emitWarning( - `Use of deprecated trailing slash pattern mapping "${match}" in the ` + - `"exports" field module resolution of the package at ${pjsonPath}${ - base ? ` imported from ${fileURLToPath(base)}` : - ''}. Mapping specifiers ending in "/" is no longer supported.`, - 'DeprecationWarning', - 'DEP0155', - ); -} - -const doubleSlashRegEx = /[/\\][/\\]/; - -/** - * Emits a deprecation warning for invalid segment in module resolution. - * @param {string} target - The target module. - * @param {string} request - The requested module. - * @param {string} match - The matched module. - * @param {string} pjsonUrl - The package.json URL. - * @param {boolean} internal - Whether the module is in the "imports" or "exports" field. - * @param {string} base - The base URL. - * @param {boolean} isTarget - Whether the target is a module. - */ -function emitInvalidSegmentDeprecation(target, request, match, pjsonUrl, internal, base, isTarget) { - if (process.noDeprecation) { - return; - } - const pjsonPath = fileURLToPath(pjsonUrl); - const double = RegExpPrototypeExec(doubleSlashRegEx, isTarget ? target : request) !== null; - process.emitWarning( - `Use of deprecated ${double ? 'double slash' : - 'leading or trailing slash matching'} resolving "${target}" for module ` + - `request "${request}" ${request !== match ? `matched to "${match}" ` : '' - }in the "${internal ? 'imports' : 'exports'}" field module resolution of the package at ${ - pjsonPath}${base ? ` imported from ${fileURLToPath(base)}` : ''}.`, - 'DeprecationWarning', - 'DEP0166', - ); -} - -/** - * Emits a deprecation warning if the given URL is a module and - * the package.json file does not define a "main" or "exports" field. - * @param {URL} url - The URL of the module being resolved. - * @param {string} path - The path of the module being resolved. - * @param {string} pkgPath - The path of the parent dir of the package.json file for the module. - * @param {string | URL} [base] - The base URL for the module being resolved. - * @param {string} [main] - The "main" field from the package.json file. - */ -function emitLegacyIndexDeprecation(url, path, pkgPath, base, main) { - if (process.noDeprecation) { - return; - } - const format = defaultGetFormatWithoutErrors(url); - if (format !== 'module') { return; } - const basePath = fileURLToPath(base); - if (!main) { - process.emitWarning( - `No "main" or "exports" field defined in the package.json for ${pkgPath - } resolving the main entry point "${ - StringPrototypeSlice(path, pkgPath.length)}", imported from ${basePath - }.\nDefault "index" lookups for the main are deprecated for ES modules.`, - 'DeprecationWarning', - 'DEP0151', - ); - } else if (resolve(pkgPath, main) !== path) { - process.emitWarning( - `Package ${pkgPath} has a "main" field set to "${main}", ` + - `excluding the full filename and extension to the resolved file at "${ - StringPrototypeSlice(path, pkgPath.length)}", imported from ${ - basePath}.\n Automatic extension resolution of the "main" field is ` + - 'deprecated for ES modules.', - 'DeprecationWarning', - 'DEP0151', - ); - } -} - -const realpathCache = new SafeMap(); - -const legacyMainResolveExtensions = [ - '', - '.js', - '.json', - '.node', - '/index.js', - '/index.json', - '/index.node', - './index.js', - './index.json', - './index.node', -]; - -const legacyMainResolveExtensionsIndexes = { - // 0-6: when packageConfig.main is defined - kResolvedByMain: 0, - kResolvedByMainJs: 1, - kResolvedByMainJson: 2, - kResolvedByMainNode: 3, - kResolvedByMainIndexJs: 4, - kResolvedByMainIndexJson: 5, - kResolvedByMainIndexNode: 6, - // 7-9: when packageConfig.main is NOT defined, - // or when the previous case didn't found the file - kResolvedByPackageAndJs: 7, - kResolvedByPackageAndJson: 8, - kResolvedByPackageAndNode: 9, -}; - -/** - * Legacy CommonJS main resolution: - * 1. let M = pkg_url + (json main field) - * 2. TRY(M, M.js, M.json, M.node) - * 3. TRY(M/index.js, M/index.json, M/index.node) - * 4. TRY(pkg_url/index.js, pkg_url/index.json, pkg_url/index.node) - * 5. NOT_FOUND - * @param {URL} packageJSONUrl - * @param {import('typings/internalBinding/modules').PackageConfig} packageConfig - * @param {string | URL | undefined} base - * @returns {URL} - */ -function legacyMainResolve(packageJSONUrl, packageConfig, base) { - assert(isURL(packageJSONUrl)); - const pkgPath = fileURLToPath(new URL('.', packageJSONUrl)); - - const baseStringified = isURL(base) ? base.href : base; - - const resolvedOption = FSLegacyMainResolve(pkgPath, packageConfig.main, baseStringified); - - const maybeMain = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ? - packageConfig.main || './' : ''; - const resolvedPath = resolve(pkgPath, maybeMain + legacyMainResolveExtensions[resolvedOption]); - const resolvedUrl = pathToFileURL(resolvedPath); - - emitLegacyIndexDeprecation(resolvedUrl, resolvedPath, pkgPath, base, packageConfig.main); - - return resolvedUrl; -} - -const encodedSepRegEx = /%2F|%5C/i; -/** - * Finalizes the resolution of a module specifier by checking if the resolved pathname contains encoded "/" or "\\" - * characters, checking if the resolved pathname is a directory or file, and resolving any symlinks if necessary. - * @param {URL} resolved - The resolved URL object. - * @param {string | URL | undefined} base - The base URL object. - * @param {boolean} preserveSymlinks - Whether to preserve symlinks or not. - * @returns {URL} - The finalized URL object. - * @throws {ERR_INVALID_MODULE_SPECIFIER} - If the resolved pathname contains encoded "/" or "\\" characters. - * @throws {ERR_UNSUPPORTED_DIR_IMPORT} - If the resolved pathname is a directory. - * @throws {ERR_MODULE_NOT_FOUND} - If the resolved pathname is not a file. - */ -function finalizeResolution(resolved, base, preserveSymlinks) { - if (RegExpPrototypeExec(encodedSepRegEx, resolved.pathname) !== null) { - let basePath; - try { - basePath = fileURLToPath(base); - } catch { - basePath = base; - } - throw new ERR_INVALID_MODULE_SPECIFIER( - resolved.pathname, 'must not include encoded "/" or "\\" characters', - basePath); - } - - let path; - try { - path = fileURLToPath(resolved); - } catch (err) { - setOwnProperty(err, 'input', `${resolved}`); - setOwnProperty(err, 'module', `${base}`); - throw err; - } - - const stats = internalFsBinding.internalModuleStat( - StringPrototypeEndsWith(internalFsBinding, path, '/') ? StringPrototypeSlice(path, -1) : path, - ); - - // Check for stats.isDirectory() - if (stats === 1) { - let basePath; - try { - basePath = fileURLToPath(base); - } catch { - basePath = base; - } - throw new ERR_UNSUPPORTED_DIR_IMPORT(path, basePath, String(resolved)); - } else if (stats !== 0) { - // Check for !stats.isFile() - if (process.env.WATCH_REPORT_DEPENDENCIES && process.send) { - process.send({ 'watch:require': [path || resolved.pathname] }); - } - let basePath; - try { - basePath = fileURLToPath(base); - } catch { - basePath = base; - } - throw new ERR_MODULE_NOT_FOUND( - path || resolved.pathname, basePath, resolved); - } - - if (!preserveSymlinks) { - const real = realpathSync(path, { - [internalFS.realpathCacheKey]: realpathCache, - }); - const { search, hash } = resolved; - resolved = - pathToFileURL(real + (StringPrototypeEndsWith(path, sep) ? '/' : '')); - resolved.search = search; - resolved.hash = hash; - } - - return resolved; -} - -/** - * Returns an error object indicating that the specified import is not defined. - * @param {string} specifier - The import specifier that is not defined. - * @param {URL} packageJSONUrl - The URL of the package.json file, or null if not available. - * @param {string | URL | undefined} base - The base URL to use for resolving relative URLs. - * @returns {ERR_PACKAGE_IMPORT_NOT_DEFINED} - The error object. - */ -function importNotDefined(specifier, packageJSONUrl, base) { - return new ERR_PACKAGE_IMPORT_NOT_DEFINED( - specifier, packageJSONUrl && fileURLToPath(new URL('.', packageJSONUrl)), - fileURLToPath(base)); -} - -/** - * Returns an error object indicating that the specified subpath was not exported by the package. - * @param {string} subpath - The subpath that was not exported. - * @param {URL} packageJSONUrl - The URL of the package.json file. - * @param {string | URL | undefined} [base] - The base URL to use for resolving the subpath. - * @returns {ERR_PACKAGE_PATH_NOT_EXPORTED} - The error object. - */ -function exportsNotFound(subpath, packageJSONUrl, base) { - return new ERR_PACKAGE_PATH_NOT_EXPORTED( - fileURLToPath(new URL('.', packageJSONUrl)), subpath, - base && fileURLToPath(base)); -} - -/** - * Throws an error indicating that the given request is not a valid subpath match for the specified pattern. - * @param {string} request - The request that failed to match the pattern. - * @param {string} match - The pattern that the request was compared against. - * @param {URL} packageJSONUrl - The URL of the package.json file being resolved. - * @param {boolean} internal - Whether the resolution is for an "imports" or "exports" field in package.json. - * @param {string | URL | undefined} base - The base URL for the resolution. - * @throws {ERR_INVALID_MODULE_SPECIFIER} When the request is not a valid match for the pattern. - */ -function throwInvalidSubpath(request, match, packageJSONUrl, internal, base) { - const reason = `request is not a valid match in pattern "${match}" for the "${ - internal ? 'imports' : 'exports'}" resolution of ${ - fileURLToPath(packageJSONUrl)}`; - throw new ERR_INVALID_MODULE_SPECIFIER(request, reason, - base && fileURLToPath(base)); -} - -/** - * Creates an error object for an invalid package target. - * @param {string} subpath - The subpath. - * @param {import('internal/modules/esm/package_config.js').PackageTarget} target - The target. - * @param {URL} packageJSONUrl - The URL of the package.json file. - * @param {boolean} internal - Whether the package is internal. - * @param {string | URL | undefined} base - The base URL. - * @returns {ERR_INVALID_PACKAGE_TARGET} - The error object. - */ -function invalidPackageTarget( - subpath, target, packageJSONUrl, internal, base) { - if (typeof target === 'object' && target !== null) { - target = JSONStringify(target, null, ''); - } else { - target = `${target}`; - } - return new ERR_INVALID_PACKAGE_TARGET( - fileURLToPath(new URL('.', packageJSONUrl)), subpath, target, - internal, base && fileURLToPath(base)); -} - -const invalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))?(\\|\/|$)/i; -const deprecatedInvalidSegmentRegEx = /(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f|%4f)(d|%64|%44)(u|%75|%55)(l|%6c|%4c)(e|%65|%45)(s|%73|%53))(\\|\/|$)/i; -const patternRegEx = /\*/g; - -/** - * Resolves the package target string to a URL object. - * @param {string} target - The target string to resolve. - * @param {string} subpath - The subpath to append to the resolved URL. - * @param {RegExpMatchArray} match - The matched string array from the import statement. - * @param {string} packageJSONUrl - The URL of the package.json file. - * @param {string} base - The base URL to resolve the target against. - * @param {RegExp} pattern - The pattern to replace in the target string. - * @param {boolean} internal - Whether the target is internal to the package. - * @param {boolean} isPathMap - Whether the target is a path map. - * @param {string[]} conditions - The import conditions. - * @returns {URL} - The resolved URL object. - * @throws {ERR_INVALID_PACKAGE_TARGET} - If the target is invalid. - * @throws {ERR_INVALID_SUBPATH} - If the subpath is invalid. - */ -function resolvePackageTargetString( - target, - subpath, - match, - packageJSONUrl, - base, - pattern, - internal, - isPathMap, - conditions, -) { - - if (subpath !== '' && !pattern && target[target.length - 1] !== '/') { - throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - - if (!StringPrototypeStartsWith(target, './')) { - if (internal && - target[0] !== '/' && - !StringPrototypeStartsWith(target, '../')) { - // No need to convert target to string, since it's already presumed to be - if (!URLCanParse(target)) { - const exportTarget = pattern ? - RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : - target + subpath; - return packageResolve( - exportTarget, packageJSONUrl, conditions); - } - } - throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - - if (RegExpPrototypeExec(invalidSegmentRegEx, StringPrototypeSlice(target, 2)) !== null) { - if (RegExpPrototypeExec(deprecatedInvalidSegmentRegEx, StringPrototypeSlice(target, 2)) === null) { - if (!isPathMap) { - const request = pattern ? - StringPrototypeReplace(match, '*', () => subpath) : - match + subpath; - const resolvedTarget = pattern ? - RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : - target; - emitInvalidSegmentDeprecation(resolvedTarget, request, match, packageJSONUrl, internal, base, true); - } - } else { - throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - } - - const resolved = new URL(target, packageJSONUrl); - const resolvedPath = resolved.pathname; - const packagePath = new URL('.', packageJSONUrl).pathname; - - if (!StringPrototypeStartsWith(resolvedPath, packagePath)) { - throw invalidPackageTarget(match, target, packageJSONUrl, internal, base); - } - - if (subpath === '') { return resolved; } - - if (RegExpPrototypeExec(invalidSegmentRegEx, subpath) !== null) { - const request = pattern ? StringPrototypeReplace(match, '*', () => subpath) : match + subpath; - if (RegExpPrototypeExec(deprecatedInvalidSegmentRegEx, subpath) === null) { - if (!isPathMap) { - const resolvedTarget = pattern ? - RegExpPrototypeSymbolReplace(patternRegEx, target, () => subpath) : - target; - emitInvalidSegmentDeprecation(resolvedTarget, request, match, packageJSONUrl, internal, base, false); - } - } else { - throwInvalidSubpath(request, match, packageJSONUrl, internal, base); - } - } - - if (pattern) { - return new URL( - RegExpPrototypeSymbolReplace(patternRegEx, resolved.href, () => subpath), - ); - } - - return new URL(subpath, resolved); -} - -/** - * Checks if the given key is a valid array index. - * @param {string} key - The key to check. - * @returns {boolean} - Returns `true` if the key is a valid array index, else `false`. - */ -function isArrayIndex(key) { - const keyNum = +key; - if (`${keyNum}` !== key) { return false; } - return keyNum >= 0 && keyNum < 0xFFFF_FFFF; -} - -/** - * Resolves the target of a package based on the provided parameters. - * @param {string} packageJSONUrl - The URL of the package.json file. - * @param {import('internal/modules/esm/package_config.js').PackageTarget} target - The target to resolve. - * @param {string} subpath - The subpath to resolve. - * @param {string} packageSubpath - The subpath of the package to resolve. - * @param {string} base - The base path to resolve. - * @param {RegExp} pattern - The pattern to match. - * @param {boolean} internal - Whether the package is internal. - * @param {boolean} isPathMap - Whether the package is a path map. - * @param {Set} conditions - The conditions to match. - * @returns {URL | null | undefined} - The resolved target, or null if not found, or undefined if not resolvable. - */ -function resolvePackageTarget(packageJSONUrl, target, subpath, packageSubpath, - base, pattern, internal, isPathMap, conditions) { - if (typeof target === 'string') { - return resolvePackageTargetString( - target, subpath, packageSubpath, packageJSONUrl, base, pattern, internal, - isPathMap, conditions); - } else if (ArrayIsArray(target)) { - if (target.length === 0) { - return null; - } - - let lastException; - for (let i = 0; i < target.length; i++) { - const targetItem = target[i]; - let resolveResult; - try { - resolveResult = resolvePackageTarget( - packageJSONUrl, targetItem, subpath, packageSubpath, base, pattern, - internal, isPathMap, conditions); - } catch (e) { - lastException = e; - if (e.code === 'ERR_INVALID_PACKAGE_TARGET') { - continue; - } - throw e; - } - if (resolveResult === undefined) { - continue; - } - if (resolveResult === null) { - lastException = null; - continue; - } - return resolveResult; - } - if (lastException == null) { - return lastException; - } - throw lastException; - } else if (typeof target === 'object' && target !== null) { - const keys = ObjectGetOwnPropertyNames(target); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (isArrayIndex(key)) { - throw new ERR_INVALID_PACKAGE_CONFIG( - fileURLToPath(packageJSONUrl), base, - '"exports" cannot contain numeric property keys.'); - } - } - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - if (key === 'default' || conditions.has(key)) { - const conditionalTarget = target[key]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, conditionalTarget, subpath, packageSubpath, base, - pattern, internal, isPathMap, conditions); - if (resolveResult === undefined) { continue; } - return resolveResult; - } - } - return undefined; - } else if (target === null) { - return null; - } - throw invalidPackageTarget(packageSubpath, target, packageJSONUrl, internal, - base); -} - -/** - * Is the given exports object using the shorthand syntax? - * @param {import('internal/modules/esm/package_config.js').PackageConfig['exports']} exports - * @param {URL} packageJSONUrl The URL of the package.json file. - * @param {string | URL | undefined} base The base URL. - */ -function isConditionalExportsMainSugar(exports, packageJSONUrl, base) { - if (typeof exports === 'string' || ArrayIsArray(exports)) { return true; } - if (typeof exports !== 'object' || exports === null) { return false; } - - const keys = ObjectGetOwnPropertyNames(exports); - let isConditionalSugar = false; - let i = 0; - for (let j = 0; j < keys.length; j++) { - const key = keys[j]; - const curIsConditionalSugar = key === '' || key[0] !== '.'; - if (i++ === 0) { - isConditionalSugar = curIsConditionalSugar; - } else if (isConditionalSugar !== curIsConditionalSugar) { - throw new ERR_INVALID_PACKAGE_CONFIG( - fileURLToPath(packageJSONUrl), base, - '"exports" cannot contain some keys starting with \'.\' and some not.' + - ' The exports object must either be an object of package subpath keys' + - ' or an object of main entry condition name keys only.'); - } - } - return isConditionalSugar; -} - -/** - * Resolves the exports of a package. - * @param {URL} packageJSONUrl - The URL of the package.json file. - * @param {string} packageSubpath - The subpath of the package to resolve. - * @param {import('internal/modules/esm/package_config.js').PackageConfig} packageConfig - The package metadata. - * @param {string | URL | undefined} base - The base path to resolve from. - * @param {Set} conditions - An array of conditions to match. - * @returns {URL} - The resolved package target. - */ -function packageExportsResolve( - packageJSONUrl, packageSubpath, packageConfig, base, conditions) { - let { exports } = packageConfig; - if (isConditionalExportsMainSugar(exports, packageJSONUrl, base)) { - exports = { '.': exports }; - } - - if (ObjectPrototypeHasOwnProperty(exports, packageSubpath) && - !StringPrototypeIncludes(packageSubpath, '*') && - !StringPrototypeEndsWith(packageSubpath, '/')) { - const target = exports[packageSubpath]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, target, '', packageSubpath, base, false, false, false, - conditions, - ); - - if (resolveResult == null) { - throw exportsNotFound(packageSubpath, packageJSONUrl, base); - } - - return resolveResult; - } - - let bestMatch = ''; - let bestMatchSubpath; - const keys = ObjectGetOwnPropertyNames(exports); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const patternIndex = StringPrototypeIndexOf(key, '*'); - if (patternIndex !== -1 && - StringPrototypeStartsWith(packageSubpath, - StringPrototypeSlice(key, 0, patternIndex))) { - // When this reaches EOL, this can throw at the top of the whole function: - // - // if (StringPrototypeEndsWith(packageSubpath, '/')) - // throwInvalidSubpath(packageSubpath) - // - // To match "imports" and the spec. - if (StringPrototypeEndsWith(packageSubpath, '/')) { - emitTrailingSlashPatternDeprecation(packageSubpath, packageJSONUrl, - base); - } - const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); - if (packageSubpath.length >= key.length && - StringPrototypeEndsWith(packageSubpath, patternTrailer) && - patternKeyCompare(bestMatch, key) === 1 && - StringPrototypeLastIndexOf(key, '*') === patternIndex) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice( - packageSubpath, patternIndex, - packageSubpath.length - patternTrailer.length); - } - } - } - - if (bestMatch) { - const target = exports[bestMatch]; - const resolveResult = resolvePackageTarget( - packageJSONUrl, - target, - bestMatchSubpath, - bestMatch, - base, - true, - false, - StringPrototypeEndsWith(packageSubpath, '/'), - conditions); - - if (resolveResult == null) { - throw exportsNotFound(packageSubpath, packageJSONUrl, base); - } - return resolveResult; - } - - throw exportsNotFound(packageSubpath, packageJSONUrl, base); -} - -/** - * Compares two strings that may contain a wildcard character ('*') and returns a value indicating their order. - * @param {string} a - The first string to compare. - * @param {string} b - The second string to compare. - * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, - * or 0 if they are equal. - */ -function patternKeyCompare(a, b) { - const aPatternIndex = StringPrototypeIndexOf(a, '*'); - const bPatternIndex = StringPrototypeIndexOf(b, '*'); - const baseLenA = aPatternIndex === -1 ? a.length : aPatternIndex + 1; - const baseLenB = bPatternIndex === -1 ? b.length : bPatternIndex + 1; - if (baseLenA > baseLenB) { return -1; } - if (baseLenB > baseLenA) { return 1; } - if (aPatternIndex === -1) { return 1; } - if (bPatternIndex === -1) { return -1; } - if (a.length > b.length) { return -1; } - if (b.length > a.length) { return 1; } - return 0; -} - -/** - * Resolves the given import name for a package. - * @param {string} name - The name of the import to resolve. - * @param {string | URL | undefined} base - The base URL to resolve the import from. - * @param {Set} conditions - An object containing the import conditions. - * @throws {ERR_INVALID_MODULE_SPECIFIER} If the import name is not valid. - * @throws {ERR_PACKAGE_IMPORT_NOT_DEFINED} If the import name cannot be resolved. - * @returns {URL} The resolved import URL. - */ -function packageImportsResolve(name, base, conditions) { - if (name === '#' || StringPrototypeStartsWith(name, '#/') || - StringPrototypeEndsWith(name, '/')) { - const reason = 'is not a valid internal imports specifier name'; - throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base)); - } - let packageJSONUrl; - const packageConfig = packageJsonReader.getPackageScopeConfig(base); - if (packageConfig.exists) { - packageJSONUrl = pathToFileURL(packageConfig.pjsonPath); - const imports = packageConfig.imports; - if (imports) { - if (ObjectPrototypeHasOwnProperty(imports, name) && - !StringPrototypeIncludes(name, '*')) { - const resolveResult = resolvePackageTarget( - packageJSONUrl, imports[name], '', name, base, false, true, false, - conditions, - ); - if (resolveResult != null) { - return resolveResult; - } - } else { - let bestMatch = ''; - let bestMatchSubpath; - const keys = ObjectGetOwnPropertyNames(imports); - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const patternIndex = StringPrototypeIndexOf(key, '*'); - if (patternIndex !== -1 && - StringPrototypeStartsWith(name, - StringPrototypeSlice(key, 0, - patternIndex))) { - const patternTrailer = StringPrototypeSlice(key, patternIndex + 1); - if (name.length >= key.length && - StringPrototypeEndsWith(name, patternTrailer) && - patternKeyCompare(bestMatch, key) === 1 && - StringPrototypeLastIndexOf(key, '*') === patternIndex) { - bestMatch = key; - bestMatchSubpath = StringPrototypeSlice( - name, patternIndex, name.length - patternTrailer.length); - } - } - } - - if (bestMatch) { - const target = imports[bestMatch]; - const resolveResult = resolvePackageTarget(packageJSONUrl, target, - bestMatchSubpath, - bestMatch, base, true, - true, false, conditions); - if (resolveResult != null) { - return resolveResult; - } - } - } - } - } - throw importNotDefined(name, packageJSONUrl, base); -} - - -/** - * Resolves a package specifier to a URL. - * @param {string} specifier - The package specifier to resolve. - * @param {string | URL | undefined} base - The base URL to use for resolution. - * @param {Set} conditions - An object containing the conditions for resolution. - * @returns {URL} - The resolved URL. - */ -function packageResolve(specifier, base, conditions) { - // TODO(@anonrig): Move this to a C++ function. - if (BuiltinModule.canBeRequiredWithoutScheme(specifier)) { - return new URL('node:' + specifier); - } - - const { packageJSONUrl, packageJSONPath, packageSubpath } = packageJsonReader.getPackageJSONURL(specifier, base); - - const packageConfig = packageJsonReader.read(packageJSONPath, { __proto__: null, specifier, base, isESM: true }); - - // Package match. - if (packageConfig.exports != null) { - return packageExportsResolve( - packageJSONUrl, packageSubpath, packageConfig, base, conditions); - } - if (packageSubpath === '.') { - return legacyMainResolve( - packageJSONUrl, - packageConfig, - base, - ); - } - - return new URL(packageSubpath, packageJSONUrl); -} - -/** - * Checks if a specifier is a bare specifier. - * @param {string} specifier - The specifier to check. - */ -function isBareSpecifier(specifier) { - return specifier[0] && specifier[0] !== '/' && specifier[0] !== '.'; -} - -/** - * Determines whether a specifier is a relative path. - * @param {string} specifier - The specifier to check. - */ -function isRelativeSpecifier(specifier) { - if (specifier[0] === '.') { - if (specifier.length === 1 || specifier[1] === '/') { return true; } - if (specifier[1] === '.') { - if (specifier.length === 2 || specifier[2] === '/') { return true; } - } - } - return false; -} - -/** - * Determines whether a specifier should be treated as a relative or absolute path. - * @param {string} specifier - The specifier to check. - */ -function shouldBeTreatedAsRelativeOrAbsolutePath(specifier) { - if (specifier === '') { return false; } - if (specifier[0] === '/') { return true; } - return isRelativeSpecifier(specifier); -} - -/** - * Resolves a module specifier to a URL. - * @param {string} specifier - The module specifier to resolve. - * @param {string | URL | undefined} base - The base URL to resolve against. - * @param {Set} conditions - An object containing environment conditions. - * @param {boolean} preserveSymlinks - Whether to preserve symlinks in the resolved URL. - */ -function moduleResolve(specifier, base, conditions, preserveSymlinks) { - const protocol = typeof base === 'string' ? - StringPrototypeSlice(base, 0, StringPrototypeIndexOf(base, ':') + 1) : - base.protocol; - const isData = protocol === 'data:'; - // Order swapped from spec for minor perf gain. - // Ok since relative URLs cannot parse as URLs. - let resolved; - if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { - try { - resolved = new URL(specifier, base); - } catch (cause) { - const error = new ERR_UNSUPPORTED_RESOLVE_REQUEST(specifier, base); - setOwnProperty(error, 'cause', cause); - throw error; - } - } else if (protocol === 'file:' && specifier[0] === '#') { - resolved = packageImportsResolve(specifier, base, conditions); - } else { - try { - resolved = new URL(specifier); - } catch (cause) { - if (isData && !BuiltinModule.canBeRequiredWithoutScheme(specifier)) { - const error = new ERR_UNSUPPORTED_RESOLVE_REQUEST(specifier, base); - setOwnProperty(error, 'cause', cause); - throw error; - } - resolved = packageResolve(specifier, base, conditions); - } - } - if (resolved.protocol !== 'file:') { - return resolved; - } - return finalizeResolution(resolved, base, preserveSymlinks); -} - -/** - * Try to resolve an import as a CommonJS module. - * @param {string} specifier - The specifier to resolve. - * @param {string} parentURL - The base URL. - * @returns {string | Buffer | false} - */ -function resolveAsCommonJS(specifier, parentURL) { - try { - const parent = fileURLToPath(parentURL); - const tmpModule = new CJSModule(parent, null); - tmpModule.paths = CJSModule._nodeModulePaths(parent); - - let found = CJSModule._resolveFilename(specifier, tmpModule, false); - - // If it is a relative specifier return the relative path - // to the parent - if (isRelativeSpecifier(specifier)) { - const foundURL = pathToFileURL(found).pathname; - found = relativePosixPath( - StringPrototypeSlice(parentURL, 'file://'.length, StringPrototypeLastIndexOf(parentURL, '/')), - foundURL); - - // Add './' if the path does not start with '../' - // This should be a safe assumption because when loading - // esm modules there should be always a file specified so - // there should not be a specifier like '..' or '.' - if (!StringPrototypeStartsWith(found, '../')) { - found = `./${found}`; - } - } else if (isBareSpecifier(specifier)) { - // If it is a bare specifier return the relative path within the - // module - const i = StringPrototypeIndexOf(specifier, '/'); - const pkg = i === -1 ? specifier : StringPrototypeSlice(specifier, 0, i); - const needle = `${sep}node_modules${sep}${pkg}${sep}`; - const index = StringPrototypeLastIndexOf(found, needle); - if (index !== -1) { - found = pkg + '/' + ArrayPrototypeJoin( - ArrayPrototypeMap( - StringPrototypeSplit(StringPrototypeSlice(found, index + needle.length), sep), - // Escape URL-special characters to avoid generating a incorrect suggestion - encodeURIComponent, - ), - '/', - ); - } else { - found = `${pathToFileURL(found)}`; - } - } - return found; - } catch { - return false; - } -} - -/** - * Validate user-input in `context` supplied by a custom loader. - * @param {string | URL | undefined} parentURL - The parent URL. - */ -function throwIfInvalidParentURL(parentURL) { - if (parentURL === undefined) { - return; // Main entry point, so no parent - } - if (typeof parentURL !== 'string' && !isURL(parentURL)) { - throw new ERR_INVALID_ARG_TYPE('parentURL', ['string', 'URL'], parentURL); - } -} - -/** - * Resolves the given specifier using the provided context, which includes the parent URL and conditions. - * Attempts to resolve the specifier and returns the resulting URL and format. - * @param {string} specifier - The specifier to resolve. - * @param {object} [context={}] - The context object containing the parent URL and conditions. - * @param {string} [context.parentURL] - The URL of the parent module. - * @param {string[]} [context.conditions] - The conditions for resolving the specifier. - */ -function defaultResolve(specifier, context = {}) { - let { parentURL, conditions } = context; - throwIfInvalidParentURL(parentURL); - - let parsedParentURL; - if (parentURL) { - parsedParentURL = URLParse(parentURL); - } - - let parsed, protocol; - if (shouldBeTreatedAsRelativeOrAbsolutePath(specifier)) { - parsed = URLParse(specifier, parsedParentURL); - } else { - parsed = URLParse(specifier); - } - - if (parsed != null) { - // Avoid accessing the `protocol` property due to the lazy getters. - protocol = parsed.protocol; - - if (protocol === 'data:') { - return { __proto__: null, url: parsed.href }; - } - } - - protocol ??= parsed?.protocol; - if (protocol === 'node:') { return { __proto__: null, url: specifier }; } - - - const isMain = parentURL === undefined; - if (isMain) { - parentURL = getCWDURL().href; - - // This is the initial entry point to the program, and --input-type has - // been passed as an option; but --input-type can only be used with - // --eval, --print or STDIN string input. It is not allowed with file - // input, to avoid user confusion over how expansive the effect of the - // flag should be (i.e. entry point only, package scope surrounding the - // entry point, etc.). - if (inputTypeFlag) { throw new ERR_INPUT_TYPE_NOT_ALLOWED(); } - } - - conditions = getConditionsSet(conditions); - let url; - try { - url = moduleResolve( - specifier, - parentURL, - conditions, - isMain ? preserveSymlinksMain : preserveSymlinks, - ); - } catch (error) { - // Try to give the user a hint of what would have been the - // resolved CommonJS module - if (error.code === 'ERR_MODULE_NOT_FOUND' || - error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') { - if (StringPrototypeStartsWith(specifier, 'file://')) { - specifier = fileURLToPath(specifier); - } - decorateErrorWithCommonJSHints(error, specifier, parentURL); - } - throw error; - } - - return { - __proto__: null, - // Do NOT cast `url` to a string: that will work even when there are real - // problems, silencing them - url: url.href, - format: defaultGetFormatWithoutErrors(url, context), - }; -} - -/** - * Decorates the given error with a hint for CommonJS modules. - * @param {Error} error - The error to decorate. - * @param {string} specifier - The specifier that was attempted to be imported. - * @param {string} parentURL - The URL of the parent module. - */ -function decorateErrorWithCommonJSHints(error, specifier, parentURL) { - const found = resolveAsCommonJS(specifier, parentURL); - if (found && found !== specifier) { // Don't suggest the same input the user provided. - // Modify the stack and message string to include the hint - const endOfFirstLine = StringPrototypeIndexOf(error.stack, '\n'); - const hint = `Did you mean to import ${JSONStringify(found)}?`; - error.stack = - StringPrototypeSlice(error.stack, 0, endOfFirstLine) + '\n' + - hint + - StringPrototypeSlice(error.stack, endOfFirstLine); - error.message += `\n${hint}`; - } -} - -module.exports = { - decorateErrorWithCommonJSHints, - defaultResolve, - encodedSepRegEx, - legacyMainResolve, - packageExportsResolve, - packageImportsResolve, - packageResolve, - throwIfInvalidParentURL, -}; - -// cycle -const { - defaultGetFormatWithoutErrors, -} = require('internal/modules/esm/get_format');