GeezerVison is showing github.com — module: move helpers out of cjs loader · nodejs/node@2ff4e71
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js +6-66Lines changed: 6 additions & 66 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -55,7 +55,6 @@ const { | 55 | 55 | StringPrototypeCharAt, | 56 | 56 | StringPrototypeCharCodeAt, | 57 | 57 | StringPrototypeEndsWith, | 58 | | - StringPrototypeLastIndexOf, | 59 | 58 | StringPrototypeIndexOf, | 60 | 59 | StringPrototypeRepeat, | 61 | 60 | StringPrototypeSlice, | @@ -68,7 +67,7 @@ const cjsParseCache = new SafeWeakMap(); | 68 | 67 |
| 69 | 68 | // Set first due to cycle with ESM loader functions. | 70 | 69 | module.exports = { | 71 | | - wrapSafe, Module, toRealPath, readPackageScope, cjsParseCache, | | 70 | + wrapSafe, Module, cjsParseCache, | 72 | 71 | get hasLoadedAnyUserCJSModule() { return hasLoadedAnyUserCJSModule; }, | 73 | 72 | initializeCJS, | 74 | 73 | }; | @@ -88,9 +87,7 @@ const { | 88 | 87 | const { internalCompileFunction } = require('internal/vm'); | 89 | 88 | const assert = require('internal/assert'); | 90 | 89 | const fs = require('fs'); | 91 | | -const internalFS = require('internal/fs/utils'); | 92 | 90 | const path = require('path'); | 93 | | -const { sep } = path; | 94 | 91 | const { internalModuleStat } = internalBinding('fs'); | 95 | 92 | const { safeGetenv } = internalBinding('credentials'); | 96 | 93 | const { | @@ -106,6 +103,7 @@ const { | 106 | 103 | makeRequireFunction, | 107 | 104 | normalizeReferrerURL, | 108 | 105 | stripBOM, | | 106 | + toRealPath, | 109 | 107 | } = require('internal/modules/helpers'); | 110 | 108 | const packageJsonReader = require('internal/modules/package_json_reader'); | 111 | 109 | const { getOptionValue, getEmbedderOptions } = require('internal/options'); | @@ -403,15 +401,7 @@ function initializeCJS() { | 403 | 401 | // -> a.<ext> | 404 | 402 | // -> a/index.<ext> | 405 | 403 |
| 406 | | -/** | 407 | | - * @param {string} requestPath | 408 | | - * @return {PackageConfig} | 409 | | - */ | 410 | | -function readPackage(requestPath) { | 411 | | - return packageJsonReader.read(path.resolve(requestPath, 'package.json')); | 412 | | -} | 413 | | - | 414 | | -let _readPackage = readPackage; | | 404 | +let _readPackage = packageJsonReader.readPackage; | 415 | 405 | ObjectDefineProperty(Module, '_readPackage', { | 416 | 406 | __proto__: null, | 417 | 407 | get() { return _readPackage; }, | @@ -423,37 +413,6 @@ ObjectDefineProperty(Module, '_readPackage', { | 423 | 413 | configurable: true, | 424 | 414 | }); | 425 | 415 |
| 426 | | -/** | 427 | | - * Get the nearest parent package.json file from a given path. | 428 | | - * Return the package.json data and the path to the package.json file, or false. | 429 | | - * @param {string} checkPath The path to start searching from. | 430 | | - */ | 431 | | -function readPackageScope(checkPath) { | 432 | | - const rootSeparatorIndex = StringPrototypeIndexOf(checkPath, sep); | 433 | | - let separatorIndex; | 434 | | - const enabledPermission = permission.isEnabled(); | 435 | | - do { | 436 | | - separatorIndex = StringPrototypeLastIndexOf(checkPath, sep); | 437 | | - checkPath = StringPrototypeSlice(checkPath, 0, separatorIndex); | 438 | | - // Stop the search when the process doesn't have permissions | 439 | | - // to walk upwards | 440 | | - if (enabledPermission && !permission.has('fs.read', checkPath + sep)) { | 441 | | - return false; | 442 | | - } | 443 | | - if (StringPrototypeEndsWith(checkPath, sep + 'node_modules')) { | 444 | | - return false; | 445 | | - } | 446 | | - const pjson = _readPackage(checkPath + sep); | 447 | | - if (pjson.exists) { | 448 | | - return { | 449 | | - data: pjson, | 450 | | - path: checkPath, | 451 | | - }; | 452 | | - } | 453 | | - } while (separatorIndex > rootSeparatorIndex); | 454 | | - return false; | 455 | | -} | 456 | | - | 457 | 416 | /** | 458 | 417 | * Try to load a specifier as a package. | 459 | 418 | * @param {string} requestPath The path to what we are trying to load | @@ -498,14 +457,6 @@ function tryPackage(requestPath, exts, isMain, originalPath) { | 498 | 457 | return actual; | 499 | 458 | } | 500 | 459 |
| 501 | | -/** | 502 | | - * Cache for storing resolved real paths of modules. | 503 | | - * In order to minimize unnecessary lstat() calls, this cache is a list of known-real paths. | 504 | | - * Set to an empty Map to reset. | 505 | | - * @type {Map<string, string>} | 506 | | - */ | 507 | | -const realpathCache = new SafeMap(); | 508 | | - | 509 | 460 | /** | 510 | 461 | * Check if the file exists and is not a directory if using `--preserve-symlinks` and `isMain` is false, keep symlinks | 511 | 462 | * intact, otherwise resolve to the absolute realpath. | @@ -521,17 +472,6 @@ function tryFile(requestPath, isMain) { | 521 | 472 | return toRealPath(requestPath); | 522 | 473 | } | 523 | 474 |
| 524 | | - | 525 | | -/** | 526 | | - * Resolves the path of a given `require` specifier, following symlinks. | 527 | | - * @param {string} requestPath The `require` specifier | 528 | | - */ | 529 | | -function toRealPath(requestPath) { | 530 | | - return fs.realpathSync(requestPath, { | 531 | | - [internalFS.realpathCacheKey]: realpathCache, | 532 | | - }); | 533 | | -} | 534 | | - | 535 | 475 | /** | 536 | 476 | * Given a path, check if the file exists with any of the set extensions. | 537 | 477 | * @param {string} basePath The path and filename without extension | @@ -593,7 +533,7 @@ function trySelfParentPath(parent) { | 593 | 533 | function trySelf(parentPath, request) { | 594 | 534 | if (!parentPath) { return false; } | 595 | 535 |
| 596 | | - const { data: pkg, path: pkgPath } = readPackageScope(parentPath); | | 536 | + const { data: pkg, path: pkgPath } = packageJsonReader.readPackageScope(parentPath); | 597 | 537 | if (!pkg || pkg.exports == null || pkg.name === undefined) { | 598 | 538 | return false; | 599 | 539 | } | @@ -1153,7 +1093,7 @@ Module._resolveFilename = function(request, parent, isMain, options) { | 1153 | 1093 |
| 1154 | 1094 | if (request[0] === '#' && (parent?.filename || parent?.id === '<repl>')) { | 1155 | 1095 | const parentPath = parent?.filename ?? process.cwd() + path.sep; | 1156 | | - const pkg = readPackageScope(parentPath) || { __proto__: null }; | | 1096 | + const pkg = packageJsonReader.readPackageScope(parentPath) || { __proto__: null }; | 1157 | 1097 | if (pkg.data?.imports != null) { | 1158 | 1098 | try { | 1159 | 1099 | const { packageImportsResolve } = require('internal/modules/esm/resolve'); | @@ -1450,7 +1390,7 @@ Module._extensions['.js'] = function(module, filename) { | 1450 | 1390 | content = fs.readFileSync(filename, 'utf8'); | 1451 | 1391 | } | 1452 | 1392 | if (StringPrototypeEndsWith(filename, '.js')) { | 1453 | | - const pkg = readPackageScope(filename) || { __proto__: null }; | | 1393 | + const pkg = packageJsonReader.readPackageScope(filename) || { __proto__: null }; | 1454 | 1394 | // Function require shouldn't be used in ES modules. | 1455 | 1395 | if (pkg.data?.type === 'module') { | 1456 | 1396 | const parent = moduleParentCache.get(module); | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/helpers.js +20Lines changed: 20 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -21,6 +21,8 @@ const { | 21 | 21 | const { BuiltinModule } = require('internal/bootstrap/realm'); | 22 | 22 |
| 23 | 23 | const { validateString } = require('internal/validators'); | | 24 | +const fs = require('fs'); // Import all of `fs` so that it can be monkey-patched. | | 25 | +const internalFS = require('internal/fs/utils'); | 24 | 26 | const path = require('path'); | 25 | 27 | const { pathToFileURL, fileURLToPath, URL } = require('internal/url'); | 26 | 28 |
| @@ -39,6 +41,23 @@ let debug = require('internal/util/debuglog').debuglog('module', (fn) => { | 39 | 41 |
| 40 | 42 | /** @typedef {import('internal/modules/cjs/loader.js').Module} Module */ | 41 | 43 |
| | 44 | +/** | | 45 | + * Cache for storing resolved real paths of modules. | | 46 | + * In order to minimize unnecessary lstat() calls, this cache is a list of known-real paths. | | 47 | + * Set to an empty Map to reset. | | 48 | + * @type {Map<string, string>} | | 49 | + */ | | 50 | +const realpathCache = new SafeMap(); | | 51 | +/** | | 52 | + * Resolves the path of a given `require` specifier, following symlinks. | | 53 | + * @param {string} requestPath The `require` specifier | | 54 | + */ | | 55 | +function toRealPath(requestPath) { | | 56 | + return fs.realpathSync(requestPath, { | | 57 | + [internalFS.realpathCacheKey]: realpathCache, | | 58 | + }); | | 59 | +} | | 60 | + | 42 | 61 | /** @type {Set<string>} */ | 43 | 62 | let cjsConditions; | 44 | 63 | /** | @@ -310,4 +329,5 @@ module.exports = { | 310 | 329 | makeRequireFunction, | 311 | 330 | normalizeReferrerURL, | 312 | 331 | stripBOM, | | 332 | + toRealPath, | 313 | 333 | }; |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/package_json_reader.js +50-2Lines changed: 50 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -4,12 +4,17 @@ const { | 4 | 4 | JSONParse, | 5 | 5 | ObjectPrototypeHasOwnProperty, | 6 | 6 | SafeMap, | | 7 | + StringPrototypeEndsWith, | | 8 | + StringPrototypeIndexOf, | | 9 | + StringPrototypeLastIndexOf, | | 10 | + StringPrototypeSlice, | 7 | 11 | } = primordials; | 8 | 12 | const { | 9 | 13 | ERR_INVALID_PACKAGE_CONFIG, | 10 | 14 | } = require('internal/errors').codes; | 11 | 15 | const { internalModuleReadJSON } = internalBinding('fs'); | 12 | | -const { toNamespacedPath } = require('path'); | | 16 | +const { resolve, sep, toNamespacedPath } = require('path'); | | 17 | +const permission = require('internal/process/permission'); | 13 | 18 | const { kEmptyObject } = require('internal/util'); | 14 | 19 |
| 15 | 20 | const { fileURLToPath, pathToFileURL } = require('internal/url'); | @@ -128,4 +133,47 @@ function read(jsonPath, { base, specifier, isESM } = kEmptyObject) { | 128 | 133 | return result; | 129 | 134 | } | 130 | 135 |
| 131 | | -module.exports = { read }; | | 136 | +/** | | 137 | + * @param {string} requestPath | | 138 | + * @return {PackageConfig} | | 139 | + */ | | 140 | +function readPackage(requestPath) { | | 141 | + return read(resolve(requestPath, 'package.json')); | | 142 | +} | | 143 | + | | 144 | +/** | | 145 | + * Get the nearest parent package.json file from a given path. | | 146 | + * Return the package.json data and the path to the package.json file, or false. | | 147 | + * @param {string} checkPath The path to start searching from. | | 148 | + */ | | 149 | +function readPackageScope(checkPath) { | | 150 | + const rootSeparatorIndex = StringPrototypeIndexOf(checkPath, sep); | | 151 | + let separatorIndex; | | 152 | + const enabledPermission = permission.isEnabled(); | | 153 | + do { | | 154 | + separatorIndex = StringPrototypeLastIndexOf(checkPath, sep); | | 155 | + checkPath = StringPrototypeSlice(checkPath, 0, separatorIndex); | | 156 | + // Stop the search when the process doesn't have permissions | | 157 | + // to walk upwards | | 158 | + if (enabledPermission && !permission.has('fs.read', checkPath + sep)) { | | 159 | + return false; | | 160 | + } | | 161 | + if (StringPrototypeEndsWith(checkPath, sep + 'node_modules')) { | | 162 | + return false; | | 163 | + } | | 164 | + const pjson = readPackage(checkPath + sep); | | 165 | + if (pjson.exists) { | | 166 | + return { | | 167 | + data: pjson, | | 168 | + path: checkPath, | | 169 | + }; | | 170 | + } | | 171 | + } while (separatorIndex > rootSeparatorIndex); | | 172 | + return false; | | 173 | +} | | 174 | + | | 175 | +module.exports = { | | 176 | + read, | | 177 | + readPackage, | | 178 | + readPackageScope, | | 179 | +}; |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/run_main.js +3-2Lines changed: 3 additions & 2 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -15,12 +15,13 @@ function resolveMainPath(main) { | 15 | 15 | // Note extension resolution for the main entry point can be deprecated in a | 16 | 16 | // future major. | 17 | 17 | // Module._findPath is monkey-patchable here. | 18 | | - const { Module, toRealPath } = require('internal/modules/cjs/loader'); | | 18 | + const { Module } = require('internal/modules/cjs/loader'); | 19 | 19 | let mainPath = Module._findPath(path.resolve(main), null, true); | 20 | 20 | if (!mainPath) { return; } | 21 | 21 |
| 22 | 22 | const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main'); | 23 | 23 | if (!preserveSymlinksMain) { | | 24 | + const { toRealPath } = require('internal/modules/helpers'); | 24 | 25 | mainPath = toRealPath(mainPath); | 25 | 26 | } | 26 | 27 |
| @@ -48,7 +49,7 @@ function shouldUseESMLoader(mainPath) { | 48 | 49 | if (mainPath && StringPrototypeEndsWith(mainPath, '.mjs')) { return true; } | 49 | 50 | if (!mainPath || StringPrototypeEndsWith(mainPath, '.cjs')) { return false; } | 50 | 51 |
| 51 | | - const { readPackageScope } = require('internal/modules/cjs/loader'); | | 52 | + const { readPackageScope } = require('internal/modules/package_json_reader'); | 52 | 53 | const pkg = readPackageScope(mainPath); | 53 | 54 | // No need to guard `pkg` as it can only be an object or `false`. | 54 | 55 | return pkg.data?.type === 'module' || getOptionValue('--experimental-default-type') === 'module'; | |
|