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