Skip to content

Commit

Permalink
[browser] Fix fingerprinting of relinked dotnet.js during build (#86048)
Browse files Browse the repository at this point in the history
* Fix reading version of relinked dotnet.js during build
* Support .NET 7 file name
* Add WBT test
* Fix publish fingerprinting
* ConvertDllsToWebCil: fix path concatenation

---------

Co-authored-by: Ankit Jain <[email protected]>
  • Loading branch information
maraf and radical authored Jun 2, 2023
1 parent 8ee61fe commit 4a2f9d3
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,15 @@ Copyright (c) .NET Foundation. All rights reserved.
<Target Name="_ResolveWasmOutputs" DependsOnTargets="ResolveReferences;PrepareResourceNames;ComputeIntermediateSatelliteAssemblies;_ResolveWasmConfiguration;_WasmNativeForBuild">
<ItemGroup>
<_WasmConfigFileCandidates Include="@(StaticWebAsset)" Condition="'%(SourceType)' == 'Discovered'" />
<_DotNetJsItem Include="@(ReferenceCopyLocalPaths)" Condition="('%(FileName)' == 'dotnet' or '%(FileName)' == 'dotnet.native') and '%(Extension)' == '.js'" />

<!-- Remove dotnet.js/wasm from runtime pack, in favor of the relinked ones in @(WasmNativeAsset) -->
<ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)"
Condition="@(WasmNativeAsset->Count()) > 0 and ( '%(FileName)' == 'dotnet' or '%(FileName)' == 'dotnet.native' ) and ('%(Extension)' == '.wasm' or '%(Extension)' == '.js')" />
</ItemGroup>
<PropertyGroup>
<_DotNetJsBuildVersion>%(_DotNetJsItem.NuGetPackageVersion)</_DotNetJsBuildVersion>
</PropertyGroup>

<ComputeWasmBuildAssets
Candidates="@(ReferenceCopyLocalPaths->Distinct());@(WasmNativeAsset)"
Expand All @@ -205,6 +209,7 @@ Copyright (c) .NET Foundation. All rights reserved.
ProjectSatelliteAssemblies="@(IntermediateSatelliteAssembliesWithTargetPath)"
TimeZoneSupport="$(_BlazorEnableTimeZoneSupport)"
InvariantGlobalization="$(_WasmInvariantGlobalization)"
DotNetJsVersion="$(_DotNetJsBuildVersion)"
CopySymbols="$(_WasmCopyOutputSymbolsToOutputDirectory)"
OutputPath="$(OutputPath)"
FingerprintDotNetJs="$(WasmFingerprintDotnetJs)"
Expand Down
12 changes: 12 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config)
}
}

[Theory]
[InlineData("Debug")]
[InlineData("Release")]
public void DefaultTemplate_BuildNative_WithWorkload(string config)
{
string id = $"blz_buildandbuildnative_{config}_{Path.GetRandomFileName()}";

CreateBlazorWasmTemplateProject(id);

BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked), "/p:WasmBuildNative=true");
}

// Disabling for now - publish folder can have more than one dotnet*hash*js, and not sure
// how to pick which one to check, for the test
//[Theory]
Expand Down
39 changes: 38 additions & 1 deletion src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
using Xunit.Abstractions;
using Xunit.Sdk;
using Microsoft.Playwright;
using System.Runtime.Serialization.Json;
using Microsoft.NET.Sdk.WebAssembly;

#nullable enable

Expand Down Expand Up @@ -822,7 +824,7 @@ protected static void AssertFile(string file0, string file1, string? label = nul
return result;
}

protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasmFromRuntimePack, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null)
protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasmFromRuntimePack, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null, bool expectFingerprinting = false)
{
binFrameworkDir ??= FindBlazorBinFrameworkDir(config, isPublish, targetFramework);

Expand All @@ -839,6 +841,41 @@ protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasm
dotnetJsPath!,
"Expected dotnet.native.js to be same as the runtime pack",
same: dotnetWasmFromRuntimePack);

string bootConfigPath = Path.Combine(binFrameworkDir, "blazor.boot.json");
Assert.True(File.Exists(bootConfigPath), $"Expected to find '{bootConfigPath}'");

