From 86087c7bfcbe1480757a3c9f3656e954d6576f2d Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 7 Nov 2024 20:02:06 -0500 Subject: [PATCH] fix(@angular/build): avoid overwriting inline style bundling additional results A component may contain multiple inline styles that will originate from the same containing file. The content of the processed style is sent directly to the Angular compiler. However, any additional result files are collected and emitted in the application output. In most cases, this worked as expected as inline styles rarely had resource references that would overwrite each other. However, the potential is present for later inline styles for a component to overwrite these output files. To avoid this potential problem, the internal identifier now accounts for both the class name and order of the inline styles. This ensures that each inline style retains a unique additional results entry. --- .../src/tools/esbuild/angular/compiler-plugin.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts index 34133ab8e283..e7964cfe43ac 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts @@ -153,7 +153,6 @@ export function createCompilerPlugin( let modifiedFiles; if ( pluginOptions.sourceFileCache?.modifiedFiles.size && - referencedFileTracker && !pluginOptions.noopTypeScriptCompilation ) { // TODO: Differentiate between changed input files and stale output files @@ -164,6 +163,8 @@ export function createCompilerPlugin( if (!pluginOptions.externalRuntimeStyles) { stylesheetBundler.invalidate(modifiedFiles); } + // Remove any stale additional results based on modified files + modifiedFiles.forEach((file) => additionalResults.delete(file)); } if ( @@ -181,6 +182,7 @@ export function createCompilerPlugin( sourceFileCache: pluginOptions.sourceFileCache, async transformStylesheet(data, containingFile, stylesheetFile, order, className) { let stylesheetResult; + let resultSource = stylesheetFile ?? containingFile; // Stylesheet file only exists for external stylesheets if (stylesheetFile) { @@ -203,6 +205,11 @@ export function createCompilerPlugin( .digest('hex') : undefined, ); + // Adjust result source for inline styles. + // There may be multiple inline styles with the same containing file and to ensure that the results + // do not overwrite each other the result source identifier needs to be unique for each. The class + // name and order fields can be used for this. The structure is arbitrary as long as it is unique. + resultSource += `?class=${className}&order=${order}`; } (result.warnings ??= []).push(...stylesheetResult.warnings); @@ -213,7 +220,7 @@ export function createCompilerPlugin( } const { contents, outputFiles, metafile, referencedFiles } = stylesheetResult; - additionalResults.set(stylesheetFile ?? containingFile, { + additionalResults.set(resultSource, { outputFiles, metafile, });