GeezerVison is showing github.com — lib: merge cjs and esm package json reader caches · nodejs/node@15530fe
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 +15-39Lines changed: 15 additions & 39 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -82,7 +82,6 @@ const { | 82 | 82 | pendingDeprecate, | 83 | 83 | emitExperimentalWarning, | 84 | 84 | kEmptyObject, | 85 | | - filterOwnProperties, | 86 | 85 | setOwnProperty, | 87 | 86 | getLazy, | 88 | 87 | } = require('internal/util'); | @@ -355,36 +354,12 @@ function initializeCJS() { | 355 | 354 | // -> a.<ext> | 356 | 355 | // -> a/index.<ext> | 357 | 356 |
| 358 | | -const packageJsonCache = new SafeMap(); | 359 | | - | | 357 | +/** | | 358 | + * @param {string} requestPath | | 359 | + * @return {PackageConfig} | | 360 | + */ | 360 | 361 | function readPackage(requestPath) { | 361 | | - const jsonPath = path.resolve(requestPath, 'package.json'); | 362 | | - | 363 | | - const existing = packageJsonCache.get(jsonPath); | 364 | | - if (existing !== undefined) return existing; | 365 | | - | 366 | | - const result = packageJsonReader.read(jsonPath); | 367 | | - const json = result.containsKeys === false ? '{}' : result.string; | 368 | | - if (json === undefined) { | 369 | | - packageJsonCache.set(jsonPath, false); | 370 | | - return false; | 371 | | - } | 372 | | - | 373 | | - try { | 374 | | - const filtered = filterOwnProperties(JSONParse(json), [ | 375 | | - 'name', | 376 | | - 'main', | 377 | | - 'exports', | 378 | | - 'imports', | 379 | | - 'type', | 380 | | - ]); | 381 | | - packageJsonCache.set(jsonPath, filtered); | 382 | | - return filtered; | 383 | | - } catch (e) { | 384 | | - e.path = jsonPath; | 385 | | - e.message = 'Error parsing ' + jsonPath + ': ' + e.message; | 386 | | - throw e; | 387 | | - } | | 362 | + return packageJsonReader.read(path.resolve(requestPath, 'package.json')); | 388 | 363 | } | 389 | 364 |
| 390 | 365 | let _readPackage = readPackage; | @@ -414,7 +389,7 @@ function readPackageScope(checkPath) { | 414 | 389 | if (StringPrototypeEndsWith(checkPath, sep + 'node_modules')) | 415 | 390 | return false; | 416 | 391 | const pjson = _readPackage(checkPath + sep); | 417 | | - if (pjson) return { | | 392 | + if (pjson.exists) return { | 418 | 393 | data: pjson, | 419 | 394 | path: checkPath, | 420 | 395 | }; | @@ -423,7 +398,7 @@ function readPackageScope(checkPath) { | 423 | 398 | } | 424 | 399 |
| 425 | 400 | function tryPackage(requestPath, exts, isMain, originalPath) { | 426 | | - const pkg = _readPackage(requestPath)?.main; | | 401 | + const pkg = _readPackage(requestPath).main; | 427 | 402 |
| 428 | 403 | if (!pkg) { | 429 | 404 | return tryExtensions(path.resolve(requestPath, 'index'), exts, isMain); | @@ -528,9 +503,10 @@ function trySelfParentPath(parent) { | 528 | 503 | function trySelf(parentPath, request) { | 529 | 504 | if (!parentPath) return false; | 530 | 505 |
| 531 | | - const { data: pkg, path: pkgPath } = readPackageScope(parentPath) || {}; | 532 | | - if (!pkg || pkg.exports === undefined) return false; | 533 | | - if (typeof pkg.name !== 'string') return false; | | 506 | + const { data: pkg, path: pkgPath } = readPackageScope(parentPath); | | 507 | + if (!pkg || pkg.exports == null || pkg.name === undefined) { | | 508 | + return false; | | 509 | + } | 534 | 510 |
| 535 | 511 | let expansion; | 536 | 512 | if (request === pkg.name) { | @@ -565,7 +541,7 @@ function resolveExports(nmPath, request) { | 565 | 541 | return; | 566 | 542 | const pkgPath = path.resolve(nmPath, name); | 567 | 543 | const pkg = _readPackage(pkgPath); | 568 | | - if (pkg?.exports != null) { | | 544 | + if (pkg.exists && pkg.exports != null) { | 569 | 545 | try { | 570 | 546 | const { packageExportsResolve } = require('internal/modules/esm/resolve'); | 571 | 547 | return finalizeEsmResolution(packageExportsResolve( | @@ -1028,7 +1004,7 @@ Module._resolveFilename = function(request, parent, isMain, options) { | 1028 | 1004 |
| 1029 | 1005 | if (request[0] === '#' && (parent?.filename || parent?.id === '<repl>')) { | 1030 | 1006 | const parentPath = parent?.filename ?? process.cwd() + path.sep; | 1031 | | - const pkg = readPackageScope(parentPath) || {}; | | 1007 | + const pkg = readPackageScope(parentPath) || { __proto__: null }; | 1032 | 1008 | if (pkg.data?.imports != null) { | 1033 | 1009 | try { | 1034 | 1010 | const { packageImportsResolve } = require('internal/modules/esm/resolve'); | @@ -1274,9 +1250,9 @@ Module._extensions['.js'] = function(module, filename) { | 1274 | 1250 | content = fs.readFileSync(filename, 'utf8'); | 1275 | 1251 | } | 1276 | 1252 | if (StringPrototypeEndsWith(filename, '.js')) { | 1277 | | - const pkg = readPackageScope(filename); | | 1253 | + const pkg = readPackageScope(filename) || { __proto__: null }; | 1278 | 1254 | // Function require shouldn't be used in ES modules. | 1279 | | - if (pkg?.data?.type === 'module') { | | 1255 | + if (pkg.data?.type === 'module') { | 1280 | 1256 | const parent = moduleParentCache.get(module); | 1281 | 1257 | const parentPath = parent?.filename; | 1282 | 1258 | const packageJsonPath = path.resolve(pkg.path, 'package.json'); | |
Collapse file Copy file name to clipboard +8-98Lines changed: 8 additions & 98 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 1 | 1 | 'use strict'; | 2 | 2 |
| 3 | 3 | const { | 4 | | - JSONParse, | 5 | | - ObjectPrototypeHasOwnProperty, | 6 | | - SafeMap, | 7 | 4 | StringPrototypeEndsWith, | 8 | 5 | } = primordials; | 9 | 6 | const { URL, fileURLToPath } = require('internal/url'); | 10 | | -const { | 11 | | - ERR_INVALID_PACKAGE_CONFIG, | 12 | | -} = require('internal/errors').codes; | 13 | | - | 14 | | -const { filterOwnProperties } = require('internal/util'); | 15 | | - | 16 | | - | 17 | | -/** | 18 | | - * @typedef {string | string[] | Record<string, unknown>} Exports | 19 | | - * @typedef {'module' | 'commonjs'} PackageType | 20 | | - * @typedef {{ | 21 | | - * pjsonPath: string, | 22 | | - * exports?: ExportConfig, | 23 | | - * name?: string, | 24 | | - * main?: string, | 25 | | - * type?: PackageType, | 26 | | - * }} PackageConfig | 27 | | - */ | 28 | | - | 29 | | -/** @type {Map<string, PackageConfig>} */ | 30 | | -const packageJSONCache = new SafeMap(); | 31 | | - | 32 | | - | 33 | | -/** | 34 | | - * @param {string} path | 35 | | - * @param {string} specifier | 36 | | - * @param {string | URL | undefined} base | 37 | | - * @returns {PackageConfig} | 38 | | - */ | 39 | | -function getPackageConfig(path, specifier, base) { | 40 | | - const existing = packageJSONCache.get(path); | 41 | | - if (existing !== undefined) { | 42 | | - return existing; | 43 | | - } | 44 | | - const packageJsonReader = require('internal/modules/package_json_reader'); | 45 | | - const source = packageJsonReader.read(path).string; | 46 | | - if (source === undefined) { | 47 | | - const packageConfig = { | 48 | | - pjsonPath: path, | 49 | | - exists: false, | 50 | | - main: undefined, | 51 | | - name: undefined, | 52 | | - type: 'none', | 53 | | - exports: undefined, | 54 | | - imports: undefined, | 55 | | - }; | 56 | | - packageJSONCache.set(path, packageConfig); | 57 | | - return packageConfig; | 58 | | - } | 59 | | - | 60 | | - let packageJSON; | 61 | | - try { | 62 | | - packageJSON = JSONParse(source); | 63 | | - } catch (error) { | 64 | | - throw new ERR_INVALID_PACKAGE_CONFIG( | 65 | | - path, | 66 | | - (base ? `"${specifier}" from ` : '') + fileURLToPath(base || specifier), | 67 | | - error.message, | 68 | | - ); | 69 | | - } | 70 | | - | 71 | | - let { imports, main, name, type } = filterOwnProperties(packageJSON, ['imports', 'main', 'name', 'type']); | 72 | | - const exports = ObjectPrototypeHasOwnProperty(packageJSON, 'exports') ? packageJSON.exports : undefined; | 73 | | - if (typeof imports !== 'object' || imports === null) { | 74 | | - imports = undefined; | 75 | | - } | 76 | | - if (typeof main !== 'string') { | 77 | | - main = undefined; | 78 | | - } | 79 | | - if (typeof name !== 'string') { | 80 | | - name = undefined; | 81 | | - } | 82 | | - // Ignore unknown types for forwards compatibility | 83 | | - if (type !== 'module' && type !== 'commonjs') { | 84 | | - type = 'none'; | 85 | | - } | 86 | | - | 87 | | - const packageConfig = { | 88 | | - pjsonPath: path, | 89 | | - exists: true, | 90 | | - main, | 91 | | - name, | 92 | | - type, | 93 | | - exports, | 94 | | - imports, | 95 | | - }; | 96 | | - packageJSONCache.set(path, packageConfig); | 97 | | - return packageConfig; | 98 | | -} | 99 | | - | | 7 | +const packageJsonReader = require('internal/modules/package_json_reader'); | 100 | 8 |
| 101 | 9 | /** | 102 | 10 | * @param {URL | string} resolved | @@ -109,7 +17,11 @@ function getPackageScopeConfig(resolved) { | 109 | 17 | if (StringPrototypeEndsWith(packageJSONPath, 'node_modules/package.json')) { | 110 | 18 | break; | 111 | 19 | } | 112 | | - const packageConfig = getPackageConfig(fileURLToPath(packageJSONUrl), resolved); | | 20 | + const packageConfig = packageJsonReader.read(fileURLToPath(packageJSONUrl), { | | 21 | + __proto__: null, | | 22 | + specifier: resolved, | | 23 | + isESM: true, | | 24 | + }); | 113 | 25 | if (packageConfig.exists) { | 114 | 26 | return packageConfig; | 115 | 27 | } | @@ -124,7 +36,8 @@ function getPackageScopeConfig(resolved) { | 124 | 36 | } | 125 | 37 | } | 126 | 38 | const packageJSONPath = fileURLToPath(packageJSONUrl); | 127 | | - const packageConfig = { | | 39 | + return { | | 40 | + __proto__: null, | 128 | 41 | pjsonPath: packageJSONPath, | 129 | 42 | exists: false, | 130 | 43 | main: undefined, | @@ -133,12 +46,9 @@ function getPackageScopeConfig(resolved) { | 133 | 46 | exports: undefined, | 134 | 47 | imports: undefined, | 135 | 48 | }; | 136 | | - packageJSONCache.set(packageJSONPath, packageConfig); | 137 | | - return packageConfig; | 138 | 49 | } | 139 | 50 |
| 140 | 51 |
| 141 | 52 | module.exports = { | 142 | | - getPackageConfig, | 143 | 53 | getPackageScopeConfig, | 144 | 54 | }; |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/modules/esm/resolve.js +5-5Lines changed: 5 additions & 5 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -53,8 +53,9 @@ const { | 53 | 53 | } = require('internal/errors').codes; | 54 | 54 |
| 55 | 55 | const { Module: CJSModule } = require('internal/modules/cjs/loader'); | 56 | | -const { getPackageConfig, getPackageScopeConfig } = require('internal/modules/esm/package_config'); | | 56 | +const { getPackageScopeConfig } = require('internal/modules/esm/package_config'); | 57 | 57 | const { getConditionsSet } = require('internal/modules/esm/utils'); | | 58 | +const packageJsonReader = require('internal/modules/package_json_reader'); | 58 | 59 | const { internalModuleStat } = internalBinding('fs'); | 59 | 60 |
| 60 | 61 | /** | @@ -734,8 +735,7 @@ function packageResolve(specifier, base, conditions) { | 734 | 735 | const packageConfig = getPackageScopeConfig(base); | 735 | 736 | if (packageConfig.exists) { | 736 | 737 | const packageJSONUrl = pathToFileURL(packageConfig.pjsonPath); | 737 | | - if (packageConfig.name === packageName && | 738 | | - packageConfig.exports !== undefined && packageConfig.exports !== null) { | | 738 | + if (packageConfig.exports != null && packageConfig.name === packageName) { | 739 | 739 | return packageExportsResolve( | 740 | 740 | packageJSONUrl, packageSubpath, packageConfig, base, conditions); | 741 | 741 | } | @@ -759,8 +759,8 @@ function packageResolve(specifier, base, conditions) { | 759 | 759 | } | 760 | 760 |
| 761 | 761 | // Package match. | 762 | | - const packageConfig = getPackageConfig(packageJSONPath, specifier, base); | 763 | | - if (packageConfig.exports !== undefined && packageConfig.exports !== null) { | | 762 | + const packageConfig = packageJsonReader.read(packageJSONPath, { __proto__: null, specifier, base, isESM: true }); | | 763 | + if (packageConfig.exports != null) { | 764 | 764 | return packageExportsResolve( | 765 | 765 | packageJSONUrl, packageSubpath, packageConfig, base, conditions); | 766 | 766 | } | |
|