using (var bootConfigContent = File.OpenRead(bootConfigPath))
{
var bootConfig = ParseBootData(bootConfigContent);
var dotnetJsEntries = bootConfig.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.") && k.EndsWith(".js")).ToArray();

void AssertFileExists(string fileName)
{
string absolutePath = Path.Combine(binFrameworkDir, fileName);
Assert.True(File.Exists(absolutePath), $"Expected to find '{absolutePath}'");
}

string versionHashRegex = @"\d.0.\d?(-[a-z]+(\.\d\.\d+\.\d)?)?\.([a-zA-Z0-9])+";
Assert.Collection(
dotnetJsEntries.OrderBy(f => f),
item => { Assert.Equal(expectFingerprinting ? $"dotnet\\.{versionHashRegex}\\.js" : "dotnet.js", item); AssertFileExists(item); },
item => { Assert.Matches($"dotnet\\.native\\.{versionHashRegex}\\.js", item); AssertFileExists(item); },
item => { Assert.Matches($"dotnet\\.runtime\\.{versionHashRegex}\\.js", item); AssertFileExists(item); }
);
}
}

private static BootJsonData ParseBootData(Stream stream)
{
stream.Position = 0;
var serializer = new DataContractJsonSerializer(
typeof(BootJsonData),
new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true });

var config = (BootJsonData?)serializer.ReadObject(stream);
Assert.NotNull(config);
return config;
}

protected void AssertBlazorBootJson(string config, bool isPublish, bool isNet7AndBelow, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null)
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Playwright" Version="1.21.0" />
<ProjectReference Include="$(RepoRoot)src\tasks\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks\Microsoft.NET.Sdk.WebAssembly.Pack.Tasks.csproj" />
<Compile Include="$(MonoProjectRoot)wasm\debugger\DebuggerTestSuite\BrowserLocator.cs" />

<None Include="$(RepoRoot)\src\mono\wasm\test-main.js" CopyToOutputDirectory="PreserveNewest" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class ComputeWasmBuildAssets : Task
[Required]
public ITaskItem[] ProjectSatelliteAssemblies { get; set; }

[Required]
public string DotNetJsVersion { get; set; }

[Required]
public string OutputPath { get; set; }

Expand Down Expand Up @@ -114,7 +117,7 @@ public override bool Execute()
if (candidateFileName != "dotnet" || FingerprintDotNetJs)
{
var itemHash = FileHasher.GetFileHash(candidate.ItemSpec);
newDotnetJSFileName = $"{candidateFileName}.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js";
newDotnetJSFileName = $"{candidateFileName}.{DotNetJsVersion}.{itemHash}.js";

var originalFileFullPath = Path.GetFullPath(candidate.ItemSpec);
var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ private List<ITaskItem> ProcessNativeAssets(
newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata());
newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec);

string relativePath = FingerprintDotNetJs
string relativePath = baseName != "dotnet" || FingerprintDotNetJs
? $"_framework/{$"{baseName}.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}"
: $"_framework/{baseName}.js";

Expand All @@ -242,8 +242,9 @@ private List<ITaskItem> ProcessNativeAssets(

if (isDotNetWasm)
{
var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => {
var name= $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}";
var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a =>
{
var name = $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}";
return name == "dotnet.native.wasm" || name == "dotnet.wasm";
});
ITaskItem newDotNetWasm = null;
Expand Down Expand Up @@ -589,7 +590,7 @@ private void GroupResolvedFilesToPublish(
}

var extension = candidate.GetMetadata("Extension");
if (string.Equals(extension, ".dll", StringComparison.Ordinal) || string.Equals (extension, Utils.WebcilInWasmExtension, StringComparison.Ordinal))
if (string.Equals(extension, ".dll", StringComparison.Ordinal) || string.Equals(extension, Utils.WebcilInWasmExtension, StringComparison.Ordinal))
{
var culture = candidate.GetMetadata("Culture");
var inferredCulture = candidate.GetMetadata("DestinationSubDirectory").Replace("\\", "/").Trim('/');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public override bool Execute()
var tmpDir = IntermediateOutputPath;
if (!Directory.Exists(tmpDir))
Directory.CreateDirectory(tmpDir);
var tmpWebcil = string.Concat (tmpDir, webcilFileName);
var tmpWebcil = Path.Combine(tmpDir, webcilFileName);
var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: filePath, outputPath: tmpWebcil, logger: Log);
webcilWriter.ConvertToWebcil();

Expand Down

0 comments on commit 4a2f9d3

Please sign in to comment.