Skip to content

Commit de177e3

Browse files
authored
Pass file path with runtime version to hash generator (#27835)
Description This pull request addresses an issue reported by users in #27752 in which the integrity checks that occur in the browser for assemblies loaded by a Blazor WebAssembly application incorrectly fail after a user upgrades their application from one version to another. This occurs because our MSBuild targets don't correctly update the compressed assemblies when a user upgrades, which results in the non-compressed assemblies and integrity hash pointing to the new version but the compressed assembly pointing to the old version which causes an integrity check failure. Technical Description The GzipCompression task iterates through a list of provided FilesToCompress and determines whether or not a file needs to be updated by checking to see if the input file is older than the compressed file that already exists in the intermediate output path. aspnetcore/src/Components/WebAssembly/Sdk/src/GZipCompress.cs Lines 45 to 50 in 45540f7 if (File.Exists(outputRelativePath) && File.GetLastWriteTimeUtc(inputPath) < File.GetLastWriteTimeUtc(outputRelativePath)) { // Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing. Log.LogMessage(MessageImportance.Low, $"Skipping '{inputPath}' because '{outputRelativePath}' is newer than '{inputPath}'."); return; } The outputRelativePath used in the comparison above is a hashed value generated from the the RelativePath which is set to wwwroot/_framework/Microsoft.CSharp.dll for example. If a user changes from version 5.0-rc2 to 5.0 of a package, then the RelativePath will be the same whereas the FullPath will be ~/.nuget/packages/microsoft.netcore.app.runtime.browser-wasm/5.0.0/runtimes/browser-wasm/lib/net5.0/Microsoft.CSharp.dll compared to /Users/captainsafia/.nuget/packages/microsoft.netcore.app.runtime.browser-wasm/5.0.0-rc.2.20475.5/runtimes/browser-wasm/lib/net5.0/Microsoft.CSharp.dll. By passing the FullPath we are able to account for the package version in the generated output which will cause a unique hash to be generated for different package versions and the File.Exists check in the conditional to fail and result in the new gzipped outputs being generated as expected. Customer Impact This bug was reported by multiple customers after the release of .NET 5. The bug makes the upgrade experience between .NET versions a lot rougher since users run into unexpected exceptions in their apps at runtime. Viable workarounds for this include running dotnet clean before building the project after an upgrade. Regression? This is not a regression, but the issue is more serious since users are upgrading from Blazor WASM 3.2 to Blazor WASM 5 or from a 5.0 RC to the RTM. Risk The risk associated with this change is relatively slim, because: Manually validation was completed The behavior implemented in the changeset mimicks what we already do in the Brotli compression The impact area is only limited to Blazor WASM apps running in development
1 parent 65192fa commit de177e3

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

src/Components/WebAssembly/Sdk/src/GZipCompress.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,26 @@ public override bool Execute()
3232
System.Threading.Tasks.Parallel.For(0, FilesToCompress.Length, i =>
3333
{
3434
var file = FilesToCompress[i];
35-
var inputPath = file.ItemSpec;
35+
var inputFullPath = file.GetMetadata("FullPath");
3636
var relativePath = file.GetMetadata("RelativePath");
3737
var outputRelativePath = Path.Combine(
3838
OutputDirectory,
39-
BrotliCompress.CalculateTargetPath(relativePath, ".gz"));
39+
BrotliCompress.CalculateTargetPath(inputFullPath, ".gz"));
4040

4141
var outputItem = new TaskItem(outputRelativePath);
4242
outputItem.SetMetadata("RelativePath", relativePath + ".gz");
4343
CompressedFiles[i] = outputItem;
4444

45-
if (File.Exists(outputRelativePath) && File.GetLastWriteTimeUtc(inputPath) < File.GetLastWriteTimeUtc(outputRelativePath))
45+
if (File.Exists(outputRelativePath) && File.GetLastWriteTimeUtc(inputFullPath) < File.GetLastWriteTimeUtc(outputRelativePath))
4646
{
4747
// Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing.
48-
Log.LogMessage(MessageImportance.Low, $"Skipping '{inputPath}' because '{outputRelativePath}' is newer than '{inputPath}'.");
48+
Log.LogMessage(MessageImportance.Low, $"Skipping '{file.ItemSpec}' because '{outputRelativePath}' is newer than '{file.ItemSpec}'.");
4949
return;
5050
}
5151

5252
try
5353
{
54-
using var sourceStream = File.OpenRead(inputPath);
54+
using var sourceStream = File.OpenRead(file.ItemSpec);
5555
using var fileStream = File.Create(outputRelativePath);
5656
using var stream = new GZipStream(fileStream, CompressionLevel.Optimal);
5757

0 commit comments

Comments
 (0)