From 5da314644ae882ff22fb43101d0c3d89a35c40e9 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 22 Apr 2020 11:01:22 -0700 Subject: Add an option to allow trimming collation data --- .../Build/src/targets/Blazor.MonoRuntime.props | 1 + .../Build/src/targets/Blazor.MonoRuntime.targets | 4 +++ .../src/targets/CollationLinkerDescriptor.xml | 21 ++++++++++++ .../Build/test/BuildIntegrationTests/Assert.cs | 40 +++++++++++++++++++++- .../PublishIntegrationTest.cs | 28 +++++++++++++++ .../Tests/WebAssemblyStringComparisonTest.cs | 35 +++++++++++++++++++ .../test/testassets/BasicTestApp/Index.razor | 1 + .../BasicTestApp/StringComparisonComponent.razor | 11 ++++++ 8 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 src/Components/WebAssembly/Build/src/targets/CollationLinkerDescriptor.xml create mode 100644 src/Components/test/E2ETest/Tests/WebAssemblyStringComparisonTest.cs create mode 100644 src/Components/test/testassets/BasicTestApp/StringComparisonComponent.razor diff --git a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.props b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.props index 45223bca93..453deddacd 100644 --- a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.props +++ b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.props @@ -9,6 +9,7 @@ <_BlazorRuntimeBinOutputPath>$(_BaseBlazorRuntimeOutputPath)_bin\ <_BlazorRuntimeWasmOutputPath>$(_BaseBlazorRuntimeOutputPath)wasm\ <_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml + <_BlazorCollationLinkerDescriptor>$(MSBuildThisFileDirectory)CollationLinkerDescriptor.xml <_BlazorBootJsonName>blazor.boot.json diff --git a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets index 1b7614bbae..8cb135f996 100644 --- a/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/WebAssembly/Build/src/targets/Blazor.MonoRuntime.targets @@ -218,6 +218,10 @@ <_BlazorLinkerRoot Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' != 'true'" /> + + + $(AdditionalMonoLinkerOptions) --substitutions "$(_BlazorCollationLinkerDescriptor)" + diff --git a/src/Components/WebAssembly/Build/src/targets/CollationLinkerDescriptor.xml b/src/Components/WebAssembly/Build/src/targets/CollationLinkerDescriptor.xml new file mode 100644 index 0000000000..693bdb6768 --- /dev/null +++ b/src/Components/WebAssembly/Build/src/targets/CollationLinkerDescriptor.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Components/WebAssembly/Build/test/BuildIntegrationTests/Assert.cs b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/Assert.cs index 75c223f742..aaf3e508b5 100644 --- a/src/Components/WebAssembly/Build/test/BuildIntegrationTests/Assert.cs +++ b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/Assert.cs @@ -534,7 +534,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build { using (var file = File.OpenRead(assemblyPath)) { - var peReader = new PEReader(file); + using var peReader = new PEReader(file); var metadataReader = peReader.GetMetadataReader(); return metadataReader.TypeDefinitions.Where(t => !t.IsNil).Select(t => { @@ -544,6 +544,44 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build } } + public static void AssemblyContainsResource(MSBuildResult result, string assemblyPath, string resourceName) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath)); + + var resources = GetAssemblyResourceNames(assemblyPath); + Assert.Contains(resourceName, resources); + } + + public static void AssemblyDoesNotContainResource(MSBuildResult result, string assemblyPath, string resourceName) + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath)); + + var resources = GetAssemblyResourceNames(assemblyPath); + Assert.DoesNotContain(resourceName, resources); + } + + private static IEnumerable GetAssemblyResourceNames(string assemblyPath) + { + using var file = File.OpenRead(assemblyPath); + using var peReader = new PEReader(file); + var metadataReader = peReader.GetMetadataReader(); + return metadataReader.ManifestResources.Where(r => !r.IsNil).Select(r => + { + var resource = metadataReader.GetManifestResource(r); + return metadataReader.GetString(resource.Name); + }).ToArray(); + } + public static void AssemblyHasAttribute(MSBuildResult result, string assemblyPath, string fullTypeName) { if (result == null) diff --git a/src/Components/WebAssembly/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs index cb9957fcbc..20c7bed354 100644 --- a/src/Components/WebAssembly/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs +++ b/src/Components/WebAssembly/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs @@ -60,6 +60,9 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"), serviceWorkerContent: "// This is the production service worker", assetsManifestPath: "custom-service-worker-assets.js"); + + // When publishing without linker, we expect to have collation information present in mscorlib.dll + Assert.AssemblyContainsResource(result, Path.Combine(blazorPublishDirectory, "_framework", "_bin", "mscorlib.dll"), "collation.cjkCHS.bin"); } [Fact] @@ -99,6 +102,31 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build // Verify web.config Assert.FileExists(result, publishDirectory, "web.config"); Assert.FileCountEquals(result, 1, publishDirectory, "*", SearchOption.TopDirectoryOnly); + + // When publishing with linker, we expect to have collation information present in mscorlib.dll + Assert.AssemblyContainsResource(result, Path.Combine(blazorPublishDirectory, "_framework", "_bin", "mscorlib.dll"), "collation.cjkCHS.bin"); + } + + [Fact] + public async Task Publish_LinkerEnabledAndBlazorWebAssemblyPreserveCollationDataSet_CollationInformationIsPreserved() + { + // Arrange + using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" }); + project.Configuration = "Release"; + project.AddProjectFileContent( +@" + false +"); + var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish"); + + Assert.BuildPassed(result); + + var publishDirectory = project.PublishOutputDirectory; + + var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot"); + + // When publishing with BlazorWebAssemblyPreserveCollationData=false, collation information should be stripped out. + Assert.AssemblyDoesNotContainResource(result, Path.Combine(blazorPublishDirectory, "_framework", "_bin", "mscorlib.dll"), "collation.cjkCHS.bin"); } [Fact] diff --git a/src/Components/test/E2ETest/Tests/WebAssemblyStringComparisonTest.cs b/src/Components/test/E2ETest/Tests/WebAssemblyStringComparisonTest.cs new file mode 100644 index 0000000000..9a38268403 --- /dev/null +++ b/src/Components/test/E2ETest/Tests/WebAssemblyStringComparisonTest.cs @@ -0,0 +1,35 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using BasicTestApp; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; +using Microsoft.AspNetCore.E2ETesting; +using OpenQA.Selenium; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Components.E2ETest.Tests +{ + public class WebAssemblyStringComparisonTest : ServerTestBase> + { + public WebAssemblyStringComparisonTest( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + } + + [Fact] + public void InvariantCultureWorksAsExpected() + { + Navigate(ServerPathBase, noReload: false); + Browser.MountTestComponent(); + + var result = Browser.Exists(By.Id("results")); + + Assert.Equal("Ordinal: False Invariant: True", result.Text); + } + } +} diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor index 85dfc1f22f..7a0c524cf8 100644 --- a/src/Components/test/testassets/BasicTestApp/Index.razor +++ b/src/Components/test/testassets/BasicTestApp/Index.razor @@ -71,6 +71,7 @@ + diff --git a/src/Components/test/testassets/BasicTestApp/StringComparisonComponent.razor b/src/Components/test/testassets/BasicTestApp/StringComparisonComponent.razor new file mode 100644 index 0000000000..7983a8558e --- /dev/null +++ b/src/Components/test/testassets/BasicTestApp/StringComparisonComponent.razor @@ -0,0 +1,11 @@ +@{ + // This test verifies that invariant cultue works correctly in WebAssembly environments. The test case is based on the discussions here: https://stackoverflow.com/a/20085219 + var string1 = "Strasse"; + var string2 = "Straße"; + + var ordinalComparison = string1.Equals(string2, StringComparison.Ordinal); + var invariantComparison = string1.Equals(string2, StringComparison.InvariantCulture); +} + +
Ordinal: @ordinalComparison Invariant: @invariantComparison
+ -- cgit v1.2.3