From a041820211f2a7ab31824b9c603e88b38d3c8982 Mon Sep 17 00:00:00 2001 From: David Michon Date: Tue, 26 Aug 2025 20:31:18 +0000 Subject: [PATCH] [rush-resolver-cache] Fix bundledDependencies --- ...resolver-cache-cache_2025-08-26-20-18.json | 10 +++++ .../src/afterInstallAsync.ts | 38 ++++++++++++++----- 2 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 common/changes/@microsoft/rush/resolver-cache-cache_2025-08-26-20-18.json diff --git a/common/changes/@microsoft/rush/resolver-cache-cache_2025-08-26-20-18.json b/common/changes/@microsoft/rush/resolver-cache-cache_2025-08-26-20-18.json new file mode 100644 index 00000000000..bd7ff97cb34 --- /dev/null +++ b/common/changes/@microsoft/rush/resolver-cache-cache_2025-08-26-20-18.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/rush-plugins/rush-resolver-cache-plugin/src/afterInstallAsync.ts b/rush-plugins/rush-resolver-cache-plugin/src/afterInstallAsync.ts index 118159e5601..f8557042abc 100644 --- a/rush-plugins/rush-resolver-cache-plugin/src/afterInstallAsync.ts +++ b/rush-plugins/rush-resolver-cache-plugin/src/afterInstallAsync.ts @@ -41,9 +41,11 @@ function getPlatformInfo(): IPlatformInfo { } const END_TOKEN: string = '/package.json":'; +const SUBPACKAGE_CACHE_FILE_VERSION: 1 = 1; interface INestedPackageJsonCache { subPackagesByIntegrity: [string, string[] | boolean][]; + version: number; } /** @@ -93,8 +95,14 @@ export async function afterInstallAsync( try { const cacheContent: string = await FileSystem.readFileAsync(subPackageCacheFilePath); const cacheJson: INestedPackageJsonCache = JSON.parse(cacheContent); - oldSubPackagesByIntegrity = new Map(cacheJson.subPackagesByIntegrity); - terminal.writeLine(`Loaded subpackage cache from ${subPackageCacheFilePath}`); + if (cacheJson.version !== SUBPACKAGE_CACHE_FILE_VERSION) { + terminal.writeLine( + `Expected subpackage cache version ${SUBPACKAGE_CACHE_FILE_VERSION}, got ${cacheJson.version}` + ); + } else { + oldSubPackagesByIntegrity = new Map(cacheJson.subPackagesByIntegrity); + terminal.writeLine(`Loaded subpackage cache from ${subPackageCacheFilePath}`); + } } catch (err) { // Ignore } @@ -196,8 +204,9 @@ export async function afterInstallAsync( terminal.writeDebugLine( `Nested "package.json" files found for package at ${descriptionFileRoot}: ${result.join(', ')}` ); + // Clone this array to ensure that mutations don't affect the subpackage cache. // eslint-disable-next-line require-atomic-updates - context.nestedPackageDirs = result; + context.nestedPackageDirs = [...result]; } } @@ -209,6 +218,21 @@ export async function afterInstallAsync( }); } + // Serialize this before `computeResolverCacheFromLockfileAsync` because bundledDependencies get removed + // from the `nestedPackageDirs` array. We clone above for safety, but this is making doubly sure. + const newSubPackageCache: INestedPackageJsonCache = { + version: SUBPACKAGE_CACHE_FILE_VERSION, + subPackagesByIntegrity: Array.from(subPackagesByIntegrity) + }; + const serializedSubpackageCache: string = JSON.stringify(newSubPackageCache); + const writeSubPackageCachePromise: Promise = FileSystem.writeFileAsync( + subPackageCacheFilePath, + serializedSubpackageCache, + { + ensureFolderExists: true + } + ); + const cacheFile: IResolverCacheFile = await computeResolverCacheFromLockfileAsync({ workspaceRoot, commonPrefixToTrim: rushRoot, @@ -218,19 +242,13 @@ export async function afterInstallAsync( afterExternalPackagesAsync }); - const newSubPackageCache: string = JSON.stringify({ - subPackagesByIntegrity: Array.from(subPackagesByIntegrity) - }); - const serialized: string = JSON.stringify(cacheFile); await Promise.all([ FileSystem.writeFileAsync(cacheFilePath, serialized, { ensureFolderExists: true }), - FileSystem.writeFileAsync(subPackageCacheFilePath, newSubPackageCache, { - ensureFolderExists: true - }) + writeSubPackageCachePromise ]); terminal.writeLine(`Resolver cache written.`);