Replat blazor on net5 (#23078)
* Replat blazor on net5 * Make all e2e tests pass * Fixup * Update js files * Fixups * Fixup * Fixup * Skip globalization tests * Undo workarounds * PR feedback * Update dependencies from https://github.com/dotnet/runtime build 20200622.6 System.ComponentModel.Annotations , System.Diagnostics.DiagnosticSource , System.Diagnostics.EventLog , Microsoft.Extensions.Logging.Configuration , Microsoft.Extensions.Logging.Console , Microsoft.Extensions.Logging.Debug , Microsoft.Extensions.Logging.EventLog , Microsoft.Extensions.Logging.EventSource , Microsoft.Extensions.Logging.TraceSource , Microsoft.Extensions.Options , Microsoft.Extensions.Options.ConfigurationExtensions , Microsoft.Extensions.Options.DataAnnotations , Microsoft.Extensions.Primitives , Microsoft.Extensions.Logging.Abstractions , Microsoft.Extensions.Logging , Microsoft.Extensions.Internal.Transport , Microsoft.Extensions.Http , Microsoft.Extensions.Caching.Abstractions , Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.Binder , Microsoft.Extensions.Configuration.CommandLine , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.FileExtensions , Microsoft.Extensions.Configuration.Ini , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.Configuration.UserSecrets , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyInjection.Abstractions , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.FileProviders.Abstractions , Microsoft.Extensions.FileProviders.Composite , Microsoft.Extensions.FileProviders.Physical , Microsoft.Extensions.FileSystemGlobbing , Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.Extensions.Hosting , Microsoft.Extensions.Hosting.Abstractions , Microsoft.Extensions.Configuration.Xml , Microsoft.NETCore.App.Runtime.win-x64 , Microsoft.NETCore.Platforms , Microsoft.Win32.Registry , Microsoft.Win32.SystemEvents , Microsoft.NETCore.App.Internal , Microsoft.NETCore.App.Ref , System.Drawing.Common , System.ServiceProcess.ServiceController , System.Text.Encodings.Web , System.Text.Json , System.Threading.Channels , System.Windows.Extensions , System.Security.Principal.Windows , System.Security.Permissions , System.Security.Cryptography.Xml , System.IO.Pipelines , System.Net.Http.Json , System.Net.Http.WinHttpHandler , System.Net.WebSockets.WebSocketProtocol , System.Reflection.Metadata , System.Runtime.CompilerServices.Unsafe , System.Security.Cryptography.Cng , System.Security.Cryptography.Pkcs From Version 5.0.0-preview.7.20321.2 -> To Version 5.0.0-preview.7.20322.6 * Update js file * Fix version * Fixup Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
This commit is contained in:
parent
da03fe4c48
commit
f6a6e4bd07
|
|
@ -64,8 +64,6 @@
|
|||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" ProjectPath="$(RepoRoot)src\SignalR\server\StackExchangeRedis\src\Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" />
|
||||
<ProjectReferenceProvider Include="Ignitor" ProjectPath="$(RepoRoot)src\Components\Ignitor\src\Ignitor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Authentication.WebAssembly.Msal" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Build" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Build\src\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj" />
|
||||
<ProjectReferenceProvider Include="blazor-brotli" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Compression\src\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
|
||||
|
|
|
|||
|
|
@ -15,24 +15,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Tests", "WebAssembly\WebAssembly\test\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj", "{958AD6D2-174B-4B5B-BEFC-FA64B5159334}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Build", "WebAssembly\Build\src\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj", "{E8AD67A4-77D3-4B85-AE19-4711388B62B1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Build.Tests", "WebAssembly\Build\test\Microsoft.AspNetCore.Components.WebAssembly.Build.Tests.csproj", "{E38FDBB0-08C1-444E-A449-69C8A59D721B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.DevServer", "WebAssembly\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj", "{A6C8050D-7C18-4585-ADCF-833AC1765847}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Server", "WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj", "{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{A7ABAC29-F73F-456D-AE54-46842CFC2E10}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
WebAssembly\testassets\Wasm.Authentication.Server\Wasm.Authentication.Server.csproj = WebAssembly\testassets\Wasm.Authentication.Server\Wasm.Authentication.Server.csproj
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{FD37F740-A654-4117-BFB6-9112CE4C1D3B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{C1E2C117-BE47-4E29-94B3-753262D97A5C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanity", "WebAssembly\testassets\MonoSanity\MonoSanity.csproj", "{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoSanityClient", "WebAssembly\testassets\MonoSanityClient\MonoSanityClient.csproj", "{1C4BF2D3-44A8-4A71-B031-15B983663CB0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{C0FFB29E-4696-4875-9039-E5FA1AC5A42A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{A27FF193-195B-4474-8E6C-840B2E339373}"
|
||||
|
|
@ -244,16 +239,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.TestApp",
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebAssembly", "WebAssembly", "{346EC9B8-BF36-4A5E-A1A3-77879931713A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{1FA95650-E56E-470A-82A3-BC6572E4D6CD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Server.Tests", "WebAssembly\Server\test\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj", "{3D0ED658-9DAC-4066-A587-795321FA1C98}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Server", "Server", "{42E3C95D-A41E-4E14-96FD-AAE8F340FD7E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Authentication.WebAssembly.Msal", "WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj", "{4B4E4247-7BBF-444E-9737-407D34821D70}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression", "WebAssembly\Compression\src\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj", "{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.DebugProxy", "WebAssembly\DebugProxy\src\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj", "{B118AE2F-8D1D-413F-BC5D-060DF7CB707D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevServer", "DevServer", "{C6B58D53-04E2-4D65-B445-B510A3CB7569}"
|
||||
|
|
@ -268,6 +259,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentic
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.HttpHandler", "WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj", "{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{630D5388-7A2F-42DD-9154-1F62A18CBB69}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.JSInterop", "..\JSInterop\Microsoft.JSInterop\src\Microsoft.JSInterop.csproj", "{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -326,30 +323,6 @@ Global
|
|||
{958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|x64.Build.0 = Release|Any CPU
|
||||
{958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{958AD6D2-174B-4B5B-BEFC-FA64B5159334}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6C8050D-7C18-4585-ADCF-833AC1765847}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -398,30 +371,6 @@ Global
|
|||
{C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C1E2C117-BE47-4E29-94B3-753262D97A5C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0FFB29E-4696-4875-9039-E5FA1AC5A42A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1526,18 +1475,6 @@ Global
|
|||
{4B4E4247-7BBF-444E-9737-407D34821D70}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4B4E4247-7BBF-444E-9737-407D34821D70}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4B4E4247-7BBF-444E-9737-407D34821D70}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B118AE2F-8D1D-413F-BC5D-060DF7CB707D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B118AE2F-8D1D-413F-BC5D-060DF7CB707D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B118AE2F-8D1D-413F-BC5D-060DF7CB707D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1598,6 +1535,42 @@ Global
|
|||
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|x64.Build.0 = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -1607,15 +1580,11 @@ Global
|
|||
{F000C49D-3857-42A4-918D-DA4C08691FE2} = {E059A46B-56E3-41E2-83F4-B5D180056F3B}
|
||||
{641922CD-E6F5-41E7-A085-EE07C2A7328D} = {346EC9B8-BF36-4A5E-A1A3-77879931713A}
|
||||
{958AD6D2-174B-4B5B-BEFC-FA64B5159334} = {346EC9B8-BF36-4A5E-A1A3-77879931713A}
|
||||
{E8AD67A4-77D3-4B85-AE19-4711388B62B1} = {1FA95650-E56E-470A-82A3-BC6572E4D6CD}
|
||||
{E38FDBB0-08C1-444E-A449-69C8A59D721B} = {1FA95650-E56E-470A-82A3-BC6572E4D6CD}
|
||||
{A6C8050D-7C18-4585-ADCF-833AC1765847} = {C6B58D53-04E2-4D65-B445-B510A3CB7569}
|
||||
{A4859630-F9F7-4F5C-9FF3-6C013D7C58FA} = {42E3C95D-A41E-4E14-96FD-AAE8F340FD7E}
|
||||
{A7ABAC29-F73F-456D-AE54-46842CFC2E10} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{FD37F740-A654-4117-BFB6-9112CE4C1D3B} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{C1E2C117-BE47-4E29-94B3-753262D97A5C} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{F16C1A7C-A2BD-4EB1-8BC8-23B1375F3B9E} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{1C4BF2D3-44A8-4A71-B031-15B983663CB0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{C0FFB29E-4696-4875-9039-E5FA1AC5A42A} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{3B1A56F8-B3E0-4F33-A717-50BDD4FBE12E} = {A27FF193-195B-4474-8E6C-840B2E339373}
|
||||
{35A8AE1D-ED82-485E-A8E6-A357B3CB31B3} = {3D9B9B2C-E379-41BD-83D4-2E099FBDA107}
|
||||
|
|
@ -1709,11 +1678,9 @@ Global
|
|||
{CA9948CA-B3FA-4C2E-A726-5E47BAD19457} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A}
|
||||
{97EA0A7D-FE5E-47D1-ADDC-4BFD702F55AB} = {F65EFF0F-ACF3-46BD-9A8F-CDA94AF1885A}
|
||||
{346EC9B8-BF36-4A5E-A1A3-77879931713A} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{1FA95650-E56E-470A-82A3-BC6572E4D6CD} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{3D0ED658-9DAC-4066-A587-795321FA1C98} = {42E3C95D-A41E-4E14-96FD-AAE8F340FD7E}
|
||||
{42E3C95D-A41E-4E14-96FD-AAE8F340FD7E} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{4B4E4247-7BBF-444E-9737-407D34821D70} = {81250121-9B43-40B1-BF11-CE4458F2676C}
|
||||
{1A4C96E8-3FAF-48FB-9F3C-068FAAAB3FEE} = {1FA95650-E56E-470A-82A3-BC6572E4D6CD}
|
||||
{B118AE2F-8D1D-413F-BC5D-060DF7CB707D} = {C6B58D53-04E2-4D65-B445-B510A3CB7569}
|
||||
{C6B58D53-04E2-4D65-B445-B510A3CB7569} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{8FDD9F2E-B940-4A5F-83FD-5486D0853D76} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
|
|
@ -1721,6 +1688,9 @@ Global
|
|||
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17} = {81250121-9B43-40B1-BF11-CE4458F2676C}
|
||||
{81250121-9B43-40B1-BF11-CE4458F2676C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{630D5388-7A2F-42DD-9154-1F62A18CBB69} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
|
||||
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@
|
|||
"Server\\src\\Microsoft.AspNetCore.Components.Server.csproj",
|
||||
"Server\\test\\Microsoft.AspNetCore.Components.Server.Tests.csproj",
|
||||
"WebAssembly\\Authentication.Msal\\src\\Microsoft.Authentication.WebAssembly.Msal.csproj",
|
||||
"WebAssembly\\Build\\src\\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj",
|
||||
"WebAssembly\\Build\\test\\Microsoft.AspNetCore.Components.WebAssembly.Build.Tests.csproj",
|
||||
"WebAssembly\\Compression\\src\\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj",
|
||||
"WebAssembly\\DebugProxy\\src\\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj",
|
||||
"WebAssembly\\DevServer\\src\\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj",
|
||||
"WebAssembly\\JSInterop\\src\\Microsoft.JSInterop.WebAssembly.csproj",
|
||||
|
|
@ -32,8 +29,6 @@
|
|||
"WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj",
|
||||
"WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
|
||||
"WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
|
||||
"WebAssembly\\testassets\\MonoSanityClient\\MonoSanityClient.csproj",
|
||||
"WebAssembly\\testassets\\MonoSanity\\MonoSanity.csproj",
|
||||
"WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
|
||||
"Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
||||
"Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
<Project>
|
||||
<PropertyGroup Condition="'$(UseBlazorWebAssembly)' == 'true'">
|
||||
<BlazorWebAssemblyJSPath>$(RepoRoot)src\Components\Web.JS\dist\$(Configuration)\blazor.webassembly.js</BlazorWebAssemblyJSPath>
|
||||
<BlazorWebAssemblyJSMapPath>$(BlazorWebAssemblyJSPath).map</BlazorWebAssemblyJSMapPath>
|
||||
|
||||
<_BlazorDevServerPath>$(RepoRoot)src/Components/WebAssembly/DevServer/src/bin/$(Configuration)/$(DefaultNetCoreTargetFramework)/blazor-devserver.dll</_BlazorDevServerPath>
|
||||
<RunCommand>dotnet</RunCommand>
|
||||
<RunArguments>exec "$(_BlazorDevServerPath)" serve --applicationpath "$(TargetPath)" $(AdditionalRunArguments)</RunArguments>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Add a project dependency without reference output assemblies to enforce build order -->
|
||||
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
|
||||
<ProjectReference
|
||||
Condition="'$(ReferenceBlazorBuildLocally)' == 'true' and '$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'"
|
||||
Condition="'$(UseBlazorWebAssembly)' == 'true' and '$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'"
|
||||
Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
|
|
@ -11,8 +20,6 @@
|
|||
Private="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="WebAssembly\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />
|
||||
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
|
||||
|
||||
<ItemGroup Condition="'$(FixupWebAssemblyHttpHandlerReference)' == 'true'">
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -142,7 +142,7 @@ function addScriptTagsToDocument(resourceLoader: WebAssemblyResourceLoader) {
|
|||
.filter(n => n.startsWith('dotnet.') && n.endsWith('.js'))[0];
|
||||
const dotnetJsContentHash = resourceLoader.bootConfig.resources.runtime[dotnetJsResourceName];
|
||||
const scriptElem = document.createElement('script');
|
||||
scriptElem.src = `_framework/wasm/${dotnetJsResourceName}`;
|
||||
scriptElem.src = `_framework/${dotnetJsResourceName}`;
|
||||
scriptElem.defer = true;
|
||||
|
||||
// For consistency with WebAssemblyResourceLoader, we only enforce SRI if caching is allowed
|
||||
|
|
@ -204,11 +204,11 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
|||
|
||||
// Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel.
|
||||
const dotnetWasmResourceName = 'dotnet.wasm';
|
||||
const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/_bin/${filename}`, 'assembly');
|
||||
const pdbsBeingLoaded = resourceLoader.loadResources(resources.pdb || {}, filename => `_framework/_bin/${filename}`, 'pdb');
|
||||
const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/${filename}`, 'assembly');
|
||||
const pdbsBeingLoaded = resourceLoader.loadResources(resources.pdb || {}, filename => `_framework/${filename}`, 'pdb');
|
||||
const wasmBeingLoaded = resourceLoader.loadResource(
|
||||
/* name */ dotnetWasmResourceName,
|
||||
/* url */ `_framework/wasm/${dotnetWasmResourceName}`,
|
||||
/* url */ `_framework/${dotnetWasmResourceName}`,
|
||||
/* hash */ resourceLoader.bootConfig.resources.runtime[dotnetWasmResourceName],
|
||||
/* type */ 'dotnetwasm');
|
||||
|
||||
|
|
@ -217,7 +217,7 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
|||
if (resourceLoader.bootConfig.resources.runtime.hasOwnProperty(dotnetTimeZoneResourceName)) {
|
||||
timeZoneResource = resourceLoader.loadResource(
|
||||
dotnetTimeZoneResourceName,
|
||||
`_framework/wasm/${dotnetTimeZoneResourceName}`,
|
||||
`_framework/${dotnetTimeZoneResourceName}`,
|
||||
resourceLoader.bootConfig.resources.runtime[dotnetTimeZoneResourceName],
|
||||
'timezonedata');
|
||||
}
|
||||
|
|
@ -267,7 +267,7 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
|||
if (satelliteResources) {
|
||||
const resourcePromises = Promise.all(culturesToLoad
|
||||
.filter(culture => satelliteResources.hasOwnProperty(culture))
|
||||
.map(culture => resourceLoader.loadResources(satelliteResources[culture], fileName => `_framework/_bin/${fileName}`, 'assembly'))
|
||||
.map(culture => resourceLoader.loadResources(satelliteResources[culture], fileName => `_framework/${fileName}`, 'assembly'))
|
||||
.reduce((previous, next) => previous.concat(next), new Array<LoadingResource>())
|
||||
.map(async resource => (await resource.response).arrayBuffer()));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
|
||||
<TargetName>Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks</TargetName>
|
||||
<AssemblyName>Microsoft.AspNetCore.Components.WebAssembly.Build</AssemblyName>
|
||||
<Description>Build mechanism for ASP.NET Core Blazor WebAssembly applications.</Description>
|
||||
<IsShippingPackage>true</IsShippingPackage>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Pack settings -->
|
||||
<PropertyGroup>
|
||||
<!-- Producing this package requires building with NodeJS enabled. -->
|
||||
<IsPackable Condition="'$(BuildNodeJS)' == 'false'">false</IsPackable>
|
||||
<NoPackageAnalysis>true</NoPackageAnalysis>
|
||||
<NuspecFile>Microsoft.AspNetCore.Components.WebAssembly.Build.nuspec</NuspecFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<NuspecProperty Include="configuration=$(Configuration)" />
|
||||
<NuspecProperty Include="taskskDir=$(OutputPath)tools" />
|
||||
<NuspecProperty Include="MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion=$(MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion)" />
|
||||
<NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Build.Tests" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Add a project dependency without reference output assemblies to enforce build order -->
|
||||
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
|
||||
<ProjectReference
|
||||
Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework"
|
||||
Private="false"
|
||||
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
||||
|
||||
<ProjectReference
|
||||
Include="..\..\Compression\src\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'" />
|
||||
|
||||
<Reference Include="Microsoft.Build.Framework" ExcludeAssets="Runtime" />
|
||||
<Reference Include="Microsoft.Build.Utilities.Core" ExcludeAssets="Runtime" />
|
||||
<Reference Include="System.Reflection.Metadata" Condition="'$(TargetFramework)' == 'net46'" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyBuildTask" BeforeTargets="Build" Condition="'$(DotNetBuildFromSource)' != 'true' AND '$(IsInnerBuild)' != 'true'">
|
||||
<!--
|
||||
The task produced by this project is referenced within this solution. When building, Visual Studio will lock up the assembly.
|
||||
Any attempts to overwrite the binary with a newer version will fail. This is particularly grating if a developer "Rebuilds" the project
|
||||
after an initial build since that would always attempt to overwrite the tasks dll
|
||||
|
||||
This target attempts to make this solution more usable at the cost of a more onerous inner-loop build of the Blazor.Build tasks.
|
||||
We'll copy the tasks to a location other that than the build output and use that in the Blazor.Build.targets. In the most common
|
||||
case where these tasks aren't being worked on, everything should work great. However, if you're attemping to modify these tasks,
|
||||
you will need to manaully stop MSBuild.exe processes
|
||||
-->
|
||||
|
||||
<ItemGroup>
|
||||
<_NetCoreFilesToCopy Include="$(OutputPath)$(DefaultNetCoreTargetFramework)\*" TargetPath="netcoreapp\" />
|
||||
<_DesktopFilesToCopy Include="$(OutputPath)net46\*" TargetPath="netfx\" />
|
||||
<_AllFilesToCopy Include="@(_NetCoreFilesToCopy);@(_DesktopFilesToCopy)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Error Text="No files found in $(OutputPath)$(DefaultNetCoreTargetFramework)" Condition="@(_NetCoreFilesToCopy->Count()) == 0" />
|
||||
<Error Text="No files found in $(OutputPath)net46" Condition="@(_DesktopFilesToCopy->Count()) == 0" />
|
||||
|
||||
<Copy SourceFiles="@(_AllFilesToCopy)" DestinationFiles="@(_AllFilesToCopy->'$(OutputPath)tools\%(TargetPath)%(FileName)%(Extension)')" SkipUnchangedFiles="true" Retries="1" ContinueOnError="true">
|
||||
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
|
||||
</Copy>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<_BrotliToolPathInput Include="..\..\Compression\src\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj" />
|
||||
<_BrotliToolPathInput Include="..\..\Compression\src\*.cs" />
|
||||
<_BrotliToolPathInput Include="..\..\Compression\src\*.runtimeconfig.json" />
|
||||
<_BrotliToolPathOutput Include="$(MSBuildThisFileDirectory)bin\$(Configuration)\tools\compression\blazor-brotli.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target
|
||||
Name="GetBrotliTools"
|
||||
BeforeTargets="Build;GenerateNuspec"
|
||||
Inputs="@(_BrotliToolPathInput)"
|
||||
Outputs="@(_BrotliToolPathOutput)"
|
||||
Condition="'$(DotNetBuildFromSource)' != 'true'">
|
||||
<ItemGroup>
|
||||
<_BrotliToolsPath Include="$(MSBuildThisFileDirectory)bin\$(Configuration)\tools\compression\" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<_BrotliToolsOutputPath>@(_BrotliToolsPath->'%(FullPath)')</_BrotliToolsOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<NuspecProperty Include="brotliDir=$(_BrotliToolsOutputPath)" />
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild
|
||||
Projects="..\..\Compression\src\Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression.csproj"
|
||||
Targets="Publish"
|
||||
Properties="Configuration=$(Configuration);TargetFramework=$(DefaultNetCoreTargetFramework);PublishDir=$(_BrotliToolsOutputPath)">
|
||||
</MSBuild>
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
$CommonMetadataElements$
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.AspNetCore.Components.WebAssembly.Runtime" version="$MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion$" include="all" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
$CommonFileElements$
|
||||
<file src="$PackageThirdPartyNoticesFile$" target=".\THIRD-PARTY-NOTICES.txt" />
|
||||
<file src="build\**" target="build" />
|
||||
<file src="$brotliDir$blazor-brotli.dll" target="tools/compression" />
|
||||
<file src="$brotliDir$blazor-brotli.runtimeconfig.json" target="tools/compression" />
|
||||
<file src="targets\**" target="targets" />
|
||||
<file src="$taskskDir$\**" target="tools/" />
|
||||
<file src="..\..\..\Web.JS\dist\$configuration$\blazor.webassembly.js" target="tools/blazor" />
|
||||
</files>
|
||||
</package>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<Project>
|
||||
<!--
|
||||
Importing this file is equivalent to having:
|
||||
<PackageDependency Include="Microsoft.AspNetCore.Blazor.Build" />
|
||||
... except it's much more convenient when working in this repo, because it consumes the
|
||||
Blazor.Build targets/exe directly without needing this project to be packed into a .nupkg.
|
||||
|
||||
This is only intended for use by other projects in this repo.
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<ComponentsRoot Condition="'$(ComponentsRoot)'==''">$(MSBuildThisFileDirectory)..\..\..\</ComponentsRoot>
|
||||
<BlazorBuildConfiguration Condition="'$(BlazorBuildConfiguration)'==''">$(Configuration)</BlazorBuildConfiguration>
|
||||
|
||||
<_BlazorJsPath>$(ComponentsRoot)Web.JS\dist\$(BlazorBuildConfiguration)\blazor.webassembly.js</_BlazorJsPath>
|
||||
<_BlazorJsMapPath>$(ComponentsRoot)Web.JS\dist\$(BlazorBuildConfiguration)\blazor.webassembly.js.map</_BlazorJsMapPath>
|
||||
<_BlazorToolsDir>$(MSBuildThisFileDirectory)bin\$(BlazorBuildConfiguration)\tools\</_BlazorToolsDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="Check_BlazorJSFiles" BeforeTargets="Build" Condition="'$(ExcludeFromBuild)' != 'true'">
|
||||
<Error Text="blazor.webassembly.js file could not be found at $(_BlazorJsPath)" Condition="!Exists($(_BlazorJsPath))" />
|
||||
</Target>
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)targets/All.props" />
|
||||
<Import Project="$(MSBuildThisFileDirectory)targets/All.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<Import Project="ReferenceBlazorBuildFromSource.props" />
|
||||
|
||||
<!--
|
||||
Debugging support using blazor-devserver serve.
|
||||
|
||||
A few things to note here:
|
||||
- We have to use dotnet exec to avoid launching another process and confusing the debugger.
|
||||
- Since we're doing dotnet exec, it won't automatically rebuild the DevServer project.
|
||||
- $(AdditionalRunArguments) needs to be defined before importing this file.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RunCommand>dotnet</RunCommand>
|
||||
<_BlazorCliLocation>$(MSBuildThisFileDirectory)../../DevServer/src/bin/$(Configuration)/$(DefaultNetCoreTargetFramework)/blazor-devserver.dll</_BlazorCliLocation>
|
||||
<RunArguments>exec "$(_BlazorCliLocation)" serve --applicationpath "$(MSBuildProjectDirectory)/$(OutputPath)$(TargetFileName)" $(AdditionalRunArguments)</RunArguments>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Runtime" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="_BuildBlazorBuildProject" BeforeTargets="ResolveProjectReferences" Condition="'$(NoBuild)' != 'true'">
|
||||
<!--
|
||||
The Blazor.Build project cross-compiles and we need the output of all TFMs to be available in the build output.
|
||||
We can't represent this in any good way using ProjectReference elements, but we can try and build it instead.
|
||||
-->
|
||||
<MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Components.WebAssembly.Build.csproj" />
|
||||
</Target>
|
||||
|
||||
<!-- This is used as a P2P when building the repo. Normal Blazor projects will get this as a reference through the Blazor.Build package -->
|
||||
<ItemGroup>
|
||||
<!-- Ensures these projects are built before the consuming project, but without
|
||||
adding a runtime dependency on the .dll (to be equivalent to a <PackageDependency>
|
||||
given that the packed version of this project wouldn't add a .dll reference) -->
|
||||
<ProjectReference Include="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Components.WebAssembly.Build.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||
<Properties>TargetFramework=$(DefaultNetCoreTargetFramework)</Properties>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj">
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
<!-- Optimization. Do not require framework compatibility between these projects. -->
|
||||
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
|
||||
<UndefineProperties>TargetFramework</UndefineProperties>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.Build.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Computes the checksum for a single file.
|
||||
/// </summary>
|
||||
public sealed class BlazorGetFileHash : Task
|
||||
{
|
||||
internal const string _defaultFileHashAlgorithm = "SHA256";
|
||||
internal const string _hashEncodingBase64 = "base64";
|
||||
|
||||
/// <summary>
|
||||
/// The files to be hashed.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The algorithm. Allowed values: SHA256, SHA384, SHA512. Default = SHA256.
|
||||
/// </summary>
|
||||
public string Algorithm { get; set; } = _defaultFileHashAlgorithm;
|
||||
|
||||
/// <summary>
|
||||
/// The metadata name where the hash is stored in each item. Defaults to "FileHash".
|
||||
/// </summary>
|
||||
public string MetadataName { get; set; } = "FileHash";
|
||||
|
||||
/// <summary>
|
||||
/// The encoding to use for generated hashs. Defaults to "hex". Allowed values = "base64".
|
||||
/// </summary>
|
||||
public string HashEncoding { get; set; } = _hashEncodingBase64;
|
||||
|
||||
/// <summary>
|
||||
/// The hash of the file. This is only set if there was one item group passed in.
|
||||
/// </summary>
|
||||
[Output]
|
||||
public string Hash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The input files with additional metadata set to include the file hash.
|
||||
/// </summary>
|
||||
[Output]
|
||||
public ITaskItem[] Items { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
if (!SupportsAlgorithm(Algorithm))
|
||||
{
|
||||
Log.LogError("Unrecognized HashAlgorithm {0}", Algorithm);
|
||||
return false;
|
||||
}
|
||||
|
||||
System.Threading.Tasks.Parallel.ForEach(Files, file =>
|
||||
{
|
||||
if (!File.Exists(file.ItemSpec))
|
||||
{
|
||||
Log.LogError("File not found '{0}", file.ItemSpec);
|
||||
}
|
||||
});
|
||||
|
||||
if (Log.HasLoggedErrors)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
System.Threading.Tasks.Parallel.ForEach(Files, file =>
|
||||
{
|
||||
var hash = ComputeHash(Algorithm, file.ItemSpec);
|
||||
file.SetMetadata("FileHashAlgorithm", Algorithm);
|
||||
file.SetMetadata(MetadataName, EncodeHash(hash));
|
||||
});
|
||||
|
||||
Items = Files;
|
||||
|
||||
if (Files.Length == 1)
|
||||
{
|
||||
Hash = Files[0].GetMetadata(MetadataName);
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
internal static string EncodeHash(byte[] hash)
|
||||
{
|
||||
return Convert.ToBase64String(hash);
|
||||
}
|
||||
|
||||
internal static bool SupportsAlgorithm(string algorithmName)
|
||||
=> _supportedAlgorithms.Contains(algorithmName);
|
||||
|
||||
internal static byte[] ComputeHash(string algorithmName, string filePath)
|
||||
{
|
||||
using (var stream = File.OpenRead(filePath))
|
||||
using (var algorithm = CreateAlgorithm(algorithmName))
|
||||
{
|
||||
return algorithm.ComputeHash(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> _supportedAlgorithms
|
||||
= new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"SHA256",
|
||||
"SHA384",
|
||||
"SHA512",
|
||||
};
|
||||
|
||||
private static HashAlgorithm CreateAlgorithm(string algorithmName)
|
||||
{
|
||||
if (string.Equals(algorithmName, "SHA256", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return SHA256.Create();
|
||||
}
|
||||
else if (string.Equals(algorithmName, "SHA384", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return SHA384.Create();
|
||||
}
|
||||
else if (string.Equals(algorithmName, "SHA512", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return SHA512.Create();
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks
|
||||
{
|
||||
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/LinkTask.cs
|
||||
public class BlazorILLink : ToolTask
|
||||
{
|
||||
private const string DotNetHostPathEnvironmentName = "DOTNET_HOST_PATH";
|
||||
|
||||
[Required]
|
||||
public string ILLinkPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] AssemblyPaths { get; set; }
|
||||
|
||||
public ITaskItem[] ReferenceAssemblyPaths { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] RootAssemblyNames { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem OutputDirectory { get; set; }
|
||||
|
||||
public ITaskItem[] RootDescriptorFiles { get; set; }
|
||||
|
||||
public bool ClearInitLocals { get; set; }
|
||||
|
||||
public string ClearInitLocalsAssemblies { get; set; }
|
||||
|
||||
public string ExtraArgs { get; set; }
|
||||
|
||||
public bool DumpDependencies { get; set; }
|
||||
|
||||
private string _dotnetPath;
|
||||
|
||||
private string DotNetPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
return _dotnetPath;
|
||||
}
|
||||
|
||||
_dotnetPath = Environment.GetEnvironmentVariable(DotNetHostPathEnvironmentName);
|
||||
if (string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
throw new InvalidOperationException($"{DotNetHostPathEnvironmentName} is not set");
|
||||
}
|
||||
|
||||
return _dotnetPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High;
|
||||
|
||||
protected override string ToolName => Path.GetFileName(DotNetPath);
|
||||
|
||||
protected override string GenerateFullPathToTool() => DotNetPath;
|
||||
|
||||
protected override string GenerateCommandLineCommands()
|
||||
{
|
||||
var args = new StringBuilder();
|
||||
args.Append(Quote(ILLinkPath));
|
||||
return args.ToString();
|
||||
}
|
||||
|
||||
private static string Quote(string path)
|
||||
{
|
||||
return $"\"{path.TrimEnd('\\')}\"";
|
||||
}
|
||||
|
||||
protected override string GenerateResponseFileCommands()
|
||||
{
|
||||
var args = new StringBuilder();
|
||||
|
||||
if (RootDescriptorFiles != null)
|
||||
{
|
||||
foreach (var rootFile in RootDescriptorFiles)
|
||||
{
|
||||
args.Append("-x ").AppendLine(Quote(rootFile.ItemSpec));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var assemblyItem in RootAssemblyNames)
|
||||
{
|
||||
args.Append("-a ").AppendLine(Quote(assemblyItem.ItemSpec));
|
||||
}
|
||||
|
||||
var assemblyNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var assembly in AssemblyPaths)
|
||||
{
|
||||
var assemblyPath = assembly.ItemSpec;
|
||||
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
|
||||
|
||||
// If there are multiple paths with the same assembly name, only use the first one.
|
||||
if (!assemblyNames.Add(assemblyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
args.Append("-reference ")
|
||||
.AppendLine(Quote(assemblyPath));
|
||||
|
||||
var action = assembly.GetMetadata("action");
|
||||
if ((action != null) && (action.Length > 0))
|
||||
{
|
||||
args.Append("-p ");
|
||||
args.Append(action);
|
||||
args.Append(" ").AppendLine(Quote(assemblyName));
|
||||
}
|
||||
}
|
||||
|
||||
if (ReferenceAssemblyPaths != null)
|
||||
{
|
||||
foreach (var assembly in ReferenceAssemblyPaths)
|
||||
{
|
||||
var assemblyPath = assembly.ItemSpec;
|
||||
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
|
||||
|
||||
// Don't process references for which we already have
|
||||
// implementation assemblies.
|
||||
if (assemblyNames.Contains(assemblyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
args.Append("-reference ").AppendLine(Quote(assemblyPath));
|
||||
|
||||
// Treat reference assemblies as "skip". Ideally we
|
||||
// would not even look at the IL, but only use them to
|
||||
// resolve surface area.
|
||||
args.Append("-p skip ").AppendLine(Quote(assemblyName));
|
||||
}
|
||||
}
|
||||
|
||||
if (OutputDirectory != null)
|
||||
{
|
||||
args.Append("-out ").AppendLine(Quote(OutputDirectory.ItemSpec));
|
||||
}
|
||||
|
||||
if (ClearInitLocals)
|
||||
{
|
||||
args.AppendLine("--enable-opt clearinitlocals");
|
||||
if ((ClearInitLocalsAssemblies != null) && (ClearInitLocalsAssemblies.Length > 0))
|
||||
{
|
||||
args.Append("-m ClearInitLocalsAssemblies ");
|
||||
args.AppendLine(ClearInitLocalsAssemblies);
|
||||
}
|
||||
}
|
||||
|
||||
if (ExtraArgs != null)
|
||||
{
|
||||
args.AppendLine(ExtraArgs);
|
||||
}
|
||||
|
||||
if (DumpDependencies)
|
||||
{
|
||||
args.AppendLine("--dump-dependencies");
|
||||
}
|
||||
|
||||
return args.ToString();
|
||||
}
|
||||
|
||||
protected override bool HandleTaskExecutionErrors()
|
||||
{
|
||||
// Show a slightly better error than the standard ToolTask message that says "dotnet" failed.
|
||||
Log.LogError($"ILLink failed with exit code {ExitCode}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(singleLine) && singleLine.StartsWith("Unhandled exception.", StringComparison.Ordinal))
|
||||
{
|
||||
// The Mono linker currently prints out an entire stack trace when the linker fails.
|
||||
// We want to show something actionable in the VS Error window.
|
||||
Log.LogError(singleLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.LogEventsFromTextOutput(singleLine, messageImportance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// 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 System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class BrotliCompressBlazorApplicationFiles : ToolTask
|
||||
{
|
||||
private const string DotNetHostPathEnvironmentName = "DOTNET_HOST_PATH";
|
||||
|
||||
[Required]
|
||||
public string ManifestPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public string BlazorBrotliPath { get; set; }
|
||||
|
||||
private string _dotnetPath;
|
||||
|
||||
private string DotNetPath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
return _dotnetPath;
|
||||
}
|
||||
|
||||
_dotnetPath = Environment.GetEnvironmentVariable(DotNetHostPathEnvironmentName);
|
||||
if (string.IsNullOrEmpty(_dotnetPath))
|
||||
{
|
||||
throw new InvalidOperationException($"{DotNetHostPathEnvironmentName} is not set");
|
||||
}
|
||||
|
||||
return _dotnetPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High;
|
||||
|
||||
protected override string ToolName => Path.GetFileName(DotNetPath);
|
||||
|
||||
protected override string GenerateFullPathToTool() => DotNetPath;
|
||||
|
||||
protected override string GenerateCommandLineCommands() =>
|
||||
$"\"{BlazorBrotliPath}\" \"{ManifestPath}\"";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using ResourceHashesByNameDictionary = System.Collections.Generic.Dictionary<string, string>;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class GenerateBlazorBootJson : Task
|
||||
{
|
||||
[Required]
|
||||
public string AssemblyPath { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] Resources { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool DebugBuild { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool LinkerEnabled { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool CacheBootResources { get; set; }
|
||||
|
||||
public ITaskItem[] ConfigurationFiles { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(OutputPath);
|
||||
var entryAssemblyName = AssemblyName.GetAssemblyName(AssemblyPath).Name;
|
||||
|
||||
try
|
||||
{
|
||||
WriteBootJson(fileStream, entryAssemblyName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
// Internal for tests
|
||||
internal void WriteBootJson(Stream output, string entryAssemblyName)
|
||||
{
|
||||
var result = new BootJsonData
|
||||
{
|
||||
entryAssembly = entryAssemblyName,
|
||||
cacheBootResources = CacheBootResources,
|
||||
debugBuild = DebugBuild,
|
||||
linkerEnabled = LinkerEnabled,
|
||||
resources = new ResourcesData(),
|
||||
config = new List<string>(),
|
||||
};
|
||||
|
||||
// Build a two-level dictionary of the form:
|
||||
// - assembly:
|
||||
// - UriPath (e.g., "System.Text.Json.dll")
|
||||
// - ContentHash (e.g., "4548fa2e9cf52986")
|
||||
// - runtime:
|
||||
// - UriPath (e.g., "dotnet.js")
|
||||
// - ContentHash (e.g., "3448f339acf512448")
|
||||
if (Resources != null)
|
||||
{
|
||||
var resourceData = result.resources;
|
||||
foreach (var resource in Resources)
|
||||
{
|
||||
var resourceTypeMetadata = resource.GetMetadata("BootManifestResourceType");
|
||||
ResourceHashesByNameDictionary resourceList;
|
||||
switch (resourceTypeMetadata)
|
||||
{
|
||||
case "runtime":
|
||||
resourceList = resourceData.runtime;
|
||||
break;
|
||||
case "assembly":
|
||||
resourceList = resourceData.assembly;
|
||||
break;
|
||||
case "dynamicAssembly":
|
||||
resourceList = resourceData.dynamicAssembly;
|
||||
break;
|
||||
case "pdb":
|
||||
resourceData.pdb ??= new ResourceHashesByNameDictionary();
|
||||
resourceList = resourceData.pdb;
|
||||
break;
|
||||
case "satellite":
|
||||
if (resourceData.satelliteResources is null)
|
||||
{
|
||||
resourceData.satelliteResources = new Dictionary<string, ResourceHashesByNameDictionary>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
var resourceCulture = resource.GetMetadata("Culture");
|
||||
if (resourceCulture is null)
|
||||
{
|
||||
Log.LogWarning("Satellite resource {0} does not specify required metadata 'Culture'.", resource);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!resourceData.satelliteResources.TryGetValue(resourceCulture, out resourceList))
|
||||
{
|
||||
resourceList = new ResourceHashesByNameDictionary();
|
||||
resourceData.satelliteResources.Add(resourceCulture, resourceList);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"Unsupported BootManifestResourceType metadata value: {resourceTypeMetadata}");
|
||||
}
|
||||
|
||||
var resourceName = GetResourceName(resource);
|
||||
if (!resourceList.ContainsKey(resourceName))
|
||||
{
|
||||
resourceList.Add(resourceName, $"sha256-{resource.GetMetadata("Integrity")}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigurationFiles != null)
|
||||
{
|
||||
foreach (var configFile in ConfigurationFiles)
|
||||
{
|
||||
result.config.Add(Path.GetFileName(configFile.ItemSpec));
|
||||
}
|
||||
}
|
||||
|
||||
var serializer = new DataContractJsonSerializer(typeof(BootJsonData), new DataContractJsonSerializerSettings
|
||||
{
|
||||
UseSimpleDictionaryFormat = true
|
||||
});
|
||||
|
||||
using var writer = JsonReaderWriterFactory.CreateJsonWriter(output, Encoding.UTF8, ownsStream: false, indent: true);
|
||||
serializer.WriteObject(writer, result);
|
||||
}
|
||||
|
||||
private static string GetResourceName(ITaskItem item)
|
||||
{
|
||||
var name = item.GetMetadata("BootManifestResourceName");
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new Exception($"No BootManifestResourceName was specified for item '{item.ItemSpec}'");
|
||||
}
|
||||
|
||||
return name.Replace('\\', '/');
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
/// <summary>
|
||||
/// Defines the structure of a Blazor boot JSON file
|
||||
/// </summary>
|
||||
public class BootJsonData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the assembly with the application entry point
|
||||
/// </summary>
|
||||
public string entryAssembly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of resources needed to boot the application. This includes the transitive
|
||||
/// closure of .NET assemblies (including the entrypoint assembly), the dotnet.wasm file,
|
||||
/// and any PDBs to be loaded.
|
||||
///
|
||||
/// Within <see cref="ResourceHashesByNameDictionary"/>, dictionary keys are resource names,
|
||||
/// and values are SHA-256 hashes formatted in prefixed base-64 style (e.g., 'sha256-abcdefg...')
|
||||
/// as used for subresource integrity checking.
|
||||
/// </summary>
|
||||
public ResourcesData resources { get; set; } = new ResourcesData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines whether to enable caching of the <see cref="resources"/>
|
||||
/// inside a CacheStorage instance within the browser.
|
||||
/// </summary>
|
||||
public bool cacheBootResources { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines if this is a debug build.
|
||||
/// </summary>
|
||||
public bool debugBuild { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value that determines if the linker is enabled.
|
||||
/// </summary>
|
||||
public bool linkerEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Config files for the application
|
||||
/// </summary>
|
||||
public List<string> config { get; set; }
|
||||
}
|
||||
|
||||
public class ResourcesData
|
||||
{
|
||||
/// <summary>
|
||||
/// .NET Wasm runtime resources (dotnet.wasm, dotnet.js) etc.
|
||||
/// </summary>
|
||||
public ResourceHashesByNameDictionary runtime { get; set; } = new ResourceHashesByNameDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// "assembly" (.dll) resources
|
||||
/// </summary>
|
||||
public ResourceHashesByNameDictionary assembly { get; set; } = new ResourceHashesByNameDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Assembly (.dll) resources that are loaded dynamically during runtime
|
||||
/// </summary>
|
||||
public ResourceHashesByNameDictionary dynamicAssembly { get; set; } = new ResourceHashesByNameDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// "debug" (.pdb) resources
|
||||
/// </summary>
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public ResourceHashesByNameDictionary pdb { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// localization (.satellite resx) resources
|
||||
/// </summary>
|
||||
[DataMember(EmitDefaultValue = false)]
|
||||
public Dictionary<string, ResourceHashesByNameDictionary> satelliteResources { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class GenerateBlazorCompressionManifest : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] FilesToCompress { get; set; }
|
||||
|
||||
[Required]
|
||||
public string ManifestPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
WriteCompressionManifest();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
private void WriteCompressionManifest()
|
||||
{
|
||||
var tempFilePath = Path.GetTempFileName();
|
||||
|
||||
var manifest = new ManifestData();
|
||||
var filesToCompress = new List<CompressedFile>();
|
||||
|
||||
foreach (var file in FilesToCompress)
|
||||
{
|
||||
filesToCompress.Add(new CompressedFile
|
||||
{
|
||||
Source = file.GetMetadata("FullPath"),
|
||||
InputSource = file.GetMetadata("InputSource"),
|
||||
Target = file.GetMetadata("TargetCompressionPath"),
|
||||
});
|
||||
}
|
||||
|
||||
manifest.FilesToCompress = filesToCompress.ToArray();
|
||||
|
||||
var serializer = new DataContractJsonSerializer(typeof(ManifestData));
|
||||
|
||||
using (var tempFile = File.OpenWrite(tempFilePath))
|
||||
{
|
||||
using (var writer = JsonReaderWriterFactory.CreateJsonWriter(tempFile, Encoding.UTF8, ownsStream: false, indent: true))
|
||||
{
|
||||
serializer.WriteObject(writer, manifest);
|
||||
}
|
||||
}
|
||||
|
||||
if (!File.Exists(ManifestPath))
|
||||
{
|
||||
File.Move(tempFilePath, ManifestPath);
|
||||
return;
|
||||
}
|
||||
|
||||
var originalText = File.ReadAllText(ManifestPath);
|
||||
var newManifest = File.ReadAllText(tempFilePath);
|
||||
if (!string.Equals(originalText, newManifest, StringComparison.Ordinal))
|
||||
{
|
||||
// OnlyWriteWhenDifferent
|
||||
File.Delete(ManifestPath);
|
||||
File.Move(tempFilePath, ManifestPath);
|
||||
}
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class ManifestData
|
||||
{
|
||||
[DataMember]
|
||||
public CompressedFile[] FilesToCompress { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class CompressedFile
|
||||
{
|
||||
[DataMember]
|
||||
public string Source { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string InputSource { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string Target { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
// 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 System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Build
|
||||
{
|
||||
public class GenerateServiceWorkerAssetsManifest : Task
|
||||
{
|
||||
[Required]
|
||||
public string Version { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] AssetsWithHashes { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
using var fileStream = File.Create(OutputPath);
|
||||
WriteFile(fileStream);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void WriteFile(Stream stream)
|
||||
{
|
||||
var data = new AssetsManifestFile
|
||||
{
|
||||
version = Version,
|
||||
assets = AssetsWithHashes.Select(item => new AssetsManifestFileEntry
|
||||
{
|
||||
url = item.GetMetadata("AssetUrl"),
|
||||
hash = $"sha256-{item.GetMetadata("Integrity")}",
|
||||
}).ToArray()
|
||||
};
|
||||
|
||||
using var streamWriter = new StreamWriter(stream, Encoding.UTF8, bufferSize: 50, leaveOpen: true);
|
||||
streamWriter.Write("self.assetsManifest = ");
|
||||
streamWriter.Flush();
|
||||
|
||||
using var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, ownsStream: false, indent: true);
|
||||
new DataContractJsonSerializer(typeof(AssetsManifestFile)).WriteObject(jsonWriter, data);
|
||||
jsonWriter.Flush();
|
||||
|
||||
streamWriter.WriteLine(";");
|
||||
}
|
||||
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
public class AssetsManifestFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a version string.
|
||||
/// </summary>
|
||||
public string version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the assets. Keys are URLs; values are base-64-formatted SHA256 content hashes.
|
||||
/// </summary>
|
||||
public AssetsManifestFileEntry[] assets { get; set; }
|
||||
}
|
||||
|
||||
public class AssetsManifestFileEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the asset URL. Normally this will be relative to the application's base href.
|
||||
/// </summary>
|
||||
public string url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file content hash. This should be the base-64-formatted SHA256 value.
|
||||
/// </summary>
|
||||
public string hash { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
// 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 System.IO;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks
|
||||
{
|
||||
public class GenerateTypeGranularityLinkingConfig : Task
|
||||
{
|
||||
[Required]
|
||||
public ITaskItem[] Assemblies { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var linkerElement = new XElement("linker",
|
||||
new XComment(" THIS IS A GENERATED FILE - DO NOT EDIT MANUALLY "));
|
||||
|
||||
foreach (var assembly in Assemblies)
|
||||
{
|
||||
var assemblyElement = CreateTypeGranularityConfig(assembly);
|
||||
linkerElement.Add(assemblyElement);
|
||||
}
|
||||
|
||||
using var fileStream = File.Open(OutputPath, FileMode.Create);
|
||||
new XDocument(linkerElement).Save(fileStream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private XElement CreateTypeGranularityConfig(ITaskItem assembly)
|
||||
{
|
||||
// We match all types in the assembly, and for each one, tell the linker to preserve all
|
||||
// its members (preserve=all) but only if there's some reference to the type (required=false)
|
||||
return new XElement("assembly",
|
||||
new XAttribute("fullname", Path.GetFileNameWithoutExtension(assembly.ItemSpec)),
|
||||
new XElement("type",
|
||||
new XAttribute("fullname", "*"),
|
||||
new XAttribute("preserve", "all"),
|
||||
new XAttribute("required", "false")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
// 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 System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Runtime.Serialization.Json;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class GzipCompressBlazorApplicationFiles : Task
|
||||
{
|
||||
[Required]
|
||||
public string ManifestPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var serializer = new DataContractJsonSerializer(typeof(ManifestData));
|
||||
|
||||
ManifestData manifest = null;
|
||||
using (var tempFile = File.OpenRead(ManifestPath))
|
||||
{
|
||||
manifest = (ManifestData)serializer.ReadObject(tempFile);
|
||||
}
|
||||
|
||||
System.Threading.Tasks.Parallel.ForEach(manifest.FilesToCompress, (file) =>
|
||||
{
|
||||
var inputPath = file.Source;
|
||||
var inputSource = file.InputSource;
|
||||
var targetCompressionPath = file.Target;
|
||||
|
||||
if (!File.Exists(inputSource))
|
||||
{
|
||||
Log.LogMessage($"Skipping '{inputPath}' because '{inputSource}' does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(targetCompressionPath) && File.GetLastWriteTimeUtc(inputSource) < File.GetLastWriteTimeUtc(targetCompressionPath))
|
||||
{
|
||||
// Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing.
|
||||
Log.LogMessage($"Skipping '{inputPath}' because '{targetCompressionPath}' is newer than '{inputSource}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetCompressionPath));
|
||||
|
||||
using var sourceStream = File.OpenRead(inputPath);
|
||||
using var fileStream = new FileStream(targetCompressionPath, FileMode.Create);
|
||||
using var stream = new GZipStream(fileStream, CompressionLevel.Optimal);
|
||||
|
||||
sourceStream.CopyTo(stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.LogErrorFromException(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class ManifestData
|
||||
{
|
||||
[DataMember]
|
||||
public CompressedFile[] FilesToCompress { get; set; }
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
private class CompressedFile
|
||||
{
|
||||
[DataMember]
|
||||
public string Source { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string InputSource { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public string Target { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class ResolveBlazorRuntimeDependencies : Task
|
||||
{
|
||||
[Required]
|
||||
public string EntryPoint { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] ApplicationDependencies { get; set; }
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] WebAssemblyBCLAssemblies { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] Dependencies { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
var paths = ResolveRuntimeDependenciesCore(EntryPoint, ApplicationDependencies.Select(c => c.ItemSpec), WebAssemblyBCLAssemblies.Select(c => c.ItemSpec));
|
||||
Dependencies = paths.Select(p => new TaskItem(p)).ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ResolveRuntimeDependenciesCore(
|
||||
string entryPoint,
|
||||
IEnumerable<string> applicationDependencies,
|
||||
IEnumerable<string> monoBclAssemblies)
|
||||
{
|
||||
var entryAssembly = new AssemblyEntry(entryPoint, GetAssemblyName(entryPoint));
|
||||
|
||||
var dependencies = CreateAssemblyLookup(applicationDependencies);
|
||||
|
||||
var bcl = CreateAssemblyLookup(monoBclAssemblies);
|
||||
|
||||
var assemblyResolutionContext = new AssemblyResolutionContext(
|
||||
entryAssembly,
|
||||
dependencies,
|
||||
bcl);
|
||||
|
||||
assemblyResolutionContext.ResolveAssemblies();
|
||||
|
||||
var paths = assemblyResolutionContext.Results.Select(r => r.Path);
|
||||
return paths.Concat(FindPdbs(paths));
|
||||
|
||||
static Dictionary<string, AssemblyEntry> CreateAssemblyLookup(IEnumerable<string> assemblyPaths)
|
||||
{
|
||||
var dictionary = new Dictionary<string, AssemblyEntry>(StringComparer.Ordinal);
|
||||
foreach (var path in assemblyPaths)
|
||||
{
|
||||
var assemblyName = AssemblyName.GetAssemblyName(path).Name;
|
||||
if (dictionary.TryGetValue(assemblyName, out var previous))
|
||||
{
|
||||
throw new InvalidOperationException($"Multiple assemblies found with the same assembly name '{assemblyName}':" +
|
||||
Environment.NewLine + string.Join(Environment.NewLine, previous, path));
|
||||
}
|
||||
dictionary[assemblyName] = new AssemblyEntry(path, assemblyName);
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetAssemblyName(string assemblyPath)
|
||||
{
|
||||
return AssemblyName.GetAssemblyName(assemblyPath).Name;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> FindPdbs(IEnumerable<string> dllPaths)
|
||||
{
|
||||
return dllPaths
|
||||
.Select(path => Path.ChangeExtension(path, "pdb"))
|
||||
.Where(path => File.Exists(path));
|
||||
}
|
||||
|
||||
public class AssemblyResolutionContext
|
||||
{
|
||||
public AssemblyResolutionContext(
|
||||
AssemblyEntry entryAssembly,
|
||||
Dictionary<string, AssemblyEntry> dependencies,
|
||||
Dictionary<string, AssemblyEntry> bcl)
|
||||
{
|
||||
EntryAssembly = entryAssembly;
|
||||
Dependencies = dependencies;
|
||||
Bcl = bcl;
|
||||
}
|
||||
|
||||
public AssemblyEntry EntryAssembly { get; }
|
||||
public Dictionary<string, AssemblyEntry> Dependencies { get; }
|
||||
public Dictionary<string, AssemblyEntry> Bcl { get; }
|
||||
|
||||
public IList<AssemblyEntry> Results { get; } = new List<AssemblyEntry>();
|
||||
|
||||
internal void ResolveAssemblies()
|
||||
{
|
||||
var visitedAssemblies = new HashSet<string>();
|
||||
var pendingAssemblies = new Stack<string>();
|
||||
pendingAssemblies.Push(EntryAssembly.Name);
|
||||
ResolveAssembliesCore();
|
||||
|
||||
void ResolveAssembliesCore()
|
||||
{
|
||||
while (pendingAssemblies.Count > 0)
|
||||
{
|
||||
var current = pendingAssemblies.Pop();
|
||||
if (visitedAssemblies.Add(current))
|
||||
{
|
||||
// Not all references will be resolvable within the Mono BCL.
|
||||
// Skipping unresolved assemblies here is equivalent to passing "--skip-unresolved true" to the Mono linker.
|
||||
if (Resolve(current) is AssemblyEntry resolved)
|
||||
{
|
||||
Results.Add(resolved);
|
||||
var references = GetAssemblyReferences(resolved.Path);
|
||||
foreach (var reference in references)
|
||||
{
|
||||
pendingAssemblies.Push(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssemblyEntry? Resolve(string assemblyName)
|
||||
{
|
||||
if (EntryAssembly.Name == assemblyName)
|
||||
{
|
||||
return EntryAssembly;
|
||||
}
|
||||
|
||||
// Resolution logic. For right now, we will prefer the mono BCL version of a given
|
||||
// assembly if there is a candidate assembly and an equivalent mono assembly.
|
||||
if (Bcl.TryGetValue(assemblyName, out var assembly) ||
|
||||
Dependencies.TryGetValue(assemblyName, out assembly))
|
||||
{
|
||||
return assembly;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static IReadOnlyList<string> GetAssemblyReferences(string assemblyPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var peReader = new PEReader(File.OpenRead(assemblyPath));
|
||||
if (!peReader.HasMetadata)
|
||||
{
|
||||
return Array.Empty<string>(); // not a managed assembly
|
||||
}
|
||||
|
||||
var metadataReader = peReader.GetMetadataReader();
|
||||
|
||||
var references = new List<string>();
|
||||
foreach (var handle in metadataReader.AssemblyReferences)
|
||||
{
|
||||
var reference = metadataReader.GetAssemblyReference(handle);
|
||||
var referenceName = metadataReader.GetString(reference.Name);
|
||||
|
||||
references.Add(referenceName);
|
||||
}
|
||||
|
||||
return references;
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
// not a PE file, or invalid metadata
|
||||
}
|
||||
|
||||
return Array.Empty<string>(); // not a managed assembly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerDisplay("{ToString(),nq}")]
|
||||
public readonly struct AssemblyEntry
|
||||
{
|
||||
public AssemblyEntry(string path, string name)
|
||||
{
|
||||
Path = path;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Path { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\targets\All.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ReferencesComponentsWebAssemblyBuild>true</ReferencesComponentsWebAssemblyBuild>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\targets\All.targets" />
|
||||
</Project>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="Blazor.MonoRuntime.props" />
|
||||
|
||||
<Import Project="StaticWebAssets.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
<!-- Assets for a Blazor app are exposed on the root folder by default. -->
|
||||
<StaticWebAssetBasePath>/</StaticWebAssetBasePath>
|
||||
|
||||
<!-- When using IISExpress with a standalone app, there's no point restarting IISExpress after build. It slows things unnecessarily and breaks in-flight HTTP requests. -->
|
||||
<NoRestartServerOnBuild>true</NoRestartServerOnBuild>
|
||||
|
||||
<BlazorEnableCompression Condition="'$(BlazorEnableCompression)' == ''">true</BlazorEnableCompression>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<_BlazorToolsDir Condition="'$(_BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)..\tools\</_BlazorToolsDir>
|
||||
<_BlazorTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp</_BlazorTasksTFM>
|
||||
<_BlazorTasksTFM Condition=" '$(_BlazorTasksTFM)' == ''">netfx</_BlazorTasksTFM>
|
||||
<_BlazorTasksPath>$(_BlazorToolsDir)$(_BlazorTasksTFM)\Microsoft.AspNetCore.Components.WebAssembly.Build.Tasks.dll</_BlazorTasksPath>
|
||||
|
||||
<!-- The Blazor build code can only find your referenced assemblies if they are in the output directory -->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
||||
<!-- By default, enable debugging for debug builds. -->
|
||||
<BlazorEnableDebugging Condition="'$(Configuration)' == 'Debug' AND '$(BlazorEnableDebugging)' == ''">true</BlazorEnableDebugging>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Blazor.MonoRuntime.targets" />
|
||||
<Import Project="Publish.targets" />
|
||||
<Import Project="StaticWebAssets.targets" />
|
||||
<Import Project="ServiceWorkerAssetsManifest.targets" />
|
||||
<Import Project="Compression.targets" Condition="'$(BlazorEnableCompression)' == 'true'" />
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyI18NAssemblies>none</BlazorWebAssemblyI18NAssemblies> <!-- See Mono linker docs - allows comma-separated values from: none,all,cjk,mideast,other,rare,west -->
|
||||
<AdditionalMonoLinkerOptions>--disable-opt unreachablebodies --verbose --strip-security true --exclude-feature com -v false -c link -u link -b true</AdditionalMonoLinkerOptions>
|
||||
|
||||
<_BlazorJsPath Condition="'$(_BlazorJsPath)' == ''">$(MSBuildThisFileDirectory)..\tools\blazor\blazor.webassembly.js</_BlazorJsPath>
|
||||
<_BaseBlazorRuntimeOutputPath>_framework\</_BaseBlazorRuntimeOutputPath>
|
||||
<_BlazorRuntimeBinOutputPath>$(_BaseBlazorRuntimeOutputPath)_bin\</_BlazorRuntimeBinOutputPath>
|
||||
<_BlazorRuntimeWasmOutputPath>$(_BaseBlazorRuntimeOutputPath)wasm\</_BlazorRuntimeWasmOutputPath>
|
||||
<_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml</_BlazorBuiltInBclLinkerDescriptor>
|
||||
<_BlazorCollationLinkerDescriptor>$(MSBuildThisFileDirectory)CollationLinkerDescriptor.xml</_BlazorCollationLinkerDescriptor>
|
||||
<_BlazorBootJsonName>blazor.boot.json</_BlazorBootJsonName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<BlazorLinkerDescriptor Include="$(_BlazorBuiltInBclLinkerDescriptor)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,489 +0,0 @@
|
|||
<Project>
|
||||
<UsingTask TaskName="BlazorGetFileHash" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyEnableLinking Condition="'$(BlazorWebAssemblyEnableLinking)' == '' AND '$(Configuration)' != 'Debug'">true</BlazorWebAssemblyEnableLinking>
|
||||
<BlazorWebAssemblyEnableLinking Condition="'$(BlazorWebAssemblyEnableLinking)' == ''">false</BlazorWebAssemblyEnableLinking>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target
|
||||
Name="_PrepareBlazorOutputs"
|
||||
DependsOnTargets="_ResolveBlazorInputs;_ResolveBlazorOutputs;_GenerateBlazorBootJson;_GenerateBlazorBootJsonIntegrity">
|
||||
</Target>
|
||||
|
||||
<Target Name="_ResolveBlazorInputs" DependsOnTargets="ResolveReferences;ResolveRuntimePackAssets">
|
||||
<Error Text="BlazorLinkOnBuild has been renamed to BlazorWebAssemblyEnableLinking. Please update your project files to use the new property."
|
||||
Condition="'$(BlazorLinkOnBuild)' != ''" />
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- /obj/<<configuration>>/<<targetframework>>/blazor -->
|
||||
<_BlazorIntermediateOutputPath>$(IntermediateOutputPath)blazor\</_BlazorIntermediateOutputPath>
|
||||
|
||||
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/linker.descriptor.xml -->
|
||||
<_GeneratedBlazorLinkerDescriptor>$(_BlazorIntermediateOutputPath)linker.descriptor.xml</_GeneratedBlazorLinkerDescriptor>
|
||||
|
||||
<_TypeGranularityLinkerDescriptor>$(_BlazorIntermediateOutputPath)linker.typegranularityconfig.xml</_TypeGranularityLinkerDescriptor>
|
||||
|
||||
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/linker/ -->
|
||||
<_BlazorIntermediateLinkerOutputPath>$(_BlazorIntermediateOutputPath)linker/</_BlazorIntermediateLinkerOutputPath>
|
||||
|
||||
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/blazor.boot.json -->
|
||||
<_BlazorBootJsonIntermediateOutputPath>$(_BlazorIntermediateOutputPath)$(_BlazorBootJsonName)</_BlazorBootJsonIntermediateOutputPath>
|
||||
|
||||
<_BlazorLinkerOutputCache>$(_BlazorIntermediateOutputPath)linker.output</_BlazorLinkerOutputCache>
|
||||
|
||||
<_BlazorApplicationAssembliesCacheFile>$(_BlazorIntermediateOutputPath)unlinked.output</_BlazorApplicationAssembliesCacheFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
When running from Desktop MSBuild, DOTNET_HOST_PATH is not set.
|
||||
In this case, explicitly specify the path to the dotnet host.
|
||||
-->
|
||||
<PropertyGroup Condition=" '$(DOTNET_HOST_PATH)' == '' ">
|
||||
<_DotNetHostDirectory>$(NetCoreRoot)</_DotNetHostDirectory>
|
||||
<_DotNetHostFileName>dotnet</_DotNetHostFileName>
|
||||
<_DotNetHostFileName Condition=" '$(OS)' == 'Windows_NT' ">dotnet.exe</_DotNetHostFileName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_WebAssemblyBCLFolder Include="
|
||||
$(ComponentsWebAssemblyBaseClassLibraryPath);
|
||||
$(ComponentsWebAssemblyBaseClassLibraryFacadesPath);
|
||||
$(ComponentsWebAssemblyFrameworkPath)" />
|
||||
|
||||
<_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" />
|
||||
|
||||
<_BlazorConfigFile Include="wwwroot\appsettings*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
Calculate the assemblies that act as inputs to calculate assembly closure. Based on _ComputeAssembliesToPostprocessOnPublish which is used as input to SDK's linker
|
||||
https://github.com/dotnet/sdk/blob/d597e7b09d7657ba4e326d6734e14fcbf8473564/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L864-L873
|
||||
-->
|
||||
<ItemGroup>
|
||||
<!-- Assemblies from packages -->
|
||||
<_BlazorManagedRuntimeAssembly Include="@(RuntimeCopyLocalItems)" />
|
||||
|
||||
<!-- Assemblies from other references -->
|
||||
<_BlazorUserRuntimeAssembly Include="@(ReferencePath->WithMetadataValue('CopyLocal', 'true'))" />
|
||||
<_BlazorUserRuntimeAssembly Include="@(ReferenceDependencyPaths->WithMetadataValue('CopyLocal', 'true'))" />
|
||||
|
||||
<_BlazorManagedRuntimeAssembly Include="@(_BlazorUserRuntimeAssembly)" />
|
||||
<_BlazorManagedRuntimeAssembly Include="@(IntermediateAssembly)" />
|
||||
</ItemGroup>
|
||||
|
||||
<MakeDir Directories="$(_BlazorIntermediateOutputPath)" />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="BlazorWriteSatelliteAssemblyFile" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<UsingTask TaskName="BlazorReadSatelliteAssemblyFile" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
|
||||
<Target Name="_ResolveBlazorOutputs" DependsOnTargets="_ResolveBlazorOutputsWhenLinked;_ResolveBlazorOutputsWhenNotLinked">
|
||||
<!--
|
||||
These are the items calculated as the closure of the runtime assemblies, either by calling the linker
|
||||
or by calling our custom ResolveBlazorRuntimeDependencies task if the linker was disabled. Other than
|
||||
satellite assemblies, this should include all assemblies needed to run the application.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<_BlazorJSFile Include="$(_BlazorJSPath)" />
|
||||
<_BlazorJSFile Include="$(_BlazorJSMapPath)" Condition="Exists('$(_BlazorJSMapPath)')" />
|
||||
|
||||
<_DotNetWasmRuntimeFile Include="$(ComponentsWebAssemblyRuntimePath)*"/>
|
||||
<_DotNetWasmRuntimeFile
|
||||
Remove="%(Identity)"
|
||||
Condition="'$(BlazorEnableTimeZoneSupport)' == 'false' AND '%(FileName)%(Extension)' == 'dotnet.timezones.dat'" />
|
||||
|
||||
<!--
|
||||
ReferenceCopyLocalPaths includes all files that are part of the build out with CopyLocalLockFileAssemblies on.
|
||||
Remove assemblies that are inputs to calculating the assembly closure. Instead use the resolved outputs, since it is the minimal set.
|
||||
|
||||
ReferenceCopyLocalPaths also includes satellite assemblies from referenced projects but are inexpicably missing
|
||||
any metadata that might allow them to be differentiated. We'll explicitly add those
|
||||
to _BlazorOutputWithTargetPath so that satellite assemblies from packages, the current project and referenced project
|
||||
are all treated the same.
|
||||
-->
|
||||
<_BlazorCopyLocalPaths Include="@(ReferenceCopyLocalPaths)"
|
||||
Exclude="@(_BlazorManagedRuntimeAssembly);@(ReferenceSatellitePaths)"
|
||||
Condition="'%(Extension)' == '.dll'" />
|
||||
|
||||
<_BlazorCopyLocalPaths Include="@(IntermediateSatelliteAssembliesWithTargetPath)">
|
||||
<DestinationSubDirectory>%(IntermediateSatelliteAssembliesWithTargetPath.Culture)\</DestinationSubDirectory>
|
||||
</_BlazorCopyLocalPaths>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorCopyLocalPaths)">
|
||||
<!-- This group is for satellite assemblies. We set the resource name to include a path, e.g. "fr\\SomeAssembly.resources.dll" -->
|
||||
<BootManifestResourceType Condition="'%(_BlazorCopyLocalPaths.Extension)' == '.pdb'">pdb</BootManifestResourceType>
|
||||
<BootManifestResourceType Condition="'%(_BlazorCopyLocalPaths.Culture)' == '' AND '%(_BlazorCopyLocalPaths.Extension)' == '.dll'">assembly</BootManifestResourceType>
|
||||
<BootManifestResourceType Condition="'%(_BlazorCopyLocalPaths.Culture)' != '' AND '%(_BlazorCopyLocalPaths.Extension)' == '.dll'">satellite</BootManifestResourceType>
|
||||
<BootManifestResourceName>%(_BlazorCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)</BootManifestResourceName>
|
||||
<TargetOutputPath>$(_BlazorRuntimeBinOutputPath)%(_BlazorCopyLocalPaths.DestinationSubDirectory)%(FileName)%(Extension)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(ReferenceSatellitePaths)">
|
||||
<Culture>$([System.String]::Copy('%(ReferenceSatellitePaths.DestinationSubDirectory)').Trim('\').Trim('/'))</Culture>
|
||||
<BootManifestResourceType>satellite</BootManifestResourceType>
|
||||
<BootManifestResourceName>%(ReferenceSatellitePaths.DestinationSubDirectory)%(FileName)%(Extension)</BootManifestResourceName>
|
||||
<TargetOutputPath>$(_BlazorRuntimeBinOutputPath)%(ReferenceSatellitePaths.DestinationSubDirectory)%(FileName)%(Extension)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorResolvedAssembly)">
|
||||
<BootManifestResourceType Condition="'%(Extension)' == '.dll'">assembly</BootManifestResourceType>
|
||||
<BootManifestResourceType Condition="'%(Extension)' == '.pdb'">pdb</BootManifestResourceType>
|
||||
<BootManifestResourceType Condition="@(BlazorWebAssemblyLazyLoad->AnyHaveMetadataValue('Identity', '%(Filename)')) != ''">dynamicAssembly</BootManifestResourceType>
|
||||
<BootManifestResourceName>%(FileName)%(Extension)</BootManifestResourceName>
|
||||
<TargetOutputPath>$(_BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(_DotNetWasmRuntimeFile)">
|
||||
<TargetOutputPath>$(_BlazorRuntimeWasmOutputPath)%(FileName)%(Extension)</TargetOutputPath>
|
||||
<BootManifestResourceType>runtime</BootManifestResourceType>
|
||||
<BootManifestResourceName>%(FileName)%(Extension)</BootManifestResourceName>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorJSFile)">
|
||||
<TargetOutputPath>$(_BaseBlazorRuntimeOutputPath)%(FileName)%(Extension)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<_BlazorWriteSatelliteAssembly Include="@(_BlazorOutputWithTargetPath->WithMetadataValue('BootManifestResourceType', 'satellite'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
When building with BuildingProject=false, satellite assemblies do not get resolved (the ones for the current project and the one for
|
||||
referenced project). BuildingProject=false is typically set for referenced projects when building inside VisualStudio.
|
||||
To workaround this, we'll stash metadata during a regular build, and rehydrate from it when BuildingProject=false.
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorSatelliteAssemblyStashFile>$(_BlazorIntermediateOutputPath)blazor.satelliteasm.props</_BlazorSatelliteAssemblyStashFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<BlazorWriteSatelliteAssemblyFile
|
||||
SatelliteAssembly="@(_BlazorWriteSatelliteAssembly)"
|
||||
WriteFile="$(_BlazorSatelliteAssemblyStashFile)"
|
||||
Condition="'$(BuildingProject)' == 'true' AND '@(_BlazorWriteSatelliteAssembly->Count())' != '0'" />
|
||||
|
||||
<Delete
|
||||
Files="$(_BlazorSatelliteAssemblyStashFile)"
|
||||
Condition="'$(BuildingProject)' == 'true' AND '@(_BlazorWriteSatelliteAssembly->Count())' == '0' and EXISTS('$(_BlazorSatelliteAssemblyStashFile)')" />
|
||||
|
||||
<BlazorReadSatelliteAssemblyFile
|
||||
ReadFile="$(_BlazorSatelliteAssemblyStashFile)"
|
||||
Condition="'$(BuildingProject)' != 'true' AND EXISTS('$(_BlazorSatelliteAssemblyStashFile)')">
|
||||
<Output TaskParameter="SatelliteAssembly" ItemName="_BlazorReadSatelliteAssembly" />
|
||||
</BlazorReadSatelliteAssemblyFile>
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(_BlazorSatelliteAssemblyStashFile)" Condition="Exists('$(_BlazorSatelliteAssemblyStashFile)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'@(_BlazorReadSatelliteAssembly->Count())' != '0'">
|
||||
<!-- We've imported a previously stashed file. Let's turn in to a _BlazorOutputWithTargetPath -->
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorReadSatelliteAssembly)">
|
||||
<BootManifestResourceType>satellite</BootManifestResourceType>
|
||||
<BootManifestResourceName>%(_BlazorReadSatelliteAssembly.DestinationSubDirectory)%(FileName)%(Extension)</BootManifestResourceName>
|
||||
<TargetOutputPath>$(_BlazorRuntimeBinOutputPath)%(_BlazorReadSatelliteAssembly.DestinationSubDirectory)%(FileName)%(Extension)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
We need to know at build time (not publish time) whether or not to include pdbs in the
|
||||
blazor.boot.json file, so this is controlled by the BlazorEnableDebugging flag, whose
|
||||
default value is determined by the build configuration.
|
||||
-->
|
||||
<ItemGroup Condition="'$(BlazorEnableDebugging)' != 'true'">
|
||||
<_BlazorOutputWithTargetPath Remove="@(_BlazorOutputWithTargetPath)" Condition="'%(Extension)' == '.pdb'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ExistingBlazorOutputWithTargetPath Include="@(_BlazorOutputWithTargetPath)" Condition="Exists('%(FullPath)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<BlazorGetFileHash Files="@(_ExistingBlazorOutputWithTargetPath)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_BlazorOutputWithHash" />
|
||||
</BlazorGetFileHash>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorOutputWithIntegrity Include="@(_BlazorOutputWithHash)">
|
||||
<Integrity>%(_BlazorOutputWithHash.FileHash)</Integrity>
|
||||
<IntegrityFile>$(IntermediateOutputPath)integrity\$([System.String]::Copy('%(FileHash)').Replace('/','-').Replace('+','_')).hash</IntegrityFile>
|
||||
</_BlazorOutputWithIntegrity>
|
||||
|
||||
<_BlazorOutputWithTargetPath Remove="@(_BlazorOutputWithIntegrity)" />
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorOutputWithIntegrity)" RemoveMetadata="FileHash;FileHashAlgorithm" />
|
||||
|
||||
<MakeDir Directories="$(IntermediateOutputPath)integrity" />
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile Lines="%(_BlazorOutputWithIntegrity.Integrity)" File="%(_BlazorOutputWithIntegrity.IntegrityFile)" WriteOnlyWhenDifferent="true" Overwrite="true" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="%(_BlazorOutputWithIntegrity.IntegrityFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
Linker enabled part of the pipeline:
|
||||
|
||||
* If there are no descriptors defined, generate a new linker descriptor.
|
||||
* Invoke the linker and write linked files to a well-known directory.
|
||||
* Collect the outputs of the linker.
|
||||
-->
|
||||
|
||||
<Target
|
||||
Name="_ResolveBlazorOutputsWhenLinked"
|
||||
Condition="'$(BlazorWebAssemblyEnableLinking)' == 'true'"
|
||||
DependsOnTargets="_PrepareBlazorLinkerInputs;_GenerateBlazorLinkerDescriptor;_GenerateTypeGranularLinkerDescriptor;_LinkBlazorApplication">
|
||||
|
||||
<!-- _BlazorLinkerOutputCache records files linked during the last incremental build of the target. Read the contents and assign linked files to be copied to the output. -->
|
||||
<ReadLinesFromFile File="$(_BlazorLinkerOutputCache)">
|
||||
<Output TaskParameter="Lines" ItemName="_BlazorResolvedAssembly"/>
|
||||
</ReadLinesFromFile>
|
||||
</Target>
|
||||
|
||||
<Target Name="_PrepareBlazorLinkerInputs">
|
||||
<ItemGroup>
|
||||
<_BlazorRuntimeCopyLocalItems Include="@(RuntimeCopyLocalItems)" />
|
||||
|
||||
<!--
|
||||
Any assembly from a package reference that starts with System. file name is allowed to be linked.
|
||||
Assemblies from Microsoft.AspNetCore and Microsoft.Extensions, are also linked but with TypeGranularity.
|
||||
-->
|
||||
<_BlazorRuntimeCopyLocalItems IsLinkable="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('System.'))" />
|
||||
<_BlazorRuntimeCopyLocalItems IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))" />
|
||||
<_BlazorRuntimeCopyLocalItems IsLinkable="true" TypeGranularity="true" Condition="$([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.'))" />
|
||||
|
||||
<_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" />
|
||||
<_BlazorAssemblyToLink Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' == 'true'" />
|
||||
|
||||
<_BlazorLinkerRoot Include="@(IntermediateAssembly)" />
|
||||
<_BlazorLinkerRoot Include="@(_BlazorUserRuntimeAssembly)" />
|
||||
<_BlazorLinkerRoot Include="@(_BlazorRuntimeCopyLocalItems)" Condition="'%(_BlazorRuntimeCopyLocalItems.IsLinkable)' != 'true'" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- When specifically requested, include the linker substitutions file that strips out collation information.-->
|
||||
<PropertyGroup Condition="'$(BlazorWebAssemblyPreserveCollationData)' == 'false'">
|
||||
<AdditionalMonoLinkerOptions>$(AdditionalMonoLinkerOptions) --substitutions "$(_BlazorCollationLinkerDescriptor)"</AdditionalMonoLinkerOptions>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="BlazorCreateRootDescriptorFile" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<Target Name="_GenerateBlazorLinkerDescriptor"
|
||||
Inputs="@(IntermediateAssembly)"
|
||||
Outputs="$(_GeneratedBlazorLinkerDescriptor)">
|
||||
|
||||
<!-- Generate linker descriptors if the project doesn't explicitly provide one. -->
|
||||
|
||||
<BlazorCreateRootDescriptorFile
|
||||
AssemblyNames="@(IntermediateAssembly->'%(Filename)')"
|
||||
RootDescriptorFilePath="$(_GeneratedBlazorLinkerDescriptor)" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(_GeneratedBlazorLinkerDescriptor)" />
|
||||
<BlazorLinkerDescriptor Include="$(_GeneratedBlazorLinkerDescriptor)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="GenerateTypeGranularityLinkingConfig" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<Target Name="_GenerateTypeGranularLinkerDescriptor"
|
||||
Inputs="@(_BlazorAssemblyToLink->WithMetadataValue('TypeGranularity', 'true'))"
|
||||
Outputs="$(_TypeGranularityLinkerDescriptor)">
|
||||
|
||||
<GenerateTypeGranularityLinkingConfig
|
||||
Assemblies="@(_BlazorAssemblyToLink->WithMetadataValue('TypeGranularity', 'true'))"
|
||||
OutputPath="$(_TypeGranularityLinkerDescriptor)" />
|
||||
|
||||
<ItemGroup>
|
||||
<BlazorLinkerDescriptor Include="$(_TypeGranularityLinkerDescriptor)" />
|
||||
<FileWrites Include="$(_TypeGranularityLinkerDescriptor)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
Note that the VS-specific condition below is a workaround for https://github.com/dotnet/aspnetcore/issues/19822
|
||||
For more details, see https://github.com/dotnet/aspnetcore/issues/20413
|
||||
-->
|
||||
<UsingTask TaskName="BlazorILLink" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<Target
|
||||
Name="_LinkBlazorApplication"
|
||||
Inputs="$(ProjectAssetsFile);
|
||||
@(_BlazorManagedRuntimeAssembly);
|
||||
@(BlazorLinkerDescriptor);
|
||||
$(MSBuildAllProjects)"
|
||||
Outputs="$(_BlazorLinkerOutputCache)"
|
||||
Condition="'$(BuildingInsideVisualStudio)' != 'true' OR '$(DeployOnBuild)' != 'true'">
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorLinkerAdditionalOptions>-l $(BlazorWebAssemblyI18NAssemblies) $(AdditionalMonoLinkerOptions)</_BlazorLinkerAdditionalOptions>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_OldLinkedFile Include="$(_BlazorIntermediateLinkerOutputPath)*.dll" />
|
||||
<_OldLinkedFile Include="$(_BlazorIntermediateLinkerOutputPath)*.pdb" />
|
||||
</ItemGroup>
|
||||
|
||||
<Delete Files="@(_OldLinkedFile)" />
|
||||
|
||||
<BlazorILLink
|
||||
ILLinkPath="$(ComponentsWebAssemblyLinkerPath)"
|
||||
AssemblyPaths="@(_BlazorAssemblyToLink)"
|
||||
RootAssemblyNames="@(_BlazorLinkerRoot)"
|
||||
RootDescriptorFiles="@(BlazorLinkerDescriptor)"
|
||||
OutputDirectory="$(_BlazorIntermediateLinkerOutputPath)"
|
||||
ExtraArgs="$(_BlazorLinkerAdditionalOptions)"
|
||||
ToolExe="$(_DotNetHostFileName)"
|
||||
ToolPath="$(_DotNetHostDirectory)" />
|
||||
|
||||
<ItemGroup>
|
||||
<_LinkerResult Include="$(_BlazorIntermediateLinkerOutputPath)*.dll" />
|
||||
<_LinkerResult Include="$(_BlazorIntermediateLinkerOutputPath)*.pdb" />
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile File="$(_BlazorLinkerOutputCache)" Lines="@(_LinkerResult)" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="ResolveBlazorRuntimeDependencies" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<Target
|
||||
Name="_ResolveBlazorOutputsWhenNotLinked"
|
||||
DependsOnTargets="_ResolveBlazorRuntimeDependencies"
|
||||
Condition="'$(BlazorWebAssemblyEnableLinking)' != 'true'">
|
||||
|
||||
<ReadLinesFromFile File="$(_BlazorApplicationAssembliesCacheFile)" Condition="'@(_BlazorResolvedAssembly->Count())' == '0'">
|
||||
<Output TaskParameter="Lines" ItemName="_BlazorResolvedAssembly"/>
|
||||
</ReadLinesFromFile>
|
||||
|
||||
<ItemGroup>
|
||||
<!--
|
||||
Workaround for https://github.com/dotnet/aspnetcore/issues/19926. Add _BlazorResolvedAssembly to FileWrites so that these files
|
||||
do not get removed during an incremental build. Note that we add these files here as opposed to _ResolveBlazorRuntimeDependencies
|
||||
since the task that calculates these items in _ResolveBlazorRuntimeDependencies does not execute in incremental builds.
|
||||
-->
|
||||
<FileWrites Include="$(_BlazorResolvedAssembly)"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_ResolveBlazorRuntimeDependencies"
|
||||
Inputs="$(ProjectAssetsFile);
|
||||
@(IntermediateAssembly);
|
||||
@(_BlazorManagedRuntimeAssembly)"
|
||||
Outputs="$(_BlazorApplicationAssembliesCacheFile)">
|
||||
|
||||
<!--
|
||||
At this point we have decided not to run the linker and instead to just copy the assemblies
|
||||
from the BCL referenced by the app the nuget package into the _framework/_bin folder.
|
||||
The only thing we need to do here is collect the list of items that will go into _framework/_bin.
|
||||
-->
|
||||
<ResolveBlazorRuntimeDependencies
|
||||
EntryPoint="@(IntermediateAssembly)"
|
||||
ApplicationDependencies="@(_BlazorManagedRuntimeAssembly)"
|
||||
WebAssemblyBCLAssemblies="@(_WebAssemblyBCLAssembly)">
|
||||
|
||||
<Output TaskParameter="Dependencies" ItemName="_BlazorResolvedAssemblyUnlinked" />
|
||||
</ResolveBlazorRuntimeDependencies>
|
||||
|
||||
<ItemGroup Condition="'$(BlazorWebAssemblyI18NAssemblies)' != 'none'">
|
||||
<!--
|
||||
Unless the user has asked for no-assemblies, copy all I18N assemblies to the build output.
|
||||
We do not want to decipher the linker's format for passing in I18N options in our build targets
|
||||
-->
|
||||
<_BlazorResolvedAssemblyUnlinked Include="$(ComponentsWebAssemblyBaseClassLibraryPath)I18N*.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
Workaround for https://github.com/dotnet/aspnetcore/issues/19926. Using the files from their initial locations
|
||||
as-is causes RazorSDK to remove files from a hosted app's publish directory. This is because files being removed
|
||||
are looked up by their path. We'll copy files to an intermediate location to avoid the removal code.
|
||||
-->
|
||||
<Copy
|
||||
SourceFiles="@(_BlazorResolvedAssemblyUnlinked)"
|
||||
DestinationFolder="$(_BlazorIntermediateOutputPath)unlinked">
|
||||
<Output TaskParameter="CopiedFiles" ItemName="_BlazorResolvedAssembly" />
|
||||
</Copy>
|
||||
|
||||
<WriteLinesToFile File="$(_BlazorApplicationAssembliesCacheFile)" Lines="@(_BlazorResolvedAssembly)" Overwrite="true" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(_BlazorApplicationAssembliesCacheFile)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateBlazorBootJsonInputHash">
|
||||
<ItemGroup>
|
||||
<_BlazorBootJsonHashInput Include="@(IntermediateAssembly)" />
|
||||
<_BlazorBootJsonHashInput Include="@(_BlazorOutputWithTargetPath)" />
|
||||
<_BlazorBootJsonHashInput Include="@(_BlazorConfigFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Hash ItemsToHash="@(_BlazorBootJsonHashInput)">
|
||||
<Output TaskParameter="HashResult" PropertyName="_BlazorBootJsonInputHash" />
|
||||
</Hash>
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorBootJsonInputHashFile>$(_BlazorIntermediateOutputPath)boot.json.input</_BlazorBootJsonInputHashFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<WriteLinesToFile
|
||||
Lines="$(_BlazorBootJsonInputHash)"
|
||||
File="$(_BlazorBootJsonInputHashFile)"
|
||||
Overwrite="True"
|
||||
WriteOnlyWhenDifferent="True" />
|
||||
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="GenerateBlazorBootJson" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
|
||||
<Target
|
||||
Name="_GenerateBlazorBootJson"
|
||||
DependsOnTargets="_GenerateBlazorBootJsonInputHash"
|
||||
Inputs="$(MSBuildAllProjects);@(_BlazorOutputWithTargetPath);$(_BlazorBootJsonInputHashFile)"
|
||||
Outputs="$(_BlazorBootJsonIntermediateOutputPath)">
|
||||
|
||||
<PropertyGroup>
|
||||
<_IsDebugBuild>false</_IsDebugBuild>
|
||||
<_IsDebugBuild Condition="'$(Configuration)' == 'Debug'">true</_IsDebugBuild>
|
||||
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorBootResource Include="@(_BlazorOutputWithTargetPath->HasMetadata('BootManifestResourceType'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<GenerateBlazorBootJson
|
||||
AssemblyPath="@(IntermediateAssembly)"
|
||||
Resources="@(_BlazorBootResource)"
|
||||
DebugBuild="$(_IsDebugBuild)"
|
||||
LinkerEnabled="$(BlazorWebAssemblyEnableLinking)"
|
||||
CacheBootResources="$(BlazorCacheBootResources)"
|
||||
OutputPath="$(_BlazorBootJsonIntermediateOutputPath)"
|
||||
ConfigurationFiles="@(_BlazorConfigFile)" />
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateBlazorBootJsonIntegrity">
|
||||
|
||||
<GetFileHash Files="$(_BlazorBootJsonIntermediateOutputPath)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_BlazorBootJsonWithHash" />
|
||||
</GetFileHash>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<_BlazorBootJsonWithIntegrity Include="@(_BlazorBootJsonWithHash)">
|
||||
<Integrity>%(FileHash)</Integrity>
|
||||
<IntegrityFile>$(IntermediateOutputPath)integrity\$([System.String]::Copy('%(FileHash)').Replace('/','-').Replace('+','_')).hash</IntegrityFile>
|
||||
</_BlazorBootJsonWithIntegrity>
|
||||
|
||||
<_BlazorOutputWithTargetPath Include="@(_BlazorBootJsonWithIntegrity)" RemoveMetadata="FileHash;FileHashAlgorithm">
|
||||
<TargetOutputPath>$(_BaseBlazorRuntimeOutputPath)$(_BlazorBootJsonName)</TargetOutputPath>
|
||||
</_BlazorOutputWithTargetPath>
|
||||
|
||||
<FileWrites Include="$(_BlazorBootJsonIntermediateOutputPath)" />
|
||||
<FileWrites Include="%(_BlazorBootJsonWithIntegrity.IntegrityFile)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile Lines="%(_BlazorBootJsonWithIntegrity.Integrity)" File="%(_BlazorBootJsonWithIntegrity.IntegrityFile)" WriteOnlyWhenDifferent="true" Overwrite="true" />
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<linker>
|
||||
<!-- This file disables exclusions that remove collation data -->
|
||||
|
||||
<assembly fullname="mscorlib">
|
||||
<resource name="collation.cjkCHS.bin" action="remove"/>
|
||||
<resource name="collation.cjkCHT.bin" action="remove"/>
|
||||
<resource name="collation.cjkJA.bin" action="remove"/>
|
||||
<resource name="collation.cjkKO.bin" action="remove"/>
|
||||
<resource name="collation.cjkKOlv2.bin" action="remove"/>
|
||||
<resource name="collation.core.bin" action="remove"/>
|
||||
<resource name="collation.tailoring.bin" action="remove"/>
|
||||
|
||||
<type fullname="System.Globalization.CompareInfo">
|
||||
<method signature="System.Boolean get_IgnoreCaseNotSupported()" body="stub" value="true"/>
|
||||
</type>
|
||||
|
||||
<type fullname="System.Globalization.CompareInfo">
|
||||
<method signature="System.Boolean get_UseManagedCollation()" body="stub" value="false"/>
|
||||
</type>
|
||||
</assembly>
|
||||
</linker>
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
|
||||
<_BlazorBrotliPath>$(_BlazorToolsDir)compression\blazor-brotli.dll</_BlazorBrotliPath>
|
||||
<ResolveCurrentProjectStaticWebAssetsDependsOn>
|
||||
$(ResolveCurrentProjectStaticWebAssetsDependsOn);
|
||||
_ResolveBlazorFilesToCompress;
|
||||
</ResolveCurrentProjectStaticWebAssetsDependsOn>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_ResolveBlazorFilesToCompress" AfterTargets="_ResolveBlazorGeneratedAssets">
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorFilesIntermediateOutputPath>$(IntermediateOutputPath)compressed\</_BlazorFilesIntermediateOutputPath>
|
||||
<_GzipCompressionBlazorApplicationFilesManifestPath>$(IntermediateOutputPath)compressed\gzip.manifest.json</_GzipCompressionBlazorApplicationFilesManifestPath>
|
||||
<_BrotliCompressionBlazorApplicationFilesManifestPath>$(IntermediateOutputPath)compressed\brotli.manifest.json</_BrotliCompressionBlazorApplicationFilesManifestPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<MakeDir Directories="$(_BlazorFilesIntermediateOutputPath)" />
|
||||
<ItemGroup>
|
||||
|
||||
<_CompressionCandidate Include="@(StaticWebAsset)" Condition="'%(SourceType)' == '' and $([System.String]::Copy('%(RelativePath)').Replace('\','/').StartsWith('_framework/'))" KeepDuplicates="false" />
|
||||
<_CompressionCandidateIntegrity Include="@(_BlazorOutputWithTargetPath->'%(FullPath)')" />
|
||||
<_CompressionCandidateWithIntegrity Include="%(Identity)">
|
||||
<SourceType>@(_CompressionCandidate->'%(SourceType)')</SourceType>
|
||||
<SourceId>@(_CompressionCandidate->'%(SourceId)')</SourceId>
|
||||
<ContentRoot>@(_CompressionCandidate->'%(ContentRoot)')</ContentRoot>
|
||||
<BasePath>@(_CompressionCandidate->'%(BasePath)')</BasePath>
|
||||
<RelativePath>@(_CompressionCandidate->'%(RelativePath)')</RelativePath>
|
||||
<InputSource>@(_CompressionCandidateIntegrity->'%(IntegrityFile)')</InputSource>
|
||||
</_CompressionCandidateWithIntegrity>
|
||||
|
||||
<_GzipBlazorFileToCompress Include="@(_CompressionCandidateWithIntegrity)">
|
||||
<TargetCompressionPath>$(_BlazorFilesIntermediateOutputPath)%(RelativePath).gz</TargetCompressionPath>
|
||||
<TargetOutputPath>%(RelativePath).gz</TargetOutputPath>
|
||||
<RelativePath>%(RelativePath).gz</RelativePath>
|
||||
</_GzipBlazorFileToCompress>
|
||||
<_GzipBlazorFileToCompress Remove="@(_BlazorFileCompressExclusion)" />
|
||||
|
||||
<_BrotliBlazorFileToCompress Include="@(_CompressionCandidateWithIntegrity)">
|
||||
<TargetCompressionPath>$(_BlazorFilesIntermediateOutputPath)%(RelativePath).br</TargetCompressionPath>
|
||||
<TargetOutputPath>%(RelativePath).br</TargetOutputPath>
|
||||
<RelativePath>%(RelativePath).br</RelativePath>
|
||||
</_BrotliBlazorFileToCompress>
|
||||
<_BrotliBlazorFileToCompress Remove="@(_BlazorFileCompressExclusion)" />
|
||||
|
||||
<_BlazorFileToCompress Include="@(_GzipBlazorFileToCompress)" />
|
||||
<_BlazorFileToCompress Include="@(_BrotliBlazorFileToCompress)" />
|
||||
<_BlazorFileToCompress Remove="@(_BlazorFileCompressExclusion)" />
|
||||
|
||||
<_CompressedStaticWebAsset Include="@(_BlazorFileToCompress->'%(TargetCompressionPath)')" RemoveMetadata="TargetOutputPath;TargetCompressionPath" />
|
||||
|
||||
<StaticWebAsset Include="@(_CompressedStaticWebAsset->'%(FullPath)')" KeepMetadata="SourceType;SourceId;ContentRoot;BasePath;RelativePath" />
|
||||
<FileWrites Include="@(_CompressedStaticWebAsset)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="GzipCompressBlazorApplicationFiles" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<UsingTask TaskName="BrotliCompressBlazorApplicationFiles" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
<UsingTask TaskName="GenerateBlazorCompressionManifest" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
|
||||
<Target
|
||||
Name="_GzipCompressBlazorApplicationFiles"
|
||||
DependsOnTargets="ResolveStaticWebAssetsInputs"
|
||||
BeforeTargets="_BlazorStaticWebAssetsCopyGeneratedFilesToOutputDirectory"
|
||||
Inputs="$(_GzipCompressionBlazorApplicationFilesManifestPath)"
|
||||
Outputs="@(_GzipBlazorFileToCompress->'%(TargetCompressionPath)')">
|
||||
|
||||
<GzipCompressBlazorApplicationFiles ManifestPath="$(_GzipCompressionBlazorApplicationFilesManifestPath)" />
|
||||
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_GenerateGzipCompressionBlazorApplicationFilesManifest"
|
||||
BeforeTargets="_GzipCompressBlazorApplicationFiles"
|
||||
Inputs="@(_GzipBlazorFileToCompress->'%(InputSource)')"
|
||||
Outputs="$(_GzipCompressionBlazorApplicationFilesManifestPath)">
|
||||
|
||||
<GenerateBlazorCompressionManifest FilesToCompress="@(_GzipBlazorFileToCompress)" ManifestPath="$(_GzipCompressionBlazorApplicationFilesManifestPath)" />
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_BrotliCompressBlazorApplicationFiles"
|
||||
BeforeTargets="GetCopyToPublishDirectoryItems;_CopyResolvedFilesToPublishPreserveNewest"
|
||||
DependsOnTargets="ResolveStaticWebAssetsInputs"
|
||||
Inputs="$(_BrotliCompressionBlazorApplicationFilesManifestPath)"
|
||||
Outputs="@(_BrotliBlazorFileToCompress->'%(TargetCompressionPath)')">
|
||||
|
||||
<BrotliCompressBlazorApplicationFiles
|
||||
BlazorBrotliPath="$(_BlazorBrotliPath)"
|
||||
ManifestPath="$(_BrotliCompressionBlazorApplicationFilesManifestPath)"
|
||||
ToolExe="$(_DotNetHostFileName)"
|
||||
ToolPath="$(_DotNetHostDirectory)" />
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_GenerateBrotliCompressionBlazorApplicationFilesManifest"
|
||||
BeforeTargets="_GzipCompressBlazorApplicationFiles"
|
||||
Inputs="@(_BrotliBlazorFileToCompress->'%(InputSource)')"
|
||||
Outputs="$(_BrotliCompressionBlazorApplicationFilesManifestPath)">
|
||||
|
||||
<GenerateBlazorCompressionManifest FilesToCompress="@(_BrotliBlazorFileToCompress)" ManifestPath="$(_BrotliCompressionBlazorApplicationFilesManifestPath)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<!-- Disable unwanted parts of the default publish process -->
|
||||
<CopyBuildOutputToPublishDirectory>false</CopyBuildOutputToPublishDirectory>
|
||||
<CopyOutputSymbolsToPublishDirectory>false</CopyOutputSymbolsToPublishDirectory>
|
||||
<PreserveCompilationContext>false</PreserveCompilationContext>
|
||||
<RazorCompileOnPublish>false</RazorCompileOnPublish>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<IsWebConfigTransformDisabled>true</IsWebConfigTransformDisabled>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target
|
||||
Name="_BlazorCleanupPublishOutput"
|
||||
AfterTargets="ComputeResolvedFilesToPublishList"
|
||||
Condition="'$(BlazorPrunePublishOutput)' != 'false'">
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Delete stray contents from the root of the the app. -->
|
||||
<ResolvedFileToPublish
|
||||
Remove="%(ResolvedFileToPublish.Identity)"
|
||||
Condition="'%(ResolvedFileToPublish.RelativePath)' != 'web.config' AND !$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target
|
||||
Name="_BlazorCopyStandaloneWebConfig"
|
||||
AfterTargets="_BlazorCleanupPublishOutput;ComputeResolvedFilesToPublishList"
|
||||
Condition="'@(ResolvedFileToPublish->AnyHaveMetadataValue('RelativePath', 'web.config'))' != 'true'">
|
||||
|
||||
<ItemGroup>
|
||||
<ResolvedFileToPublish Include="$(MSBuildThisFileDirectory)Standalone.Web.config">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<RelativePath>web.config</RelativePath>
|
||||
</ResolvedFileToPublish>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<Target Name="_ComputeServiceWorkerAssetsManifestInputs"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
BeforeTargets="_ResolveBlazorOutputs;_ResolveBlazorFilesToCompress">
|
||||
|
||||
<PropertyGroup>
|
||||
<_ServiceWorkerAssetsManifestIntermediateOutputPath>$([MSBuild]::MakeRelative($(MSBuildProjectDirectory), $(_BlazorIntermediateOutputPath)))$(ServiceWorkerAssetsManifest)</_ServiceWorkerAssetsManifestIntermediateOutputPath>
|
||||
<_ServiceWorkerAssetsManifestFullPath>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)/$(_ServiceWorkerAssetsManifestIntermediateOutputPath)'))</_ServiceWorkerAssetsManifestFullPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorOutputWithTargetPath
|
||||
Include="$(_ServiceWorkerAssetsManifestFullPath)"
|
||||
TargetOutputPath="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" />
|
||||
|
||||
<_ManifestStaticWebAsset Include="$(_ServiceWorkerAssetsManifestFullPath)">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>$(ServiceWorkerAssetsManifest)</RelativePath>
|
||||
</_ManifestStaticWebAsset>
|
||||
|
||||
<StaticWebAsset Include="@(_ManifestStaticWebAsset)" />
|
||||
<_CompressionCandidate Include="@(_ManifestStaticWebAsset)" />
|
||||
<_CompressionCandidateWithIntegrity Include="@(_ManifestStaticWebAsset)">
|
||||
<InputSource>$(_ServiceWorkerAssetsManifestFullPath)</InputSource>
|
||||
</_CompressionCandidateWithIntegrity>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="GenerateServiceWorkerAssetsManifest" AssemblyFile="$(_BlazorTasksPath)" />
|
||||
|
||||
<Target Name="_WriteServiceWorkerAssetsManifest"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
Inputs="@(ServiceWorkerAssetsManifestItem)"
|
||||
Outputs="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)"
|
||||
BeforeTargets="_ComputeManifestIntegrity"
|
||||
DependsOnTargets="ResolveStaticWebAssetsInputs;_GenerateServiceWorkerIntermediateFiles">
|
||||
|
||||
<GenerateServiceWorkerAssetsManifest
|
||||
Version="$(ServiceWorkerAssetsManifestVersion)"
|
||||
AssetsWithHashes="@(_ServiceWorkerAssetsManifestItemWithHash)"
|
||||
OutputPath="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" />
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_ComputeManifestIntegrity"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
BeforeTargets="_BlazorStaticWebAssetsCopyGeneratedFilesToOutputDirectory;_GzipCompressBlazorApplicationFiles">
|
||||
|
||||
<GetFileHash Files="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_ServiceWorkerManifestWithHash" />
|
||||
</GetFileHash>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<_ServiceWorkerManifestWithIntegrity Include="@(_ServiceWorkerManifestWithHash)">
|
||||
<Integrity>%(FileHash)</Integrity>
|
||||
<IntegrityFile>$(IntermediateOutputPath)integrity\$([System.String]::Copy('%(FileHash)').Replace('/','-').Replace('+','_')).hash</IntegrityFile>
|
||||
</_ServiceWorkerManifestWithIntegrity>
|
||||
|
||||
<FileWrites Include="%(_ServiceWorkerManifestWithIntegrity.IntegrityFile)" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<WriteLinesToFile Lines="%(_ServiceWorkerManifestWithIntegrity.Integrity)" File="%(_ServiceWorkerManifestWithIntegrity.IntegrityFile)" WriteOnlyWhenDifferent="true" Overwrite="true" />
|
||||
|
||||
<PropertyGroup>
|
||||
<_ServiceWorkerManifestIntegrityFile>$(IntermediateOutputPath)integrity\$([System.String]::Copy('%(_ServiceWorkerManifestWithIntegrity.FileHash)').Replace('/','-').Replace('+','_')).hash</_ServiceWorkerManifestIntegrityFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_GzipFileToPatch Include="@(_GzipBlazorFileToCompress)" Condition="'%(Identity)' == '$(_ServiceWorkerAssetsManifestFullPath)'" KeepDuplicates="false">
|
||||
<InputSource>$(_ServiceWorkerManifestIntegrityFile)</InputSource>
|
||||
</_GzipFileToPatch>
|
||||
|
||||
<_GzipBlazorFileToCompress Remove="@(_GzipFileToPatch)" />
|
||||
<_GzipBlazorFileToCompress Include="@(_GzipFileToPatch)" />
|
||||
|
||||
<_BrotliFileToPatch Include="@(_BrotliBlazorFileToCompress)" Condition="'%(Identity)' == '$(_ServiceWorkerAssetsManifestFullPath)'" KeepDuplicates="false">
|
||||
<InputSource>$(_ServiceWorkerManifestIntegrityFile)</InputSource>
|
||||
</_BrotliFileToPatch>
|
||||
|
||||
<_BrotliBlazorFileToCompress Remove="@(_BrotliFileToPatch)" />
|
||||
<_BrotliBlazorFileToCompress Include="@(_BrotliFileToPatch)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_ComputeServiceWorkerAssetsManifestFileHashes"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
DependsOnTargets="ResolveStaticWebAssetsInputs;_BlazorComputeOtherAssetsIntegrity">
|
||||
|
||||
<ItemGroup>
|
||||
<ServiceWorkerAssetsManifestItem
|
||||
Include="%(StaticWebAsset.Identity)"
|
||||
Condition="'%(RelativePath)' != '$(ServiceWorkerAssetsManifest)'">
|
||||
<AssetUrl>$([System.String]::Copy('$([System.String]::Copy('%(StaticWebAsset.BasePath)').TrimEnd('/'))/%(StaticWebAsset.RelativePath)').Replace('\','/').TrimStart('/'))</AssetUrl>
|
||||
</ServiceWorkerAssetsManifestItem>
|
||||
|
||||
<!-- Don't include compressed files in the manifest, since their existence is transparent to the client -->
|
||||
<ServiceWorkerAssetsManifestItem Remove="@(_CompressedStaticWebAsset->'%(FullPath)')" />
|
||||
|
||||
<!-- Don't include the service worker files in the manifest, as the service worker doesn't need to fetch itself -->
|
||||
<ServiceWorkerAssetsManifestItem Remove="%(_ServiceWorkerIntermediateFile.FullPath)" />
|
||||
|
||||
<_ServiceWorkerExclude Include="@(_StaticWebAssetIntegrity)" />
|
||||
<_ServiceWorkerItemBase Include="@(ServiceWorkerAssetsManifestItem)" />
|
||||
<_ServiceWorkerItemBase Remove="@(_ServiceWorkerExclude)" />
|
||||
<_ServiceWorkerItemHash Include="@(ServiceWorkerAssetsManifestItem)" />
|
||||
<_ServiceWorkerItemHash Remove="@(_ServiceWorkerItemBase)" />
|
||||
<_ServiceWorkerAssetsManifestItemWithHash Include="%(Identity)">
|
||||
<AssetUrl>@(_ServiceWorkerItemHash->'%(AssetUrl)')</AssetUrl>
|
||||
<Integrity>@(_StaticWebAssetIntegrity->'%(Integrity)')</Integrity>
|
||||
</_ServiceWorkerAssetsManifestItemWithHash>
|
||||
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorComputeOtherAssetsIntegrity" Condition="'$(ServiceWorkerAssetsManifest)' != ''">
|
||||
<ItemGroup>
|
||||
<_StaticWebAssetsWithoutHash Include="@(StaticWebAsset)" Condition="'%(SourceType)' != '' or '%(ContentRoot)' == '$(_BlazorCurrentProjectWWWroot)'" />
|
||||
<_StaticWebAssetsWithoutHash Remove="@(_StaticWebAssetIntegrity)" />
|
||||
</ItemGroup>
|
||||
|
||||
<GetFileHash Files="@(_StaticWebAssetsWithoutHash)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_StaticWebAssetHash" />
|
||||
</GetFileHash>
|
||||
|
||||
<ItemGroup>
|
||||
<_StaticWebAssetIntegrity Include="%(_StaticWebAssetHash.Identity)">
|
||||
<Integrity>%(_StaticWebAssetHash.FileHash)</Integrity>
|
||||
</_StaticWebAssetIntegrity>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
|
||||
<!--
|
||||
Compute a default ServiceWorkerAssetsManifestVersion value by combining all the asset hashes.
|
||||
This is useful because then clients will only have to repopulate caches if the contents have changed.
|
||||
-->
|
||||
<Target Name="_ComputeDefaultServiceWorkerAssetsManifestVersion"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
DependsOnTargets="_ComputeServiceWorkerAssetsManifestFileHashes">
|
||||
<PropertyGroup>
|
||||
<_CombinedHashIntermediatePath>$(_BlazorIntermediateOutputPath)serviceworkerhashes.txt</_CombinedHashIntermediatePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Neither of these should ever happen, but if we do we want to know about it. -->
|
||||
<Error Text="Cannot compute service worker assets manifest version, because no service worker manifest items were defined."
|
||||
Condition="'@(_ServiceWorkerAssetsManifestItemWithHash)' == ''" />
|
||||
<Error Text="While computing service worker assets manifest version, did not find any dll entries in service worker assets manifest."
|
||||
Condition="'@(_ServiceWorkerAssetsManifestItemWithHash->WithMetadataValue('Extension', '.dll'))' == ''" />
|
||||
|
||||
<WriteLinesToFile
|
||||
File="$(_CombinedHashIntermediatePath)"
|
||||
Lines="@(_ServiceWorkerAssetsManifestItemWithHash->'%(Integrity)')"
|
||||
WriteOnlyWhenDifferent="true"
|
||||
Overwrite="true" />
|
||||
|
||||
<GetFileHash Files="$(_CombinedHashIntermediatePath)" Algorithm="SHA256" HashEncoding="base64">
|
||||
<Output TaskParameter="Items" ItemName="_ServiceWorkerAssetsManifestCombinedHash" />
|
||||
</GetFileHash>
|
||||
|
||||
<PropertyGroup>
|
||||
<ServiceWorkerAssetsManifestVersion Condition="'$(ServiceWorkerAssetsManifestVersion)' == ''">$([System.String]::Copy('%(_ServiceWorkerAssetsManifestCombinedHash.FileHash)').Substring(0, 8))</ServiceWorkerAssetsManifestVersion>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_OmitServiceWorkerContent"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
BeforeTargets="AssignTargetPaths;ResolveCurrentProjectStaticWebAssetsInputs">
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Don't emit the service worker source files to the output -->
|
||||
<Content Remove="@(ServiceWorker)" />
|
||||
<Content Remove="@(ServiceWorker->'%(PublishedContent)')" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_ResolveServiceWorkerOutputs"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
BeforeTargets="_ResolveBlazorOutputs"
|
||||
DependsOnTargets="_ComputeServiceWorkerOutputs">
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorFileCompressExclusion Include="@(_ServiceWorkerIntermediateFile->'%(FullPath)')" />
|
||||
|
||||
<_ServiceWorkerStaticWebAsset Include="@(_ServiceWorkerIntermediateFile->'%(FullPath)')">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>%(TargetOutputPath)</RelativePath>
|
||||
</_ServiceWorkerStaticWebAsset>
|
||||
|
||||
<StaticWebAsset Include="@(_ServiceWorkerStaticWebAsset)" />
|
||||
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_ComputeServiceWorkerOutputs"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''">
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Figure out where we're getting the content for each @(ServiceWorker) entry, depending on whether there's a PublishedContent value -->
|
||||
<_ServiceWorkerIntermediateFile Include="@(ServiceWorker->'$(IntermediateOutputPath)blazor\serviceworkers\%(Identity)')">
|
||||
<ContentSourcePath Condition="'%(ServiceWorker.PublishedContent)' != ''">%(ServiceWorker.PublishedContent)</ContentSourcePath>
|
||||
<ContentSourcePath Condition="'%(ServiceWorker.PublishedContent)' == ''">%(ServiceWorker.Identity)</ContentSourcePath>
|
||||
<TargetOutputPath>%(ServiceWorker.Identity)</TargetOutputPath>
|
||||
<TargetOutputPath Condition="$([System.String]::Copy('%(ServiceWorker.Identity)').Replace('\','/').StartsWith('wwwroot/'))">$([System.String]::Copy('%(ServiceWorker.Identity)').Substring(8))</TargetOutputPath>
|
||||
</_ServiceWorkerIntermediateFile>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_GenerateServiceWorkerIntermediateFiles"
|
||||
Condition="'$(ServiceWorkerAssetsManifest)' != ''"
|
||||
Inputs="@(_ServiceWorkerIntermediateFile->'%(ContentSourcePath)'); $(_CombinedHashIntermediatePath)"
|
||||
Outputs="@(_ServiceWorkerIntermediateFile)"
|
||||
DependsOnTargets="_ComputeDefaultServiceWorkerAssetsManifestVersion">
|
||||
<Copy SourceFiles="%(_ServiceWorkerIntermediateFile.ContentSourcePath)" DestinationFiles="%(_ServiceWorkerIntermediateFile.Identity)" />
|
||||
<WriteLinesToFile
|
||||
File="%(_ServiceWorkerIntermediateFile.Identity)"
|
||||
Lines="/* Manifest version: $(ServiceWorkerAssetsManifestVersion) */"
|
||||
Condition="'$(ServiceWorkerAssetsManifestVersion)' != ''" />
|
||||
<ItemGroup>
|
||||
<FileWrites Include="%(_ServiceWorkerIntermediateFile.Identity)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ResolveStaticWebAssetsInputsDependsOn>
|
||||
$(ResolveStaticWebAssetsInputsDependsOn);
|
||||
_BlazorApplyLinkPreferencesToStaticWebAssets;
|
||||
_ResolveBlazorGeneratedAssets;
|
||||
</ResolveStaticWebAssetsInputsDependsOn>
|
||||
|
||||
<GetCurrentProjectStaticWebAssetsDependsOn>
|
||||
$(GetCurrentProjectStaticWebAssetsDependsOn);
|
||||
_BlazorApplyLinkPreferencesToStaticWebAssets;
|
||||
_ResolveBlazorGeneratedAssets;
|
||||
</GetCurrentProjectStaticWebAssetsDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<_BlazorCurrentProjectWWWroot>$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)\wwwroot\'))</_BlazorCurrentProjectWWWroot>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_ResolveBlazorGeneratedAssets" DependsOnTargets="_PrepareBlazorOutputs">
|
||||
<ItemGroup>
|
||||
<_BlazorOutputCandidateAsset Include="@(_BlazorOutputWithTargetPath->'%(FullPath)')">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>$([System.String]::Copy('%(_BlazorOutputWithTargetPath.TargetOutputPath)').Replace('\','/'))</RelativePath>
|
||||
<Integrity>%(_BlazorOutputWithTargetPath.Integrity)</Integrity>
|
||||
</_BlazorOutputCandidateAsset>
|
||||
|
||||
<_BlazorOutputCandidateAsset Remove="@(StaticWebAsset)" />
|
||||
|
||||
<_StaticWebAssetIntegrity Include="@(_BlazorOutputCandidateAsset)" KeepMetadata="Integrity" />
|
||||
|
||||
<StaticWebAsset Include="@(_BlazorOutputCandidateAsset)" KeepMetadata="SourceType;SourceId;ContentRoot;BasePath;RelativePath" />
|
||||
|
||||
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="'$(BlazorEnableDebugging)' != 'true' and '%(SourceType)' == '' and '%(Extension)' == '.pdb'" />
|
||||
|
||||
<!-- We are depending on a "private" property for static web assets, but this is something we can clean-up in a later release.
|
||||
These files are not "external" in the "traditional" sense but it is fine for now as this is an implementation detail.
|
||||
We only need to do this for the standalone case, for hosted scenarios this works just fine as the assets are considered
|
||||
external. -->
|
||||
<_ExternalStaticWebAsset Include="@(_BlazorOutputWithTargetPath->'%(FullPath)')">
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<!-- We just do this to keep the existing implementation happy. We will update this in the next release. -->
|
||||
<SourceType>Generated</SourceType>
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
</_ExternalStaticWebAsset>
|
||||
|
||||
<!-- These items we are adding for forward-compatibility with newer SDK versions. The paths listed here will be added unconditionally
|
||||
to the generated static web assets manifest. This is only needed for forward compatibility in Blazor standalone scenarios. -->
|
||||
<StaticWebAssetsManifestPath Include="$([MSBuild]::NormalizeDirectory('$(TargetDir)wwwroot\'))">
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
</StaticWebAssetsManifestPath>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorStaticWebAssetsCopyGeneratedFilesToOutputDirectory"
|
||||
DependsOnTargets="ResolveStaticWebAssetsInputs;$(_BlazorCopyFilesToOutputDirectoryDependsOn)"
|
||||
AfterTargets="CopyFilesToOutputDirectory"
|
||||
Condition="'$(OutputType.ToLowerInvariant())'=='exe'">
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorCopyLocalAssets
|
||||
Include="@(StaticWebAsset)"
|
||||
Condition="'%(SourceType)' == '' and '%(ContentRoot)' != '$(_BlazorCurrentProjectWWWroot)' and !$([System.String]::Copy('%(RelativePath)').EndsWith('.br'))" />
|
||||
<_BlazorCopyLocalAssets Remove="@(_BlazorCopyLocalExclusion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy the blazor output files -->
|
||||
<Copy
|
||||
SourceFiles="@(_BlazorCopyLocalAssets)"
|
||||
DestinationFiles="@(_BlazorCopyLocalAssets->'%(ContentRoot)%(RelativePath)')"
|
||||
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
|
||||
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
|
||||
Retries="$(CopyRetryCount)"
|
||||
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
|
||||
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
|
||||
Condition="'@(_BlazorCopyLocalAssets)' != '' and '$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
|
||||
</Copy>
|
||||
|
||||
<ItemGroup>
|
||||
<FileWrites Include="@(_BlazorCopyLocalAssets->'%(ContentRoot)%(RelativePath)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_BlazorStatisticsOutput Include="@(_BlazorCopyLocalAssets->'%(RelativePath)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<Message Importance="high" Text="$(TargetName) (Blazor output) -> $(TargetDir)wwwroot" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_StaticWebAssetsBlazorStandalonePublish"
|
||||
AfterTargets="_StaticWebAssetsComputeFilesToPublish">
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<_CurrentProjectStandalonePublishStaticWebAsset Include="%(StaticWebAsset.FullPath)" Condition="'%(StaticWebAsset.SourceType)' == ''">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<RelativePath>$([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)','$([MSBuild]::NormalizePath('wwwroot\%(BasePath)\%(RelativePath)'))'))</RelativePath>
|
||||
</_CurrentProjectStandalonePublishStaticWebAsset>
|
||||
|
||||
<!-- Remove any existing external static web asset that might have been added as part of the
|
||||
regular publish pipeline. -->
|
||||
<ResolvedFileToPublish Remove="@(_CurrentProjectStandalonePublishStaticWebAsset)" />
|
||||
|
||||
<ResolvedFileToPublish Include="@(_CurrentProjectStandalonePublishStaticWebAsset)">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</ResolvedFileToPublish>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_BlazorApplyLinkPreferencesToStaticWebAssets">
|
||||
<ItemGroup>
|
||||
<_ContentWithWwrootLinkAttribute Include="@(Content)" Condition="'%(Content.Link)' != '' and $([System.String]::Copy('%(Content.Link)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
|
||||
<_ContentLinkedIntoWwwroot
|
||||
Include="@(_ContentWithWwrootLinkAttribute)"
|
||||
Condition="@(_ContentWithWwrootLinkAttribute) != '' and '%(_ContentWithWwrootLinkAttribute.CopyToPublishDirectory)' != 'false'">
|
||||
<!-- This gets rid of wwwroot\ -->
|
||||
<RelativePath>$([System.String]::Copy('%(Link)').Substring(8))</RelativePath>
|
||||
</_ContentLinkedIntoWwwroot>
|
||||
|
||||
<_OutsideContentLinkedIntoWwwroot Include="@(_ContentLinkedIntoWwwroot->'%(FullPath)')" Condition="@(_ContentLinkedIntoWwwroot) != '' and !$([System.String]::Copy('%(Identity)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
<_WwwrootLinkedContent Include="@(_ContentLinkedIntoWwwroot->'%(FullPath)')" Condition="@(_ContentLinkedIntoWwwroot) != '' and $([System.String]::Copy('%(Identity)').Replace('\','/').StartsWith('wwwroot/'))" KeepMetadata="RelativePath" />
|
||||
|
||||
<!-- For content items with the Link attribute on them, we update the relative path. This enables support at publish time for these assets but forgoes any
|
||||
dev-time support. (If you want to have dev-time support, you need to add an appropriate file into the wwwroot folder with CopyToPublishDirectory="false")
|
||||
-->
|
||||
<_NonLinkedStaticWebAssets Include="@(StaticWebAsset)" Exclude="@(_WwwrootLinkedContent)" />
|
||||
<_LinkedStaticWebAssets Include="@(StaticWebAsset)" Exclude="@(_NonLinkedStaticWebAssets)" />
|
||||
|
||||
<_UpdatedStaticWebAssets Include="%(Identity)">
|
||||
<SourceType>@(_LinkedStaticWebAssets->'%(SourceType)')</SourceType>
|
||||
<SourceId>@(_LinkedStaticWebAssets->'%(SourceId)')</SourceId>
|
||||
<ContentRoot>@(_LinkedStaticWebAssets->'%(ContentRoot)')</ContentRoot>
|
||||
<BasePath>@(_LinkedStaticWebAssets->'%(BasePath)')</BasePath>
|
||||
<RelativePath>@(_WwwrootLinkedContent->'%(RelativePath)')</RelativePath>
|
||||
</_UpdatedStaticWebAssets>
|
||||
|
||||
<StaticWebAsset Remove="@(_UpdatedStaticWebAssets)" />
|
||||
<StaticWebAsset Include="@(_UpdatedStaticWebAssets)" />
|
||||
|
||||
<!-- This allows limited publish time support for content items that are outside the wwwroot folder but are linked into the wwwroot folder. For example:
|
||||
* Imagine a set of items in <ProjectDir>/Client/publish that are linked into <ProjectDir>/wwwroot/.
|
||||
* We will consider them static web assets and default their content root to `<ProjectDir>/wwwroot` and their relative path will be whatever is after wwwroot\
|
||||
* We don't guarantee that these assets can be resolved at development time.
|
||||
* We do guarantee that we will copy them into the actual wwwroot folder at publish time.
|
||||
* If you want this type of dev-time support, the recomendation is to add the list of assets to the item group manually indicating a suitable content root.
|
||||
-->
|
||||
<StaticWebAsset Include="@(_OutsideContentLinkedIntoWwwroot)" Condition="@(_OutsideContentLinkedIntoWwwroot) != ''">
|
||||
<SourceType></SourceType>
|
||||
<SourceId>$(PackageId)</SourceId>
|
||||
<!-- We don't try to come up with a separate content root to make the inner loop work.
|
||||
You can add items with CopyToPublishDirectory=false for development time support or add the assets directly by pasing in the parameters
|
||||
-->
|
||||
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)\wwwroot\'))</ContentRoot>
|
||||
<BasePath>$(StaticWebAssetBasePath)</BasePath>
|
||||
<RelativePath>%(_OutsideContentLinkedIntoWwwroot.RelativePath)</RelativePath>
|
||||
</StaticWebAsset>
|
||||
|
||||
<_StaticWebAssetsPublishFalse Include="@(Content->'%(FullPath)')" Condition="'%(Content.CopyToPublishDirectory)' == 'false'" />
|
||||
<_StaticWebAssetsLinkOutsideWwwroot Include="@(Content->'%(FullPath)')" Condition="'%(Content.Link)' != '' and !$([System.String]::Copy('%(Content.Link)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
|
||||
<!-- Remove files that wouldn't be copied to the publish folder or that would be copied outside of the wwwroot folder if they were ever considered static web assets -->
|
||||
<StaticWebAsset Remove="@(_StaticWebAssetsPublishFalse)" />
|
||||
<StaticWebAsset Remove="@(_StaticWebAssetsLinkOutsideWwwroot)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
// 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 System.IO;
|
||||
using System.Xml.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class BlazorCreateRootDescriptorFileTest
|
||||
{
|
||||
[Fact]
|
||||
public void ProducesRootDescriptor()
|
||||
{
|
||||
// Arrange/Act
|
||||
using var stream = new MemoryStream();
|
||||
|
||||
// Act
|
||||
BlazorCreateRootDescriptorFile.WriteRootDescriptor(
|
||||
stream,
|
||||
new[] { "MyApp.dll" });
|
||||
|
||||
// Assert
|
||||
stream.Position = 0;
|
||||
var document = XDocument.Load(stream);
|
||||
var rootElement = document.Root;
|
||||
|
||||
var assemblyElement = Assert.Single(rootElement.Elements());
|
||||
Assert.Equal("assembly", assemblyElement.Name.ToString());
|
||||
Assert.Equal("MyApp.dll", assemblyElement.Attribute("fullname").Value);
|
||||
|
||||
var typeElement = Assert.Single(assemblyElement.Elements());
|
||||
Assert.Equal("type", typeElement.Name.ToString());
|
||||
Assert.Equal("*", typeElement.Attribute("fullname").Value);
|
||||
Assert.Equal("true", typeElement.Attribute("required").Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,396 +0,0 @@
|
|||
// 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 System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class BuildCompressionTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Build_WithLinkerAndCompression_IsIncremental()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
// Act
|
||||
var compressedFilesFolder = Path.Combine(project.IntermediateOutputDirectory, "compressed");
|
||||
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
|
||||
// Assert
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
|
||||
for (var j = 0; j < thumbPrint.Count; j++)
|
||||
{
|
||||
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithLinkerAndCompression_UpdatesFilesWhenSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var mainAppDll = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
var mainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var mainAppCompressedDll = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll.gz");
|
||||
var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
var blazorBootJson = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
var blazorBootJsonThumbPrint = FileThumbPrint.Create(blazorBootJson);
|
||||
var blazorBootJsonCompressed = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json.gz");
|
||||
var blazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);
|
||||
|
||||
// Act
|
||||
var programFile = Path.Combine(project.DirectoryPath, "Program.cs");
|
||||
var programFileContents = File.ReadAllText(programFile);
|
||||
File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
// Assert
|
||||
Assert.BuildPassed(result);
|
||||
var newMainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var newMainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
var newBlazorBootJsonThumbPrint = FileThumbPrint.Create(blazorBootJson);
|
||||
var newBlazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);
|
||||
|
||||
Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
|
||||
Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);
|
||||
|
||||
Assert.NotEqual(blazorBootJsonThumbPrint, newBlazorBootJsonThumbPrint);
|
||||
Assert.NotEqual(blazorBootJsonCompressedThumbPrint, newBlazorBootJsonCompressedThumbPrint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithoutLinkerAndCompression_IsIncremental()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
// Act
|
||||
var compressedFilesFolder = Path.Combine(project.IntermediateOutputDirectory, "compressed");
|
||||
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
|
||||
// Assert
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
|
||||
for (var j = 0; j < thumbPrint.Count; j++)
|
||||
{
|
||||
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithoutLinkerAndCompression_UpdatesFilesWhenSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
|
||||
// Act
|
||||
var mainAppDll = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
var mainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
|
||||
var mainAppCompressedDll = Path.Combine(project.DirectoryPath, project.BuildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll.gz");
|
||||
var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
var programFile = Path.Combine(project.DirectoryPath, "Program.cs");
|
||||
var programFileContents = File.ReadAllText(programFile);
|
||||
File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));
|
||||
|
||||
// Assert
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
Assert.BuildPassed(result);
|
||||
var newMainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var newMainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
|
||||
Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_CompressesAllFrameworkFiles()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var extensions = new[] { ".dll", ".js", ".pdb", ".wasm", ".map", ".json", ".dat" };
|
||||
// Act
|
||||
var compressedFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
project.IntermediateOutputDirectory,
|
||||
"compressed",
|
||||
"_framework");
|
||||
var compressedFiles = Directory.EnumerateFiles(
|
||||
compressedFilesPath,
|
||||
"*",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(f => Path.GetExtension(f) == ".gz")
|
||||
.Select(f => Path.GetRelativePath(compressedFilesPath, f[0..^3]))
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
|
||||
var frameworkFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
project.BuildOutputDirectory,
|
||||
"wwwroot",
|
||||
"_framework");
|
||||
var frameworkFiles = Directory.EnumerateFiles(
|
||||
frameworkFilesPath,
|
||||
"*",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(f => extensions.Contains(Path.GetExtension(f)))
|
||||
.Select(f => Path.GetRelativePath(frameworkFilesPath, f))
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
|
||||
Assert.Equal(frameworkFiles.Length, compressedFiles.Length);
|
||||
Assert.Equal(frameworkFiles, compressedFiles);
|
||||
|
||||
var brotliFiles = Directory.EnumerateFiles(
|
||||
compressedFilesPath,
|
||||
"*",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(f => Path.GetExtension(f) == ".br")
|
||||
.Select(f => Path.GetRelativePath(compressedFilesPath, f[0..^3]))
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
|
||||
// We don't compress things with brotli at build time
|
||||
Assert.Empty(brotliFiles);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_DisabledCompression_DoesNotCompressFiles()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
|
||||
// Act
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorEnableCompression=false");
|
||||
|
||||
//Assert
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var compressedFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
project.IntermediateOutputDirectory,
|
||||
"compressed");
|
||||
|
||||
Assert.False(Directory.Exists(compressedFilesPath));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_WithLinkerAndCompression_UpdatesFilesWhenSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary" });
|
||||
project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
// Act
|
||||
var mainAppDll = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
var mainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var mainAppCompressedDll = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll.br");
|
||||
var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
var blazorBootJson = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
var blazorBootJsonThumbPrint = FileThumbPrint.Create(blazorBootJson);
|
||||
var blazorBootJsonCompressed = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "blazor.boot.json.br");
|
||||
var blazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);
|
||||
|
||||
var programFile = Path.Combine(project.DirectoryPath, "..", "standalone", "Program.cs");
|
||||
var programFileContents = File.ReadAllText(programFile);
|
||||
File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));
|
||||
|
||||
// Assert
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish");
|
||||
Assert.BuildPassed(result);
|
||||
var newMainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var newMainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
var newBlazorBootJsonThumbPrint = FileThumbPrint.Create(blazorBootJson);
|
||||
var newBlazorBootJsonCompressedThumbPrint = FileThumbPrint.Create(blazorBootJsonCompressed);
|
||||
|
||||
Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
|
||||
Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);
|
||||
|
||||
Assert.NotEqual(blazorBootJsonThumbPrint, newBlazorBootJsonThumbPrint);
|
||||
Assert.NotEqual(blazorBootJsonCompressedThumbPrint, newBlazorBootJsonCompressedThumbPrint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_WithoutLinkerAndCompression_UpdatesFilesWhenSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary" });
|
||||
project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish", args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
// Act
|
||||
var mainAppDll = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
var mainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
|
||||
var mainAppCompressedDll = Path.Combine(project.DirectoryPath, project.PublishOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll.br");
|
||||
var mainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
var programFile = Path.Combine(project.DirectoryPath, "..", "standalone", "Program.cs");
|
||||
var programFileContents = File.ReadAllText(programFile);
|
||||
File.WriteAllText(programFile, programFileContents.Replace("args", "arguments"));
|
||||
|
||||
// Assert
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish", args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
Assert.BuildPassed(result);
|
||||
var newMainAppDllThumbPrint = FileThumbPrint.Create(mainAppDll);
|
||||
var newMainAppCompressedDllThumbPrint = FileThumbPrint.Create(mainAppCompressedDll);
|
||||
|
||||
Assert.NotEqual(mainAppDllThumbPrint, newMainAppDllThumbPrint);
|
||||
Assert.NotEqual(mainAppCompressedDllThumbPrint, newMainAppCompressedDllThumbPrint);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_WithLinkerAndCompression_IsIncremental()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
// Act
|
||||
var compressedFilesFolder = Path.Combine("..", "standalone", project.IntermediateOutputDirectory, "compressed");
|
||||
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
|
||||
// Assert
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
|
||||
for (var j = 0; j < thumbPrint.Count; j++)
|
||||
{
|
||||
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_WithoutLinkerAndCompression_IsIncremental()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish", args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
// Act
|
||||
var compressedFilesFolder = Path.Combine("..", "standalone", project.IntermediateOutputDirectory, "compressed");
|
||||
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
|
||||
// Assert
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:BlazorWebAssemblyEnableLinking=false");
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, compressedFilesFolder);
|
||||
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
|
||||
for (var j = 0; j < thumbPrint.Count; j++)
|
||||
{
|
||||
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_CompressesAllFrameworkFiles()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, target: "publish");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var extensions = new[] { ".dll", ".js", ".pdb", ".wasm", ".map", ".json", ".dat" };
|
||||
// Act
|
||||
var compressedFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
"..",
|
||||
"standalone",
|
||||
project.IntermediateOutputDirectory,
|
||||
"compressed",
|
||||
"_framework");
|
||||
var compressedFiles = Directory.EnumerateFiles(
|
||||
compressedFilesPath,
|
||||
"*",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(f => Path.GetExtension(f) == ".br")
|
||||
.Select(f => Path.GetRelativePath(compressedFilesPath, f[0..^3]))
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
|
||||
var frameworkFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
project.BuildOutputDirectory,
|
||||
"wwwroot",
|
||||
"_framework");
|
||||
var frameworkFiles = Directory.EnumerateFiles(
|
||||
frameworkFilesPath,
|
||||
"*",
|
||||
SearchOption.AllDirectories)
|
||||
.Where(f => extensions.Contains(Path.GetExtension(f)))
|
||||
.Select(f => Path.GetRelativePath(frameworkFilesPath, f))
|
||||
.OrderBy(f => f)
|
||||
.ToArray();
|
||||
|
||||
Assert.Equal(frameworkFiles.Length, compressedFiles.Length);
|
||||
Assert.Equal(frameworkFiles, compressedFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,361 +0,0 @@
|
|||
// 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 System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
using static Microsoft.AspNetCore.Components.WebAssembly.Build.WebAssemblyRuntimePackage;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class BuildIntegrationTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task Build_WithDefaultSettings_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Debug";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", DotNetJsFileName);
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.pdb");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.pdb");
|
||||
|
||||
var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "standalone.StaticWebAssets.xml");
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_InRelease_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Release";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", DotNetJsFileName);
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
|
||||
Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.pdb");
|
||||
Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "RazorClassLibrary.pdb");
|
||||
|
||||
var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "standalone.StaticWebAssets.xml");
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_ProducesBootJsonDataWithExpectedContent()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Debug";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var bootJsonPath = Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
var bootJsonData = ReadBootJsonData(result, bootJsonPath);
|
||||
|
||||
var runtime = bootJsonData.resources.runtime.Keys;
|
||||
Assert.Contains(DotNetJsFileName, runtime);
|
||||
Assert.Contains("dotnet.wasm", runtime);
|
||||
Assert.Contains("dotnet.timezones.dat", runtime);
|
||||
|
||||
var assemblies = bootJsonData.resources.assembly.Keys;
|
||||
Assert.Contains("standalone.dll", assemblies);
|
||||
Assert.Contains("RazorClassLibrary.dll", assemblies);
|
||||
Assert.Contains("Microsoft.Extensions.Logging.Abstractions.dll", assemblies);
|
||||
|
||||
var pdb = bootJsonData.resources.pdb.Keys;
|
||||
Assert.Contains("standalone.pdb", pdb);
|
||||
Assert.Contains("RazorClassLibrary.pdb", pdb);
|
||||
|
||||
Assert.Null(bootJsonData.resources.satelliteResources);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_InRelease_ProducesBootJsonDataWithExpectedContent()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Release";
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var bootJsonPath = Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
var bootJsonData = ReadBootJsonData(result, bootJsonPath);
|
||||
|
||||
var runtime = bootJsonData.resources.runtime.Keys;
|
||||
Assert.Contains(DotNetJsFileName, runtime);
|
||||
Assert.Contains("dotnet.wasm", runtime);
|
||||
Assert.Contains("dotnet.timezones.dat", runtime);
|
||||
|
||||
var assemblies = bootJsonData.resources.assembly.Keys;
|
||||
Assert.Contains("standalone.dll", assemblies);
|
||||
Assert.Contains("RazorClassLibrary.dll", assemblies);
|
||||
Assert.Contains("Microsoft.Extensions.Logging.Abstractions.dll", assemblies);
|
||||
|
||||
Assert.Null(bootJsonData.resources.pdb);
|
||||
Assert.Null(bootJsonData.resources.satelliteResources);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithBlazorEnableTimeZoneSupportDisabled_DoesNotCopyTimeZoneInfo()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Release";
|
||||
project.AddProjectFileContent(
|
||||
@"
|
||||
<PropertyGroup>
|
||||
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
|
||||
</PropertyGroup>");
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var bootJsonPath = Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
var bootJsonData = ReadBootJsonData(result, bootJsonPath);
|
||||
|
||||
var runtime = bootJsonData.resources.runtime.Keys;
|
||||
Assert.Contains("dotnet.wasm", runtime);
|
||||
Assert.DoesNotContain("dotnet.timezones.dat", runtime);
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
|
||||
Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_Hosted_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
|
||||
project.TargetFramework = TestFacts.DefaultNetCoreTargetFramework;
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
var path = Path.GetFullPath(Path.Combine(project.SolutionPath, "standalone", "bin", project.Configuration, "netstandard2.1", "standalone.dll"));
|
||||
Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
|
||||
var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "blazorhosted.StaticWebAssets.xml");
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("razorclasslibrary", "wwwroot"));
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("standalone", "wwwroot"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithLinkOnBuildDisabled_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.AddProjectFileContent(
|
||||
@"<PropertyGroup>
|
||||
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
|
||||
</PropertyGroup>");
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", DotNetJsFileName);
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.timezones.dat");
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[QuarantinedTest]
|
||||
public async Task Build_SatelliteAssembliesAreCopiedToBuildOutput()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" });
|
||||
project.AddProjectFileContent(
|
||||
@"
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" />
|
||||
</ItemGroup>");
|
||||
var resxfileInProject = Path.Combine(project.DirectoryPath, "Resources.ja.resx.txt");
|
||||
File.Move(resxfileInProject, Path.Combine(project.DirectoryPath, "Resource.ja.resx"));
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/restore");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "classlibrarywithsatelliteassemblies.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output.
|
||||
|
||||
var bootJsonPath = Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
Assert.FileContains(result, bootJsonPath, "\"Microsoft.CodeAnalysis.CSharp.dll\"");
|
||||
Assert.FileContains(result, bootJsonPath, "\"fr\\/Microsoft.CodeAnalysis.CSharp.resources.dll\"");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithBlazorWebAssemblyEnableLinkingFalse_SatelliteAssembliesAreCopiedToBuildOutput()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary", "classlibrarywithsatelliteassemblies" });
|
||||
project.AddProjectFileContent(
|
||||
@"
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
|
||||
<DefineConstants>$(DefineConstants);REFERENCE_classlibrarywithsatelliteassemblies</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include=""..\classlibrarywithsatelliteassemblies\classlibrarywithsatelliteassemblies.csproj"" />
|
||||
</ItemGroup>");
|
||||
|
||||
var resxfileInProject = Path.Combine(project.DirectoryPath, "Resources.ja.resx.txt");
|
||||
File.Move(resxfileInProject, Path.Combine(project.DirectoryPath, "Resource.ja.resx"));
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/restore");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "classlibrarywithsatelliteassemblies.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.CodeAnalysis.CSharp.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "fr", "Microsoft.CodeAnalysis.CSharp.resources.dll"); // Verify satellite assemblies are present in the build output.
|
||||
|
||||
var bootJson = ReadBootJsonData(result, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json"));
|
||||
|
||||
var satelliteResources = bootJson.resources.satelliteResources;
|
||||
Assert.NotNull(satelliteResources);
|
||||
|
||||
Assert.Contains("es-ES", satelliteResources.Keys);
|
||||
Assert.Contains("es-ES/classlibrarywithsatelliteassemblies.resources.dll", satelliteResources["es-ES"].Keys);
|
||||
Assert.Contains("fr", satelliteResources.Keys);
|
||||
Assert.Contains("fr/Microsoft.CodeAnalysis.CSharp.resources.dll", satelliteResources["fr"].Keys);
|
||||
Assert.Contains("ja", satelliteResources.Keys);
|
||||
Assert.Contains("ja/standalone.resources.dll", satelliteResources["ja"].Keys);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithI8NOption_CopiesI8NAssembliesWithoutLinkerEnabled()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Debug";
|
||||
project.AddProjectFileContent(
|
||||
@"
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyI18NAssemblies>other</BlazorWebAssemblyI18NAssemblies>
|
||||
</PropertyGroup>");
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.Other.dll");
|
||||
// When running without linker, we copy all I18N assemblies. Look for one additional
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.West.dll");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithI8NOption_CopiesI8NAssembliesWithLinkerEnabled()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
project.Configuration = "Debug";
|
||||
project.AddProjectFileContent(
|
||||
@"
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyEnableLinking>true</BlazorWebAssemblyEnableLinking>
|
||||
<BlazorWebAssemblyI18NAssemblies>other</BlazorWebAssemblyI18NAssemblies>
|
||||
</PropertyGroup>");
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project);
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.Other.dll");
|
||||
Assert.FileDoesNotExist(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "I18N.West.dll");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Build_WithCustomOutputPath_Works()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
|
||||
project.AddDirectoryBuildContent(
|
||||
@"<PropertyGroup>
|
||||
<BaseOutputPath>$(MSBuildThisFileDirectory)build\bin\</BaseOutputPath>
|
||||
<BaseIntermediateOutputPath>$(MSBuildThisFileDirectory)build\obj\</BaseIntermediateOutputPath>
|
||||
</PropertyGroup>");
|
||||
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/restore");
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var compressedFilesPath = Path.Combine(
|
||||
project.DirectoryPath,
|
||||
"build",
|
||||
project.IntermediateOutputDirectory,
|
||||
"compressed");
|
||||
|
||||
Assert.True(Directory.Exists(compressedFilesPath));
|
||||
}
|
||||
|
||||
private static GenerateBlazorBootJson.BootJsonData ReadBootJsonData(MSBuildResult result, string path)
|
||||
{
|
||||
return JsonSerializer.Deserialize<GenerateBlazorBootJson.BootJsonData>(
|
||||
File.ReadAllText(Path.Combine(result.Project.DirectoryPath, path)),
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
internal class FileThumbPrint : IEquatable<FileThumbPrint>
|
||||
{
|
||||
private FileThumbPrint(string path, DateTime lastWriteTimeUtc, string hash)
|
||||
{
|
||||
FilePath = path;
|
||||
LastWriteTimeUtc = lastWriteTimeUtc;
|
||||
Hash = hash;
|
||||
}
|
||||
|
||||
public string FilePath { get; }
|
||||
|
||||
public DateTime LastWriteTimeUtc { get; }
|
||||
|
||||
public string Hash { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Path.GetFileName(FilePath)}, {LastWriteTimeUtc.ToString("u")}, {Hash}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of thumbprints for all files (recursive) in the specified directory, sorted by file paths.
|
||||
/// </summary>
|
||||
public static List<FileThumbPrint> CreateFolderThumbprint(ProjectDirectory project, string directoryPath, params string[] filesToIgnore)
|
||||
{
|
||||
directoryPath = Path.Combine(project.DirectoryPath, directoryPath);
|
||||
var files = Directory.GetFiles(directoryPath).Where(p => !filesToIgnore.Contains(p));
|
||||
var thumbprintLookup = new List<FileThumbPrint>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
var thumbprint = Create(file);
|
||||
thumbprintLookup.Add(thumbprint);
|
||||
}
|
||||
|
||||
thumbprintLookup.Sort(Comparer<FileThumbPrint>.Create((a, b) => StringComparer.Ordinal.Compare(a.FilePath, b.FilePath)));
|
||||
return thumbprintLookup;
|
||||
}
|
||||
|
||||
public static FileThumbPrint Create(string path)
|
||||
{
|
||||
byte[] hashBytes;
|
||||
using (var sha1 = SHA1.Create())
|
||||
using (var fileStream = File.OpenRead(path))
|
||||
{
|
||||
hashBytes = sha1.ComputeHash(fileStream);
|
||||
}
|
||||
|
||||
var hash = Convert.ToBase64String(hashBytes);
|
||||
var lastWriteTimeUtc = File.GetLastWriteTimeUtc(path);
|
||||
return new FileThumbPrint(path, lastWriteTimeUtc, hash);
|
||||
}
|
||||
|
||||
public bool Equals(FileThumbPrint other)
|
||||
{
|
||||
return
|
||||
string.Equals(FilePath, other.FilePath, StringComparison.Ordinal) &&
|
||||
LastWriteTimeUtc == other.LastWriteTimeUtc &&
|
||||
string.Equals(Hash, other.Hash, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => LastWriteTimeUtc.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
internal static class MSBuildProcessManager
|
||||
{
|
||||
public static Task<MSBuildResult> DotnetMSBuild(
|
||||
ProjectDirectory project,
|
||||
string target = "Build",
|
||||
string args = null)
|
||||
{
|
||||
var buildArgumentList = new List<string>
|
||||
{
|
||||
// Disable node-reuse. We don't want msbuild processes to stick around
|
||||
// once the test is completed.
|
||||
"/nr:false",
|
||||
|
||||
// Always generate a bin log for debugging purposes
|
||||
"/bl",
|
||||
};
|
||||
|
||||
buildArgumentList.Add($"/t:{target}");
|
||||
buildArgumentList.Add($"/p:Configuration={project.Configuration}");
|
||||
buildArgumentList.Add($"/p:BlazorBuildConfiguration={ProjectDirectory.TestProjectConfiguration}");
|
||||
buildArgumentList.Add(args);
|
||||
|
||||
var buildArguments = string.Join(" ", buildArgumentList);
|
||||
|
||||
return MSBuildProcessManager.RunProcessAsync(project, buildArguments);
|
||||
}
|
||||
|
||||
public static async Task<MSBuildResult> RunProcessAsync(
|
||||
ProjectDirectory project,
|
||||
string arguments,
|
||||
TimeSpan? timeout = null)
|
||||
{
|
||||
var processStartInfo = new ProcessStartInfo()
|
||||
{
|
||||
WorkingDirectory = project.DirectoryPath,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
};
|
||||
|
||||
processStartInfo.FileName = DotNetMuxer.MuxerPathOrDefault();
|
||||
processStartInfo.Arguments = $"msbuild {arguments}";
|
||||
|
||||
// Suppresses the 'Welcome to .NET Core!' output that times out tests and causes locked file issues.
|
||||
// When using dotnet we're not guarunteed to run in an environment where the dotnet.exe has had its first run experience already invoked.
|
||||
processStartInfo.EnvironmentVariables["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true";
|
||||
processStartInfo.EnvironmentVariables["_BlazorWebAssemblyBuildTest_BrotliCompressionLevel_NoCompression"] = "1";
|
||||
|
||||
var processResult = await RunProcessCoreAsync(processStartInfo, timeout);
|
||||
|
||||
return new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output);
|
||||
}
|
||||
|
||||
internal static Task<ProcessResult> RunProcessCoreAsync(
|
||||
ProcessStartInfo processStartInfo,
|
||||
TimeSpan? timeout = null)
|
||||
{
|
||||
timeout = timeout ?? TimeSpan.FromSeconds(5 * 60);
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = processStartInfo,
|
||||
EnableRaisingEvents = true,
|
||||
};
|
||||
|
||||
var output = new StringBuilder();
|
||||
var outputLock = new object();
|
||||
|
||||
var diagnostics = new StringBuilder();
|
||||
diagnostics.AppendLine("Process execution diagnostics:");
|
||||
|
||||
process.ErrorDataReceived += Process_ErrorDataReceived;
|
||||
process.OutputDataReceived += Process_OutputDataReceived;
|
||||
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
var timeoutTask = GetTimeoutForProcess(process, timeout, diagnostics);
|
||||
|
||||
var waitTask = Task.Run(() =>
|
||||
{
|
||||
// We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously
|
||||
// this code used Process.Exited, which could result in us missing some output due to the ordering of
|
||||
// events.
|
||||
//
|
||||
// See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx
|
||||
if (!process.WaitForExit(Int32.MaxValue))
|
||||
{
|
||||
// unreachable - the timeoutTask will kill the process before this happens.
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
|
||||
string outputString;
|
||||
lock (outputLock)
|
||||
{
|
||||
// This marks the end of the diagnostic info which we collect when something goes wrong.
|
||||
diagnostics.AppendLine("Process output:");
|
||||
|
||||
// Expected output
|
||||
// Process execution diagnostics:
|
||||
// ...
|
||||
// Process output:
|
||||
outputString = diagnostics.ToString();
|
||||
outputString += output.ToString();
|
||||
}
|
||||
|
||||
var result = new ProcessResult(process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, outputString);
|
||||
return result;
|
||||
});
|
||||
|
||||
return Task.WhenAny<ProcessResult>(waitTask, timeoutTask).Unwrap();
|
||||
|
||||
void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
lock (outputLock)
|
||||
{
|
||||
output.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
|
||||
void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
lock (outputLock)
|
||||
{
|
||||
output.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<ProcessResult> GetTimeoutForProcess(Process process, TimeSpan? timeout, StringBuilder diagnostics)
|
||||
{
|
||||
await Task.Delay(timeout.Value);
|
||||
|
||||
// Don't timeout during debug sessions
|
||||
while (Debugger.IsAttached)
|
||||
{
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
}
|
||||
if (!process.HasExited)
|
||||
{
|
||||
await CollectDumps(process, timeout, diagnostics);
|
||||
|
||||
// This is a timeout.
|
||||
process.Kill();
|
||||
}
|
||||
|
||||
throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {timeout}. Output: {output.ToString()}");
|
||||
}
|
||||
|
||||
static async Task CollectDumps(Process process, TimeSpan? timeout, StringBuilder diagnostics)
|
||||
{
|
||||
var procDumpProcess = await CaptureDump(process, timeout, diagnostics);
|
||||
var allDotNetProcesses = Process.GetProcessesByName("dotnet");
|
||||
|
||||
var allDotNetChildProcessCandidates = allDotNetProcesses
|
||||
.Where(p => p.StartTime >= process.StartTime && p.Id != process.Id);
|
||||
|
||||
if (!allDotNetChildProcessCandidates.Any())
|
||||
{
|
||||
diagnostics.AppendLine("Couldn't find any candidate child process.");
|
||||
foreach (var dotnetProcess in allDotNetProcesses)
|
||||
{
|
||||
diagnostics.AppendLine($"Found dotnet process with PID {dotnetProcess.Id} and start time {dotnetProcess.StartTime}.");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var childProcess in allDotNetChildProcessCandidates)
|
||||
{
|
||||
diagnostics.AppendLine($"Found child process candidate '{childProcess.Id}'.");
|
||||
}
|
||||
|
||||
var childrenProcessDumpProcesses = await Task.WhenAll(allDotNetChildProcessCandidates.Select(d => CaptureDump(d, timeout, diagnostics)));
|
||||
foreach (var childProcess in childrenProcessDumpProcesses)
|
||||
{
|
||||
if (childProcess != null && childProcess.HasExited)
|
||||
{
|
||||
diagnostics.AppendLine($"ProcDump failed to run for child dotnet process candidate '{process.Id}'.");
|
||||
childProcess.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
if (procDumpProcess != null && procDumpProcess.HasExited)
|
||||
{
|
||||
diagnostics.AppendLine($"ProcDump failed to run for '{process.Id}'.");
|
||||
procDumpProcess.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
static async Task<Process> CaptureDump(Process process, TimeSpan? timeout, StringBuilder diagnostics)
|
||||
{
|
||||
var metadataAttributes = Assembly.GetExecutingAssembly()
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>();
|
||||
|
||||
var procDumpPath = metadataAttributes
|
||||
.SingleOrDefault(ama => ama.Key == "ProcDumpToolPath")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(procDumpPath))
|
||||
{
|
||||
diagnostics.AppendLine("ProcDumpPath not defined.");
|
||||
return null;
|
||||
}
|
||||
var procDumpExePath = Path.Combine(procDumpPath, "procdump.exe");
|
||||
if (!File.Exists(procDumpExePath))
|
||||
{
|
||||
diagnostics.AppendLine($"Can't find procdump.exe in '{procDumpPath}'.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var dumpDirectory = metadataAttributes
|
||||
.SingleOrDefault(ama => ama.Key == "ArtifactsLogDir")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(dumpDirectory))
|
||||
{
|
||||
diagnostics.AppendLine("ArtifactsLogDir not defined.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(dumpDirectory))
|
||||
{
|
||||
diagnostics.AppendLine($"'{dumpDirectory}' does not exist.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var procDumpPattern = Path.Combine(dumpDirectory, "HangingProcess_PROCESSNAME_PID_YYMMDD_HHMMSS.dmp");
|
||||
var procDumpStartInfo = new ProcessStartInfo(
|
||||
procDumpExePath,
|
||||
$"-accepteula -ma {process.Id} {procDumpPattern}")
|
||||
{
|
||||
CreateNoWindow = true,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
};
|
||||
|
||||
var procDumpProcess = Process.Start(procDumpStartInfo);
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
procDumpProcess.Exited += (s, a) => tcs.TrySetResult(null);
|
||||
procDumpProcess.EnableRaisingEvents = true;
|
||||
|
||||
await Task.WhenAny(tcs.Task, Task.Delay(timeout ?? TimeSpan.FromSeconds(30)));
|
||||
return procDumpProcess;
|
||||
}
|
||||
}
|
||||
|
||||
internal class ProcessResult
|
||||
{
|
||||
public ProcessResult(string fileName, string arguments, int exitCode, string output)
|
||||
{
|
||||
FileName = fileName;
|
||||
Arguments = arguments;
|
||||
ExitCode = exitCode;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public string Arguments { get; }
|
||||
|
||||
public string FileName { get; }
|
||||
|
||||
public int ExitCode { get; }
|
||||
|
||||
public string Output { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
internal class MSBuildResult
|
||||
{
|
||||
public MSBuildResult(ProjectDirectory project, string fileName, string arguments, int exitCode, string output)
|
||||
{
|
||||
Project = project;
|
||||
FileName = fileName;
|
||||
Arguments = arguments;
|
||||
ExitCode = exitCode;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public ProjectDirectory Project { get; }
|
||||
|
||||
public string Arguments { get; }
|
||||
|
||||
public string FileName { get; }
|
||||
|
||||
public int ExitCode { get; }
|
||||
|
||||
public string Output { get; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
internal class ProjectDirectory : IDisposable
|
||||
{
|
||||
public bool PreserveWorkingDirectory { get; set; } = false;
|
||||
|
||||
// Configuration the test project is building in.
|
||||
public static readonly string TestProjectConfiguration
|
||||
#if DEBUG
|
||||
= "Debug";
|
||||
#elif RELEASE
|
||||
= "Release";
|
||||
#else
|
||||
#error Configuration not supported
|
||||
#endif
|
||||
|
||||
private static readonly string RepoRoot = GetTestAttribute("Testing.RepoRoot");
|
||||
|
||||
public static ProjectDirectory Create(string projectName, string baseDirectory = "", string[] additionalProjects = null)
|
||||
{
|
||||
var destinationPath = Path.Combine(Path.GetTempPath(), "BlazorBuild", baseDirectory, Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(destinationPath);
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.EnumerateFiles(destinationPath).Any())
|
||||
{
|
||||
throw new InvalidOperationException($"{destinationPath} should be empty");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(RepoRoot))
|
||||
{
|
||||
throw new InvalidOperationException("RepoRoot was not specified.");
|
||||
}
|
||||
|
||||
var testAppsRoot = Path.Combine(RepoRoot, "src", "Components", "WebAssembly", "Build", "testassets");
|
||||
foreach (var project in new string[] { projectName, }.Concat(additionalProjects ?? Array.Empty<string>()))
|
||||
{
|
||||
var projectRoot = Path.Combine(testAppsRoot, project);
|
||||
if (!Directory.Exists(projectRoot))
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find project at '{projectRoot}'");
|
||||
}
|
||||
|
||||
var projectDestination = Path.Combine(destinationPath, project);
|
||||
var projectDestinationDir = Directory.CreateDirectory(projectDestination);
|
||||
CopyDirectory(new DirectoryInfo(projectRoot), projectDestinationDir);
|
||||
SetupDirectoryBuildFiles(RepoRoot, testAppsRoot, projectDestination);
|
||||
}
|
||||
|
||||
var directoryPath = Path.Combine(destinationPath, projectName);
|
||||
var projectPath = Path.Combine(directoryPath, projectName + ".csproj");
|
||||
|
||||
CopyRepositoryAssets(destinationPath);
|
||||
|
||||
return new ProjectDirectory(
|
||||
destinationPath,
|
||||
directoryPath,
|
||||
projectPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
CleanupDirectory(destinationPath);
|
||||
throw;
|
||||
}
|
||||
|
||||
static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination, bool recursive = true)
|
||||
{
|
||||
foreach (var file in source.EnumerateFiles())
|
||||
{
|
||||
file.CopyTo(Path.Combine(destination.FullName, file.Name));
|
||||
}
|
||||
|
||||
if (!recursive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var directory in source.EnumerateDirectories())
|
||||
{
|
||||
if (directory.Name == "bin")
|
||||
{
|
||||
// Just in case someone has opened the project in an IDE or built it. We don't want to copy
|
||||
// these folders.
|
||||
continue;
|
||||
}
|
||||
|
||||
var created = destination.CreateSubdirectory(directory.Name);
|
||||
if (directory.Name == "obj")
|
||||
{
|
||||
// Copy NuGet restore assets (viz all the files at the root of the obj directory, but stop there.)
|
||||
CopyDirectory(directory, created, recursive: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyDirectory(directory, created);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetupDirectoryBuildFiles(string repoRoot, string testAppsRoot, string projectDestination)
|
||||
{
|
||||
var razorSdkDirectoryRoot = TestFacts.RazorSdkDirectoryRoot;
|
||||
var beforeDirectoryPropsContent =
|
||||
$@"<Project>
|
||||
<PropertyGroup>
|
||||
<RepoRoot>{repoRoot}</RepoRoot>
|
||||
<RazorSdkDirectoryRoot>{razorSdkDirectoryRoot}</RazorSdkDirectoryRoot>
|
||||
</PropertyGroup>
|
||||
</Project>";
|
||||
File.WriteAllText(Path.Combine(projectDestination, "Before.Directory.Build.props"), beforeDirectoryPropsContent);
|
||||
|
||||
new List<string> { "Directory.Build.props", "Directory.Build.targets", }
|
||||
.ForEach(file =>
|
||||
{
|
||||
var source = Path.Combine(testAppsRoot, file);
|
||||
var destination = Path.Combine(projectDestination, file);
|
||||
File.Copy(source, destination);
|
||||
});
|
||||
}
|
||||
|
||||
static void CopyRepositoryAssets(string projectRoot)
|
||||
{
|
||||
const string GlobalJsonFileName = "global.json";
|
||||
var globalJsonPath = Path.Combine(RepoRoot, GlobalJsonFileName);
|
||||
|
||||
var destinationFile = Path.Combine(projectRoot, GlobalJsonFileName);
|
||||
File.Copy(globalJsonPath, destinationFile);
|
||||
}
|
||||
}
|
||||
|
||||
protected ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath)
|
||||
{
|
||||
SolutionPath = solutionPath;
|
||||
DirectoryPath = directoryPath;
|
||||
ProjectFilePath = projectFilePath;
|
||||
}
|
||||
|
||||
public string DirectoryPath { get; }
|
||||
|
||||
public string ProjectFilePath { get; }
|
||||
|
||||
public string SolutionPath { get; }
|
||||
|
||||
public string TargetFramework { get; set; } = "netstandard2.1";
|
||||
|
||||
public string Configuration { get; set; } = TestProjectConfiguration;
|
||||
|
||||
public string IntermediateOutputDirectory => Path.Combine("obj", Configuration, TargetFramework);
|
||||
|
||||
public string BuildOutputDirectory => Path.Combine("bin", Configuration, TargetFramework);
|
||||
|
||||
public string PublishOutputDirectory => Path.Combine(BuildOutputDirectory, "publish");
|
||||
|
||||
internal void AddProjectFileContent(string content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
var existing = File.ReadAllText(ProjectFilePath);
|
||||
var updated = existing.Replace("<!-- Test Placeholder -->", content);
|
||||
File.WriteAllText(ProjectFilePath, updated);
|
||||
}
|
||||
|
||||
internal void AddDirectoryBuildContent(string content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
var filepath = Path.Combine(DirectoryPath, "Directory.Build.props");
|
||||
|
||||
var existing = File.ReadAllText(filepath);
|
||||
var updated = existing.Replace("<!-- Test Placeholder -->", content);
|
||||
File.WriteAllText(filepath, updated);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (PreserveWorkingDirectory)
|
||||
{
|
||||
Console.WriteLine($"Skipping deletion of working directory {SolutionPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
CleanupDirectory(SolutionPath);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CleanupDirectory(string filePath)
|
||||
{
|
||||
var tries = 5;
|
||||
var sleep = TimeSpan.FromSeconds(3);
|
||||
|
||||
for (var i = 0; i < tries; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(filePath, recursive: true);
|
||||
return;
|
||||
}
|
||||
catch when (i < tries - 1)
|
||||
{
|
||||
Console.WriteLine($"Failed to delete directory {filePath}, trying again.");
|
||||
Thread.Sleep(sleep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTestAttribute(string key)
|
||||
{
|
||||
return typeof(ProjectDirectory).Assembly
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.FirstOrDefault(f => f.Key == key)
|
||||
?.Value;
|
||||
}
|
||||
|
||||
public override string ToString() => DirectoryPath;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class ProjectDirectoryTest
|
||||
{
|
||||
[Fact]
|
||||
public void ProjectDirectory_IsNotSetToBePreserved()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
|
||||
// Act & Assert
|
||||
// This flag is only meant for local debugging and should not be set when checking in.
|
||||
Assert.False(project.PreserveWorkingDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class PwaManifestTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Build_ServiceWorkerAssetsManifest_Works()
|
||||
{
|
||||
// Arrange
|
||||
var expectedExtensions = new[] { ".dll", ".pdb", ".js", ".wasm" };
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, args: "/p:ServiceWorkerAssetsManifest=service-worker-assets.js");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var buildOutputDirectory = project.BuildOutputDirectory;
|
||||
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.boot.json");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "blazor.webassembly.js");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "wasm", "dotnet.wasm");
|
||||
Assert.FileCountEquals(result, 1, Path.Combine(buildOutputDirectory, "wwwroot", "_framework", "wasm"), "dotnet.*.js");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "standalone.dll");
|
||||
Assert.FileExists(result, buildOutputDirectory, "wwwroot", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
|
||||
|
||||
var staticWebAssets = Assert.FileExists(result, buildOutputDirectory, "standalone.StaticWebAssets.xml");
|
||||
Assert.FileContains(result, staticWebAssets, Path.Combine("netstandard2.1", "wwwroot"));
|
||||
|
||||
var serviceWorkerAssetsManifest = Assert.FileExists(result, buildOutputDirectory, "wwwroot", "service-worker-assets.js");
|
||||
// Trim prefix 'self.assetsManifest = ' and suffix ';'
|
||||
var manifestContents = File.ReadAllText(serviceWorkerAssetsManifest).TrimEnd()[22..^1];
|
||||
|
||||
var manifestContentsJson = JsonDocument.Parse(manifestContents);
|
||||
Assert.True(manifestContentsJson.RootElement.TryGetProperty("assets", out var assets));
|
||||
Assert.Equal(JsonValueKind.Array, assets.ValueKind);
|
||||
|
||||
var entries = assets.EnumerateArray().Select(e => e.GetProperty("url").GetString()).OrderBy(e => e).ToArray();
|
||||
Assert.All(entries, e => expectedExtensions.Contains(Path.GetExtension(e)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_UpdatesServiceWorkerVersionHash_WhenSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:initial.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var publishOutputDirectory = project.PublishOutputDirectory;
|
||||
|
||||
var serviceWorkerFile = Assert.FileExists(result, publishOutputDirectory, "wwwroot", "serviceworkers", "my-service-worker.js");
|
||||
var version = File.ReadAllLines(serviceWorkerFile).Last();
|
||||
var match = Regex.Match(version, "\\/\\* Manifest version: (.{8}) \\*\\/");
|
||||
Assert.True(match.Success);
|
||||
Assert.Equal(2, match.Groups.Count);
|
||||
Assert.NotNull(match.Groups[1].Value);
|
||||
var capture = match.Groups[1].Value;
|
||||
|
||||
// Act
|
||||
var cssFile = Path.Combine(project.DirectoryPath, "LinkToWebRoot", "css", "app.css");
|
||||
File.WriteAllText(cssFile, ".updated { }");
|
||||
|
||||
// Assert
|
||||
var updatedResult = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:updated.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var updatedVersion = File.ReadAllLines(serviceWorkerFile).Last();
|
||||
var updatedMatch = Regex.Match(updatedVersion, "\\/\\* Manifest version: (.{8}) \\*\\/");
|
||||
Assert.True(updatedMatch.Success);
|
||||
Assert.Equal(2, updatedMatch.Groups.Count);
|
||||
Assert.NotNull(updatedMatch.Groups[1].Value);
|
||||
var updatedCapture = updatedMatch.Groups[1].Value;
|
||||
|
||||
Assert.NotEqual(capture, updatedCapture);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Publish_DeterministicAcrossBuilds_WhenNoSourcesChange()
|
||||
{
|
||||
// Arrange
|
||||
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
|
||||
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:initial.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var publishOutputDirectory = project.PublishOutputDirectory;
|
||||
|
||||
var serviceWorkerFile = Assert.FileExists(result, publishOutputDirectory, "wwwroot", "serviceworkers", "my-service-worker.js");
|
||||
var version = File.ReadAllLines(serviceWorkerFile).Last();
|
||||
var match = Regex.Match(version, "\\/\\* Manifest version: (.{8}) \\*\\/");
|
||||
Assert.True(match.Success);
|
||||
Assert.Equal(2, match.Groups.Count);
|
||||
Assert.NotNull(match.Groups[1].Value);
|
||||
var capture = match.Groups[1].Value;
|
||||
|
||||
// Act && Assert
|
||||
var updatedResult = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:updated.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
||||
var updatedVersion = File.ReadAllLines(serviceWorkerFile).Last();
|
||||
var updatedMatch = Regex.Match(updatedVersion, "\\/\\* Manifest version: (.{8}) \\*\\/");
|
||||
Assert.True(updatedMatch.Success);
|
||||
Assert.Equal(2, updatedMatch.Groups.Count);
|
||||
Assert.NotNull(updatedMatch.Groups[1].Value);
|
||||
var updatedCapture = updatedMatch.Groups[1].Value;
|
||||
|
||||
Assert.Equal(capture, updatedCapture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// 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 System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public static class TestFacts
|
||||
{
|
||||
public static string DefaultNetCoreTargetFramework =>
|
||||
GetAttributeValue(nameof(DefaultNetCoreTargetFramework));
|
||||
|
||||
public static string RazorSdkDirectoryRoot =>
|
||||
GetAttributeValue(nameof(RazorSdkDirectoryRoot));
|
||||
|
||||
private static string GetAttributeValue(string name)
|
||||
{
|
||||
return Assembly
|
||||
.GetExecutingAssembly()
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.FirstOrDefault(a => a.Key == $"Testing.{name}")
|
||||
.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
internal static class WebAssemblyRuntimePackage
|
||||
{
|
||||
public static readonly string ComponentsWebAssemblyRuntimePackageVersion;
|
||||
public static readonly string DotNetJsFileName;
|
||||
|
||||
static WebAssemblyRuntimePackage()
|
||||
{
|
||||
ComponentsWebAssemblyRuntimePackageVersion = typeof(WebAssemblyRuntimePackage)
|
||||
.Assembly
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.FirstOrDefault(f => f.Key == "Testing.MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion")
|
||||
?.Value
|
||||
?? throw new InvalidOperationException("Testing.MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion was not found");
|
||||
|
||||
DotNetJsFileName = $"dotnet.{ComponentsWebAssemblyRuntimePackageVersion}.js";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
|
||||
<!-- Exclude the TestFiles directory from default wildcards -->
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);TestFiles\**\*</DefaultItemExcludes>
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Embed test files so they can be referenced in tests -->
|
||||
<EmbeddedResource Include="TestFiles\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(GenerateBaselines)'=='true'">
|
||||
<DefineConstants>GENERATE_BASELINES;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Runtime" />
|
||||
<Reference Include="Microsoft.Build.Framework" />
|
||||
<Reference Include="Microsoft.Build.Utilities.Core" />
|
||||
<!-- Avoid CS1705 errors due to mix of assemblies brought in transitively. -->
|
||||
<Reference Include="Microsoft.AspNetCore.Components" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\testassets\StandaloneApp\StandaloneApp.csproj" />
|
||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.RepoRoot</_Parameter1>
|
||||
<_Parameter2>$(RepoRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.RazorSdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(ArtifactsBinDir)Microsoft.NET.Sdk.Razor\$(Configuration)\sdk-output\</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion</_Parameter1>
|
||||
<_Parameter2>$(MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Testing.DefaultNetCoreTargetFramework</_Parameter1>
|
||||
<_Parameter2>$(DefaultNetCoreTargetFramework)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="RestoreTestAssets" AfterTargets="Restore;Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
|
||||
<ItemGroup>
|
||||
<_TestAsset Include="..\testassets\standalone\standalone.csproj" />
|
||||
<_TestAsset Include="..\testassets\blazorhosted\blazorhosted.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<MSBuild
|
||||
Projects="@(_TestAsset)"
|
||||
Targets="Restore"
|
||||
Properties="
|
||||
RepoRoot=$(RepoRoot);
|
||||
MicrosoftNetCompilersToolsetPackageVersion=$(MicrosoftNetCompilersToolsetPackageVersion);
|
||||
MicrosoftNETSdkRazorPackageVersion=$(MicrosoftNETSdkRazorPackageVersion)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,181 +0,0 @@
|
|||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build
|
||||
{
|
||||
public class RuntimeDependenciesResolverTest
|
||||
{
|
||||
[Fact]
|
||||
[QuarantinedTest]
|
||||
public void FindsReferenceAssemblyGraph_ForStandaloneApp()
|
||||
{
|
||||
// Arrange
|
||||
var standaloneAppAssembly = typeof(StandaloneApp.Program).Assembly;
|
||||
var mainAssemblyLocation = standaloneAppAssembly.Location;
|
||||
|
||||
var hintPaths = ReadContent(standaloneAppAssembly, "StandaloneApp.referenceHints.txt");
|
||||
var bclLocations = ReadContent(standaloneAppAssembly, "StandaloneApp.bclLocations.txt");
|
||||
|
||||
var expectedContents = new[]
|
||||
{
|
||||
/*
|
||||
The current Mono WASM BCL forwards from netstandard.dll to various facade assemblies
|
||||
in which small bits of implementation live, such as System.Xml.XPath.XDocument. So
|
||||
if you reference netstandard, then you also reference System.Xml.XPath.XDocument.dll,
|
||||
even though you're very unlikely to be calling it at runtime. That's why the following
|
||||
list (for a very basic Blazor app) is longer than you'd expect.
|
||||
|
||||
These redundant references could be stripped out during publishing, but it's still
|
||||
unfortunate that in development mode you'd see all these unexpected assemblies get
|
||||
fetched from the server. We should try to get the Mono WASM BCL reorganized so that
|
||||
all the implementation goes into mscorlib.dll, with the facade assemblies existing only
|
||||
in case someone (or some 3rd party assembly) references them directly, but with their
|
||||
implementations 100% forwarding to mscorlib.dll. Then in development you'd fetch far
|
||||
fewer assemblies from the server, and during publishing, illink would remove all the
|
||||
uncalled implementation code from mscorlib.dll anyway.
|
||||
*/
|
||||
"Microsoft.AspNetCore.Components.dll",
|
||||
"Microsoft.AspNetCore.Components.Forms.dll",
|
||||
"Microsoft.AspNetCore.Components.Web.dll",
|
||||
"Microsoft.AspNetCore.Components.WebAssembly.dll",
|
||||
"Microsoft.Bcl.AsyncInterfaces.dll",
|
||||
"Microsoft.Extensions.Configuration.Abstractions.dll",
|
||||
"Microsoft.Extensions.Configuration.dll",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions.dll",
|
||||
"Microsoft.Extensions.Configuration.Json.dll",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions.dll",
|
||||
"Microsoft.Extensions.DependencyInjection.dll",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions.dll",
|
||||
"Microsoft.Extensions.FileProviders.Physical.dll",
|
||||
"Microsoft.Extensions.FileSystemGlobbing.dll",
|
||||
"Microsoft.Extensions.Logging.dll",
|
||||
"Microsoft.Extensions.Logging.Abstractions.dll",
|
||||
"Microsoft.Extensions.Options.dll",
|
||||
"Microsoft.Extensions.Primitives.dll",
|
||||
"Microsoft.JSInterop.dll",
|
||||
"Microsoft.JSInterop.WebAssembly.dll",
|
||||
"Mono.Security.dll",
|
||||
"mscorlib.dll",
|
||||
"netstandard.dll",
|
||||
"StandaloneApp.dll",
|
||||
"System.dll",
|
||||
"System.Buffers.dll",
|
||||
"System.Collections.Concurrent.dll",
|
||||
"System.Collections.dll",
|
||||
"System.ComponentModel.Annotations.dll",
|
||||
"System.ComponentModel.DataAnnotations.dll",
|
||||
"System.ComponentModel.Composition.dll",
|
||||
"System.Core.dll",
|
||||
"System.Data.dll",
|
||||
"System.Data.DataSetExtensions.dll",
|
||||
"System.Diagnostics.Debug.dll",
|
||||
"System.Diagnostics.DiagnosticSource.dll",
|
||||
"System.Diagnostics.Tracing.dll",
|
||||
"System.Drawing.Common.dll",
|
||||
"System.IO.Compression.dll",
|
||||
"System.IO.Compression.FileSystem.dll",
|
||||
"System.Memory.dll",
|
||||
"System.Net.Http.dll",
|
||||
"System.Net.Http.Json.dll",
|
||||
"System.Net.Http.WebAssemblyHttpHandler.dll",
|
||||
"System.Numerics.dll",
|
||||
"System.Numerics.Vectors.dll",
|
||||
"System.Reflection.dll",
|
||||
"System.Resources.ResourceManager.dll",
|
||||
"System.Runtime.Extensions.dll",
|
||||
"System.Runtime.InteropServices.dll",
|
||||
"System.Runtime.CompilerServices.Unsafe.dll",
|
||||
"System.Runtime.Serialization.dll",
|
||||
"System.Runtime.dll",
|
||||
"System.ServiceModel.Internals.dll",
|
||||
"System.Text.Encodings.Web.dll",
|
||||
"System.Text.Json.dll",
|
||||
"System.Threading.dll",
|
||||
"System.Threading.Tasks.Extensions.dll",
|
||||
"System.Transactions.dll",
|
||||
"System.Xml.dll",
|
||||
"System.Xml.Linq.dll",
|
||||
"WebAssembly.Bindings.dll",
|
||||
"WebAssembly.Net.WebSockets.dll",
|
||||
}.OrderBy(i => i, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
// Act
|
||||
|
||||
var paths = ResolveBlazorRuntimeDependencies
|
||||
.ResolveRuntimeDependenciesCore(
|
||||
mainAssemblyLocation,
|
||||
hintPaths,
|
||||
bclLocations);
|
||||
|
||||
var contents = paths
|
||||
.Select(p => Path.GetFileName(p))
|
||||
.Where(p => Path.GetExtension(p) != ".pdb")
|
||||
.OrderBy(i => i, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
|
||||
var expected = new HashSet<string>(expectedContents);
|
||||
var actual = new HashSet<string>(contents);
|
||||
|
||||
var contentNotFound = expected.Except(actual);
|
||||
var additionalContentFound = actual.Except(expected);
|
||||
|
||||
// Assert
|
||||
if (contentNotFound.Any() || additionalContentFound.Any())
|
||||
{
|
||||
throw new ContentMisMatchException
|
||||
{
|
||||
ContentNotFound = contentNotFound,
|
||||
AdditionalContentFound = additionalContentFound,
|
||||
};
|
||||
}
|
||||
|
||||
Assert.Equal(expectedContents, contents);
|
||||
}
|
||||
|
||||
private string[] ReadContent(Assembly standaloneAppAssembly, string fileName)
|
||||
{
|
||||
using var resource = standaloneAppAssembly.GetManifestResourceStream(fileName);
|
||||
using var streamReader = new StreamReader(resource);
|
||||
|
||||
return streamReader.ReadToEnd().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
private class ContentMisMatchException : Xunit.Sdk.XunitException
|
||||
{
|
||||
public IEnumerable<string> ContentNotFound { get; set; }
|
||||
|
||||
public IEnumerable<string> AdditionalContentFound { get; set; }
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
var error = new StringBuilder();
|
||||
if (ContentNotFound.Any())
|
||||
{
|
||||
error.Append($"Expected content not found: ")
|
||||
.AppendJoin(", ", ContentNotFound);
|
||||
}
|
||||
|
||||
if (AdditionalContentFound.Any())
|
||||
{
|
||||
error.Append("Unexpected content found: ")
|
||||
.AppendJoin(", ", AdditionalContentFound);
|
||||
}
|
||||
|
||||
return error.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="Before.Directory.Build.props" Condition="Exists('Before.Directory.Build.props')" />
|
||||
|
||||
<!-- Test Placeholder -->
|
||||
|
||||
<PropertyGroup>
|
||||
<RepoRoot Condition="'$(RepoRoot)' ==''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\</RepoRoot>
|
||||
<ComponentsRoot>$(RepoRoot)src\Components\</ComponentsRoot>
|
||||
<BlazorBuildRoot>$(ComponentsRoot)WebAssembly\Build\src\</BlazorBuildRoot>
|
||||
<ReferenceBlazorBuildFromSourceProps>$(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props</ReferenceBlazorBuildFromSourceProps>
|
||||
|
||||
<!-- Workaround for https://github.com/dotnet/aspnetcore/issues/17308 -->
|
||||
<DefaultNetCoreTargetFramework>netcoreapp3.1</DefaultNetCoreTargetFramework>
|
||||
|
||||
<EnableSourceLink>false</EnableSourceLink>
|
||||
<DeterministicSourcePaths>false</DeterministicSourcePaths>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(RepoRoot)eng\Versions.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Use the sample compiler \ SDK that the rest of our build uses-->
|
||||
<PackageReference Include="Microsoft.Net.Compilers.Toolset"
|
||||
Version="$(MicrosoftNetCompilersToolsetPackageVersion)"
|
||||
PrivateAssets="all"
|
||||
IsImplicitlyDefined="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Microsoft.NET.Sdk.Razor.props"/>
|
||||
</Project>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<Project>
|
||||
</Project>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\standalone\standalone.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Import Project="$(ReferenceBlazorBuildFromSourceProps)" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<ServiceWorkerAssetsManifest>custom-service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Test Placeholder -->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Runtime" Version="$(MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\razorclasslibrary\RazorClassLibrary.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- These assets should be treated as static web assets for publish purposes -->
|
||||
<Content Include="..\LinkBaseToWebRoot\**\*.js">
|
||||
<LinkBase>wwwroot\</LinkBase>
|
||||
</Content>
|
||||
|
||||
<!-- This asset should be ignored as a static web assets as it defines CopyToPublishDirectory="false" -->
|
||||
<Content Update="wwwroot\css\app.css" CopyToPublishDirectory="false" />
|
||||
|
||||
<!-- This asset should be treated as a static web asset and copied into the right location defined by its link attribute. -->
|
||||
<Content Include="LinkToWebRoot\css\app.css" Link="wwwroot\css\app.css" />
|
||||
|
||||
<!-- This asset should not be treated as a static web asset as it is being linked out of the wwwroot folder. -->
|
||||
<Content Update="wwwroot\Fake-License.txt" Link="Excluded-Static-Web-Assets\Fake-License.txt" />
|
||||
|
||||
<!-- The content from my-prod-service-worker.js should be published under the name my-service-worker.js -->
|
||||
<ServiceWorker Include="wwwroot\serviceworkers\my-service-worker.js" PublishedContent="wwwroot\serviceworkers\my-prod-service-worker.js" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>blazor-brotli</AssemblyName>
|
||||
<IsShippingPackage>false</IsShippingPackage>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Build.BrotliCompression
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private const int _error = -1;
|
||||
|
||||
static async Task<int> Main(string[] args)
|
||||
{
|
||||
if (args.Length != 1)
|
||||
{
|
||||
Console.Error.WriteLine("Invalid argument count. Usage: 'blazor-brotli <<path-to-manifest>>'");
|
||||
return _error;
|
||||
}
|
||||
|
||||
var manifestPath = args[0];
|
||||
if (!File.Exists(manifestPath))
|
||||
{
|
||||
Console.Error.WriteLine($"Manifest '{manifestPath}' does not exist.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
using var manifestStream = File.OpenRead(manifestPath);
|
||||
|
||||
var manifest = await JsonSerializer.DeserializeAsync<ManifestData>(manifestStream);
|
||||
var result = 0;
|
||||
Parallel.ForEach(manifest.FilesToCompress, (file) =>
|
||||
{
|
||||
var inputPath = file.Source;
|
||||
var inputSource = file.InputSource;
|
||||
var targetCompressionPath = file.Target;
|
||||
|
||||
if (!File.Exists(inputSource))
|
||||
{
|
||||
Console.WriteLine($"Skipping '{inputPath}' because '{inputSource}' does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(targetCompressionPath) && File.GetLastWriteTimeUtc(inputSource) < File.GetLastWriteTimeUtc(targetCompressionPath))
|
||||
{
|
||||
// Incrementalism. If input source doesn't exist or it exists and is not newer than the expected output, do nothing.
|
||||
Console.WriteLine($"Skipping '{inputPath}' because '{targetCompressionPath}' is newer than '{inputSource}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetCompressionPath));
|
||||
|
||||
using var sourceStream = File.OpenRead(inputPath);
|
||||
using var fileStream = new FileStream(targetCompressionPath, FileMode.Create);
|
||||
|
||||
var compressionLevel = CompressionLevel.Optimal;
|
||||
if (Environment.GetEnvironmentVariable("_BlazorWebAssemblyBuildTest_BrotliCompressionLevel_NoCompression") == "1")
|
||||
{
|
||||
compressionLevel = CompressionLevel.NoCompression;
|
||||
}
|
||||
using var stream = new BrotliStream(fileStream, compressionLevel);
|
||||
|
||||
sourceStream.CopyTo(stream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine(e);
|
||||
result = -1;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class ManifestData
|
||||
{
|
||||
public CompressedFile[] FilesToCompress { get; set; }
|
||||
}
|
||||
|
||||
private class CompressedFile
|
||||
{
|
||||
public string Source { get; set; }
|
||||
|
||||
public string InputSource { get; set; }
|
||||
|
||||
public string Target { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"rollForwardOnNoCandidateFx": 2
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
|
|
@ -15,6 +15,14 @@
|
|||
<Reference Include="Microsoft.Extensions.Logging" />
|
||||
<Reference Include="Microsoft.JSInterop.WebAssembly" />
|
||||
|
||||
<ProjectReference
|
||||
Include="..\..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework"
|
||||
Private="false"
|
||||
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
||||
|
||||
<!-- Tracking removing using https://github.com/dotnet/aspnetcore/issues/22283 -->
|
||||
<ProjectReference
|
||||
Include="..\..\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj"
|
||||
|
|
@ -35,4 +43,13 @@
|
|||
<InternalsVisibleTo Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests" />
|
||||
<InternalsVisibleTo Include="BasicTestApp" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyJSFile>..\..\..\Web.JS\dist\$(Configuration)\blazor.webassembly.js</BlazorWebAssemblyJSFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="$(BlazorWebAssemblyJSFile)" Pack="true" PackagePath="build\netstandard2.0\" LinkBase="build\netstandard2.0\" />
|
||||
<Content Include="build\netstandard2.0\*.props" Pack="true" PackagePath="build\netstandard2.0\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<BlazorWebAssemblyJSPath>$(MSBuildThisFileDirectory)blazor.webassembly.js</BlazorWebAssemblyJSPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<!-- Disable compression in this project so that we can validate that it can be disabled -->
|
||||
<BlazorEnableCompression>false</BlazorEnableCompression>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
|
||||
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MonoSanityClient\MonoSanityClient.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace MonoSanity
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
BuildWebHost(args).Run();
|
||||
}
|
||||
|
||||
public static IHost BuildWebHost(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webHostBuilder =>
|
||||
{
|
||||
// We require this line because we run in Production environment
|
||||
// and static web assets are only on by default during development.
|
||||
webHostBuilder.UseStaticWebAssets();
|
||||
webHostBuilder.UseStartup<Startup>();
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace MonoSanity
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseFileServer(new FileServerOptions() { EnableDefaultFiles = true, });
|
||||
app.UseBlazorFrameworkFiles();
|
||||
app.UseStaticFiles();
|
||||
app.UseRouting();
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapFallbackToFile("index.html");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Mono sanity check</title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<p>Simple sanity check to ensure the Mono runtime works in basic cases.</p>
|
||||
|
||||
<fieldset>
|
||||
<legend>Add numbers</legend>
|
||||
<form id="addNumbers">
|
||||
<input id="addNumberA" value="123" /> +
|
||||
<input id="addNumberB" value="456" /> =
|
||||
<input id="addNumbersResult" readonly />
|
||||
<button type="submit" disabled>Go</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Repeat string</legend>
|
||||
<form id="repeatString">
|
||||
<input id="repeatStringStr" value="Hello" /> *
|
||||
<input id="repeatStringCount" value="3" type="number" /> =
|
||||
<input id="repeatStringResult" readonly />
|
||||
<button type="submit" disabled>Go</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Trigger .NET exception</legend>
|
||||
<form id="triggerException">
|
||||
<input id="triggerExceptionMessage" value="Your message here" />
|
||||
<button type="submit" disabled>Go</button>
|
||||
<div><textarea rows="5" cols="80" readonly id="triggerExceptionMessageStackTrace"></textarea></div>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Call JS from .NET</legend>
|
||||
<form id="callJs">
|
||||
<input id="callJsEvalExpression" value="location.href" />
|
||||
<button type="submit" disabled>Go</button>
|
||||
<div><textarea rows="5" cols="80" readonly id="callJsResult"></textarea></div>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Call JS from .NET (no boxing)</legend>
|
||||
<form id="callJsNoBoxing">
|
||||
<input id="callJsNoBoxingNumberA" value="28" /> /
|
||||
<input id="callJsNoBoxingNumberB" value="4" /> =
|
||||
<input id="callJsNoBoxingResult" readonly />
|
||||
<button type="submit" disabled>Go</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Get runtime OS</legend>
|
||||
<form id="getRuntimeInformation">
|
||||
<button type="submit" disabled>Get</button>
|
||||
<input id="getRuntimeInformationResult" readonly />
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<p id="loadingIndicator">Loading...</p>
|
||||
|
||||
<script src="loader.js"></script>
|
||||
<script>
|
||||
initMono(['MonoSanityClient.dll', 'MonoSanityClient.pdb'], function () {
|
||||
var buttons = document.getElementsByTagName('button');
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
buttons[i].disabled = false;
|
||||
}
|
||||
el('loadingIndicator').style.display = 'none';
|
||||
window.isTestReady = true; // The Xunit code polls until this is true
|
||||
});
|
||||
|
||||
el('addNumbers').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var a = parseInt(el('addNumberA').value);
|
||||
var b = parseInt(el('addNumberB').value);
|
||||
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'AddNumbers', [a, b]);
|
||||
el('addNumbersResult').value = result;
|
||||
};
|
||||
|
||||
el('repeatString').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var str = el('repeatStringStr').value;
|
||||
var count = parseInt(el('repeatStringCount').value);
|
||||
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'RepeatString', [str, count]);
|
||||
el('repeatStringResult').value = result;
|
||||
};
|
||||
|
||||
el('triggerException').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var message = el('triggerExceptionMessage').value;
|
||||
try {
|
||||
invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'TriggerException', [message]);
|
||||
el('triggerExceptionMessageStackTrace').value = 'WARNING: No exception occurred';
|
||||
} catch (ex) {
|
||||
el('triggerExceptionMessageStackTrace').value = ex.toString();
|
||||
}
|
||||
};
|
||||
|
||||
el('callJs').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var expression = el('callJsEvalExpression').value;
|
||||
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'EvaluateJavaScript', [expression]);
|
||||
el('callJsResult').value = result;
|
||||
};
|
||||
|
||||
el('callJsNoBoxing').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var a = parseInt(el('callJsNoBoxingNumberA').value);
|
||||
var b = parseInt(el('callJsNoBoxingNumberB').value);
|
||||
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'CallJsNoBoxing', [a, b]);
|
||||
el('callJsNoBoxingResult').value = result;
|
||||
};
|
||||
|
||||
el('getRuntimeInformation').onsubmit = function (evt) {
|
||||
evt.preventDefault();
|
||||
var result = invokeMonoMethod('MonoSanityClient', 'MonoSanityClient', 'Examples', 'GetRuntimeInformation', []);
|
||||
el('getRuntimeInformationResult').value = result;
|
||||
};
|
||||
|
||||
function el(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
// Examples of functions we can invoke from .NET
|
||||
|
||||
function getUserAgentString() {
|
||||
return navigator.userAgent;
|
||||
}
|
||||
|
||||
function triggerJsException() {
|
||||
throw new Error('This is a JavaScript exception.');
|
||||
}
|
||||
|
||||
function evaluateJsExpression(dotNetStringExpression) {
|
||||
var result = eval(dotnetStringToJavaScriptString(dotNetStringExpression));
|
||||
return result === null || result === undefined
|
||||
? result // Pass through null/undefined so we can verify this is handled upstream
|
||||
: javaScriptStringToDotNetString(result.toString());
|
||||
}
|
||||
|
||||
function divideNumbersUnmarshalled(a, b) {
|
||||
// In this example, neither the arguments nor return value are boxed
|
||||
// -- we expect to receive and return numbers directly
|
||||
if (b === 0) {
|
||||
throw new Error('Division by zero');
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
(function () {
|
||||
// Implement just enough of the DotNet.* API surface for unmarshalled interop calls to work
|
||||
// in the cases used in this project
|
||||
window.DotNet = {
|
||||
jsCallDispatcher: {
|
||||
findJSFunction: function (identifier) {
|
||||
return window[identifier];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.initMono = function initMono(loadAssemblyUrls, onReadyCallback) {
|
||||
window.Module = {
|
||||
locateFile: function (fileName) {
|
||||
return fileName === 'dotnet.wasm' ? '/_framework/wasm/dotnet.wasm' : fileName;
|
||||
},
|
||||
onRuntimeInitialized: function () {
|
||||
var allAssemblyUrls = loadAssemblyUrls.concat([
|
||||
'netstandard.dll',
|
||||
'mscorlib.dll',
|
||||
'System.dll',
|
||||
'System.Core.dll',
|
||||
'System.Net.Http.dll',
|
||||
'System.Net.Http.WebAssemblyHttpHandler.dll',
|
||||
'WebAssembly.Bindings.dll'
|
||||
]);
|
||||
|
||||
// For these tests we're using Mono's built-in mono_load_runtime_and_bcl util.
|
||||
// In real apps we don't use this because we want to have more fine-grained
|
||||
// control over how the requests are issued, what gets logged, etc., so for
|
||||
// real apps Blazor's Boot.WebAssembly.ts implements its own equivalent.
|
||||
MONO.mono_load_runtime_and_bcl(
|
||||
/* vfx_prefix */ 'myapp', // Virtual filesystem root - arbitrary value
|
||||
/* deploy_prefix */ '_framework/_bin',
|
||||
/* enable_debugging */ 1,
|
||||
allAssemblyUrls,
|
||||
onReadyCallback
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
addScriptTagsToDocument();
|
||||
};
|
||||
|
||||
window.invokeMonoMethod = function invokeMonoMethod(assemblyName, namespace, typeName, methodName, args) {
|
||||
var assembly_load = Module.cwrap('mono_wasm_assembly_load', 'number', ['string']);
|
||||
var find_class = Module.cwrap('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']);
|
||||
var find_method = Module.cwrap('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']);
|
||||
|
||||
var assembly = assembly_load(assemblyName);
|
||||
var type = find_class(assembly, namespace, typeName);
|
||||
var method = find_method(type, methodName, -1);
|
||||
|
||||
var stack = Module.stackSave();
|
||||
try {
|
||||
var resultPtr = callMethod(method, null, args);
|
||||
return dotnetStringToJavaScriptString(resultPtr);
|
||||
}
|
||||
finally {
|
||||
Module.stackRestore(stack);
|
||||
}
|
||||
};
|
||||
|
||||
window.dotnetStringToJavaScriptString = function dotnetStringToJavaScriptString(mono_obj) {
|
||||
if (mono_obj === 0)
|
||||
return null;
|
||||
var mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
|
||||
var raw = mono_string_get_utf8(mono_obj);
|
||||
var res = Module.UTF8ToString(raw);
|
||||
Module._free(raw);
|
||||
return res;
|
||||
};
|
||||
|
||||
window.javaScriptStringToDotNetString = function dotnetStringToJavaScriptString(javaScriptString) {
|
||||
var mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
|
||||
return mono_string(javaScriptString);
|
||||
};
|
||||
|
||||
function callMethod(method, target, args) {
|
||||
var stack = Module.stackSave();
|
||||
var invoke_method = Module.cwrap('mono_wasm_invoke_method', 'number', ['number', 'number', 'number']);
|
||||
|
||||
try {
|
||||
var argsBuffer = Module.stackAlloc(args.length);
|
||||
var exceptionFlagManagedInt = Module.stackAlloc(4);
|
||||
for (var i = 0; i < args.length; ++i) {
|
||||
var argVal = args[i];
|
||||
if (typeof argVal === 'number') {
|
||||
var managedInt = Module.stackAlloc(4);
|
||||
Module.setValue(managedInt, argVal, 'i32');
|
||||
Module.setValue(argsBuffer + i * 4, managedInt, 'i32');
|
||||
} else if (typeof argVal === 'string') {
|
||||
var managedString = javaScriptStringToDotNetString(argVal);
|
||||
Module.setValue(argsBuffer + i * 4, managedString, 'i32');
|
||||
} else {
|
||||
throw new Error('Unsupported arg type: ' + typeof argVal);
|
||||
}
|
||||
}
|
||||
Module.setValue(exceptionFlagManagedInt, 0, 'i32');
|
||||
|
||||
var res = invoke_method(method, target, argsBuffer, exceptionFlagManagedInt);
|
||||
|
||||
if (Module.getValue(exceptionFlagManagedInt, 'i32') !== 0) {
|
||||
throw new Error(dotnetStringToJavaScriptString(res));
|
||||
}
|
||||
|
||||
return res;
|
||||
} finally {
|
||||
Module.stackRestore(stack);
|
||||
}
|
||||
}
|
||||
|
||||
async function addScriptTagsToDocument() {
|
||||
var browserSupportsNativeWebAssembly = typeof WebAssembly !== 'undefined' && WebAssembly.validate;
|
||||
if (!browserSupportsNativeWebAssembly) {
|
||||
throw new Error('This browser does not support WebAssembly.');
|
||||
}
|
||||
|
||||
var bootJson = await fetch('/_framework/blazor.boot.json').then(res => res.json());
|
||||
var dotNetJsResourceName = Object.keys(bootJson.resources.runtime)
|
||||
.filter(name => name.endsWith('.js'));
|
||||
|
||||
var scriptElem = document.createElement('script');
|
||||
scriptElem.src = '/_framework/wasm/' + dotNetJsResourceName;
|
||||
document.body.appendChild(scriptElem);
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// 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 WebAssembly.JSInterop;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace MonoSanityClient
|
||||
{
|
||||
public static class Examples
|
||||
{
|
||||
public static string AddNumbers(int a, int b)
|
||||
=> (a + b).ToString();
|
||||
|
||||
public static string RepeatString(string str, int count)
|
||||
{
|
||||
var result = new StringBuilder();
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
result.Append(str);
|
||||
}
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static void TriggerException(string message)
|
||||
{
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
public static string EvaluateJavaScript(string expression)
|
||||
{
|
||||
var result = InternalCalls.InvokeJSUnmarshalled<string, string, object, object>(out var exceptionMessage, "evaluateJsExpression", expression, null, null);
|
||||
if (exceptionMessage != null)
|
||||
{
|
||||
return $".NET got exception: {exceptionMessage}";
|
||||
}
|
||||
|
||||
return $".NET received: {(result ?? "(NULL)")}";
|
||||
}
|
||||
|
||||
public static string CallJsNoBoxing(int numberA, int numberB)
|
||||
{
|
||||
// For tests that call this method, we'll exercise the 'BlazorInvokeJS' code path
|
||||
// since that doesn't box the params
|
||||
var result = InternalCalls.InvokeJSUnmarshalled<int, int, object, int>(out var exceptionMessage, "divideNumbersUnmarshalled", numberA, numberB, null);
|
||||
if (exceptionMessage != null)
|
||||
{
|
||||
return $".NET got exception: {exceptionMessage}";
|
||||
}
|
||||
|
||||
return $".NET received: {result}";
|
||||
}
|
||||
|
||||
public static string GetRuntimeInformation()
|
||||
=> $"OSDescription: '{RuntimeInformation.OSDescription}';"
|
||||
+ $" OSArchitecture: '{RuntimeInformation.OSArchitecture}';"
|
||||
+ $" IsOSPlatform(BROWSER): '{RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"))}'";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
// 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 System.Runtime.CompilerServices;
|
||||
|
||||
namespace WebAssembly.JSInterop
|
||||
{
|
||||
// This file is copied from https://github.com/dotnet/jsinterop/blob/master/src/Mono.WebAssembly.Interop/InternalCalls.cs
|
||||
// so that MonoSanityClient can directly use the same underlying interop APIs (because
|
||||
// we're trying to observe the behavior of the Mono runtime itself, not JSInterop).
|
||||
|
||||
internal class InternalCalls
|
||||
{
|
||||
// The exact namespace, type, and method names must match the corresponding entries
|
||||
// in driver.c in the Mono distribution
|
||||
|
||||
// We're passing asyncHandle by ref not because we want it to be writable, but so it gets
|
||||
// passed as a pointer (4 bytes). We can pass 4-byte values, but not 8-byte ones.
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Razor" TreatAsLocalProperty="BlazorWebAssemblyEnableLinking">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
|
||||
<OutputType>exe</OutputType>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<!-- loader.js is hard-coded to assume it can load .pdbs regardless of Debug/Release configuration -->
|
||||
<BlazorEnableDebugging>true</BlazorEnableDebugging>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace MonoSanityClient
|
||||
{
|
||||
// Note: Not used at runtime. This exists only to give the server app some type to reference.
|
||||
// In realistic scenarios you'd have a Program class for real.
|
||||
|
||||
public class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
|
||||
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
<IsTestAssetProject>true</IsTestAssetProject>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,6 @@
|
|||
<ProjectReference Include="..\..\benchmarkapps\Wasm.Performance\TestApp\Wasm.Performance.TestApp.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\testassets\MonoSanityClient\MonoSanityClient.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\testassets\MonoSanity\MonoSanity.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj" />
|
||||
<ProjectReference Include="..\..\WebAssembly\DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj" />
|
||||
<ProjectReference Include="..\testassets\BasicTestApp\BasicTestApp.csproj" />
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
var initialResourcesRequested = GetAndClearRequestedPaths();
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json")));
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm")));
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/dotnet.timezones.dat")));
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".js")));
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith(".dll")));
|
||||
|
||||
|
|
@ -60,7 +59,6 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
var subsequentResourcesRequested = GetAndClearRequestedPaths();
|
||||
Assert.NotEmpty(initialResourcesRequested.Where(path => path.EndsWith("/blazor.boot.json")));
|
||||
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.wasm")));
|
||||
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith("/dotnet.timezones.dat")));
|
||||
Assert.NotEmpty(subsequentResourcesRequested.Where(path => path.EndsWith(".js")));
|
||||
Assert.Empty(subsequentResourcesRequested.Where(path => path.EndsWith(".dll")));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,157 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
||||
using Microsoft.AspNetCore.E2ETesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||
{
|
||||
public class MonoSanityTest : ServerTestBase<AspNetSiteServerFixture>
|
||||
{
|
||||
public MonoSanityTest(
|
||||
BrowserFixture browserFixture,
|
||||
AspNetSiteServerFixture serverFixture,
|
||||
ITestOutputHelper output)
|
||||
: base(browserFixture, serverFixture, output)
|
||||
{
|
||||
serverFixture.BuildWebHostMethod = MonoSanity.Program.BuildWebHost;
|
||||
}
|
||||
|
||||
protected override void InitializeAsyncCore()
|
||||
{
|
||||
Navigate("/", noReload: true);
|
||||
WaitUntilMonoRunningInBrowser();
|
||||
}
|
||||
|
||||
private void WaitUntilMonoRunningInBrowser()
|
||||
{
|
||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(driver =>
|
||||
{
|
||||
return ((IJavaScriptExecutor)driver)
|
||||
.ExecuteScript("return window.isTestReady;");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasTitle()
|
||||
{
|
||||
Assert.Equal("Mono sanity check", Browser.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanAddNumbers()
|
||||
{
|
||||
SetValue(Browser, "addNumberA", "1001");
|
||||
SetValue(Browser, "addNumberB", "2002");
|
||||
Browser.FindElement(By.CssSelector("#addNumbers button")).Click();
|
||||
|
||||
Assert.Equal("3003", GetValue(Browser, "addNumbersResult"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanRepeatString()
|
||||
{
|
||||
SetValue(Browser, "repeatStringStr", "Test");
|
||||
SetValue(Browser, "repeatStringCount", "5");
|
||||
Browser.FindElement(By.CssSelector("#repeatString button")).Click();
|
||||
|
||||
Assert.Equal("TestTestTestTestTest", GetValue(Browser, "repeatStringResult"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReceiveDotNetExceptionInJavaScript()
|
||||
{
|
||||
SetValue(Browser, "triggerExceptionMessage", "Hello from test");
|
||||
Browser.FindElement(By.CssSelector("#triggerException button")).Click();
|
||||
|
||||
Assert.Contains("Hello from test", GetValue(Browser, "triggerExceptionMessageStackTrace"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCallJavaScriptFromDotNet()
|
||||
{
|
||||
SetValue(Browser, "callJsEvalExpression", "getUserAgentString()");
|
||||
Browser.FindElement(By.CssSelector("#callJs button")).Click();
|
||||
var result = GetValue(Browser, "callJsResult");
|
||||
Assert.StartsWith(".NET received: Mozilla", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReceiveJavaScriptExceptionInDotNet()
|
||||
{
|
||||
SetValue(Browser, "callJsEvalExpression", "triggerJsException()");
|
||||
Browser.FindElement(By.CssSelector("#callJs button")).Click();
|
||||
var result = GetValue(Browser, "callJsResult");
|
||||
Assert.StartsWith(".NET got exception: This is a JavaScript exception.", result);
|
||||
|
||||
// Also verify we got a stack trace
|
||||
Assert.Contains("at triggerJsException", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanEvaluateJsExpressionThatResultsInNull()
|
||||
{
|
||||
SetValue(Browser, "callJsEvalExpression", "null");
|
||||
Browser.FindElement(By.CssSelector("#callJs button")).Click();
|
||||
var result = GetValue(Browser, "callJsResult");
|
||||
Assert.Equal(".NET received: (NULL)", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanEvaluateJsExpressionThatResultsInUndefined()
|
||||
{
|
||||
SetValue(Browser, "callJsEvalExpression", "console.log('Not returning anything')");
|
||||
Browser.FindElement(By.CssSelector("#callJs button")).Click();
|
||||
var result = GetValue(Browser, "callJsResult");
|
||||
Assert.Equal(".NET received: (NULL)", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCallJsFunctionsWithoutBoxing()
|
||||
{
|
||||
SetValue(Browser, "callJsNoBoxingNumberA", "108");
|
||||
SetValue(Browser, "callJsNoBoxingNumberB", "4");
|
||||
Browser.FindElement(By.CssSelector("#callJsNoBoxing button")).Click();
|
||||
Assert.Equal(".NET received: 27", GetValue(Browser, "callJsNoBoxingResult"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCallJsFunctionsWithoutBoxingAndReceiveException()
|
||||
{
|
||||
SetValue(Browser, "callJsNoBoxingNumberA", "1");
|
||||
SetValue(Browser, "callJsNoBoxingNumberB", "0");
|
||||
Browser.FindElement(By.CssSelector("#callJsNoBoxing button")).Click();
|
||||
|
||||
Assert.StartsWith(".NET got exception: Division by zero", GetValue(Browser, "callJsNoBoxingResult"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReturnsExpectedRuntimeInformation()
|
||||
{
|
||||
Browser.FindElement(By.CssSelector("#getRuntimeInformation button")).Click();
|
||||
Assert.Equal(
|
||||
"OSDescription: 'web'; OSArchitecture: 'X86'; IsOSPlatform(BROWSER): 'True'",
|
||||
GetValue(Browser, "getRuntimeInformationResult"));
|
||||
}
|
||||
|
||||
private static string GetValue(IWebDriver webDriver, string elementId)
|
||||
{
|
||||
var element = webDriver.FindElement(By.Id(elementId));
|
||||
return element.GetAttribute("value");
|
||||
}
|
||||
|
||||
private static void SetValue(IWebDriver webDriver, string elementId, string value)
|
||||
{
|
||||
var element = webDriver.FindElement(By.Id(elementId));
|
||||
element.Clear();
|
||||
element.SendKeys(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
[Fact]
|
||||
public void WasmAuthentication_Loads()
|
||||
{
|
||||
Assert.Equal("Wasm.Authentication.Client", Browser.Title);
|
||||
Browser.Equal("Wasm.Authentication.Client", () => Browser.Title);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -408,8 +408,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
|
||||
private void WaitUntilLoaded(bool skipHeader = false)
|
||||
{
|
||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(30)).Until(
|
||||
driver => driver.FindElement(By.TagName("app")).Text != "Loading...");
|
||||
Browser.Exists(By.TagName("app"));
|
||||
Browser.True(() => Browser.FindElement(By.TagName("app")).Text != "Loading...");
|
||||
|
||||
if (!skipHeader)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@ using OpenQA.Selenium;
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||
{
|
||||
// For now this is limited to server-side execution because we don't have the ability to set the
|
||||
// culture in client-side Blazor.
|
||||
public class WebAssemblyGlobalizationTest : GlobalizationTest<ToggleExecutionModeServerFixture<Program>>
|
||||
// This type is internal since localization currently does not work.
|
||||
// Make it public onc https://github.com/dotnet/runtime/issues/38124 is resolved.
|
||||
internal class WebAssemblyGlobalizationTest : GlobalizationTest<ToggleExecutionModeServerFixture<Program>>
|
||||
{
|
||||
public WebAssemblyGlobalizationTest(
|
||||
BrowserFixture browserFixture,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Theory(Skip = "https://github.com/dotnet/runtime/issues/38124")]
|
||||
[InlineData("en-US", "Hello!")]
|
||||
[InlineData("fr-FR", "Bonjour!")]
|
||||
public void CanSetCultureAndReadLocalizedResources(string culture, string message)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
AssertLogContainsCriticalMessages(
|
||||
"crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]",
|
||||
"[Custom logger] Unhandled exception rendering component: Here is the outer exception",
|
||||
"System.InvalidTimeZoneException: Here is the outer exception ---> System.ArithmeticException: Here is the inner exception",
|
||||
"System.InvalidTimeZoneException: Here is the outer exception",
|
||||
"System.ArithmeticException: Here is the inner exception",
|
||||
"at BasicTestApp.ErrorComponent.ThrowInner");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact(Skip = "https://github.com/dotnet/runtime/issues/38126")]
|
||||
public void InvariantCultureWorksAsExpected()
|
||||
{
|
||||
Navigate(ServerPathBase, noReload: false);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
|
||||
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
|
||||
<!-- Must be defined before ReferenceFromSource.props is imported -->
|
||||
<AdditionalRunArguments>--pathbase /subdir</AdditionalRunArguments>
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace BasicTestApp
|
|||
|
||||
builder.Logging.Services.AddSingleton<ILoggerProvider, PrependMessageLoggerProvider>(s =>
|
||||
new PrependMessageLoggerProvider(builder.Configuration["Logging:PrependMessage:Message"], s.GetService<IJSRuntime>()));
|
||||
|
||||
|
||||
|
||||
var host = builder.Build();
|
||||
ConfigureCulture(host);
|
||||
|
|
|
|||
|
|
@ -258,4 +258,4 @@ function receiveDotNetObjectByRefAsync(incomingData) {
|
|||
testDto: testDto
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -71,10 +71,6 @@
|
|||
<_Parameter2>$(TargetFramework)</_Parameter2>
|
||||
<_Parameter3></_Parameter3>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Test.RazorSdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(RazorSdkDirectoryRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PrepareForTest" BeforeTargets="GetAssemblyAttributes" Condition="$(DesignTimeBuild) != true">
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Templates.Test
|
|||
public async Task BlazorWasmStandaloneTemplate_Works()
|
||||
{
|
||||
var project = await ProjectFactory.GetOrCreateProject("blazorstandalone", Output);
|
||||
project.TargetFramework = "netstandard2.1";
|
||||
project.RuntimeIdentifier = "browser-wasm";
|
||||
|
||||
var createResult = await project.RunDotNetNewAsync("blazorwasm");
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
|
||||
|
|
@ -135,7 +135,7 @@ namespace Templates.Test
|
|||
public async Task BlazorWasmStandalonePwaTemplate_Works()
|
||||
{
|
||||
var project = await ProjectFactory.GetOrCreateProject("blazorstandalonepwa", Output);
|
||||
project.TargetFramework = "netstandard2.1";
|
||||
project.RuntimeIdentifier = "browser-wasm";
|
||||
|
||||
var createResult = await project.RunDotNetNewAsync("blazorwasm", args: new[] { "--pwa" });
|
||||
Assert.True(0 == createResult.ExitCode, ErrorMessages.GetFailedProcessMessage("create/restore", project, createResult));
|
||||
|
|
@ -457,8 +457,6 @@ namespace Templates.Test
|
|||
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", project, aspNetProcess.Process));
|
||||
|
||||
await aspNetProcess.AssertStatusCode("/", HttpStatusCode.OK, "text/html");
|
||||
// We only do brotli precompression for published apps
|
||||
await AssertCompressionFormat(aspNetProcess, "gzip");
|
||||
if (BrowserFixture.IsHostAutomationSupported())
|
||||
{
|
||||
aspNetProcess.VisitInBrowser(Browser);
|
||||
|
|
@ -597,7 +595,6 @@ namespace Templates.Test
|
|||
File.WriteAllText(Path.Combine(serverProject.TemplatePublishDir, "appsettings.json"), testAppSettings);
|
||||
}
|
||||
|
||||
|
||||
private (ProcessEx, string url) RunPublishedStandaloneBlazorProject(Project project)
|
||||
{
|
||||
var publishDir = Path.Combine(project.TemplatePublishDir, "wwwroot");
|
||||
|
|
|
|||
|
|
@ -34,5 +34,8 @@
|
|||
several versions older than latest. To avoid a cyclical dependency, this package reference is added to override the bundled version.
|
||||
Since this is a project reference, we must explicitly import the props file and also specify the output location of the SDK directory.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RazorSdkDirectoryRoot>${ArtifactsBinDir}Microsoft.NET.Sdk.Razor\${Configuration}\sdk-output\</RazorSdkDirectoryRoot>
|
||||
</PropertyGroup>
|
||||
<Import Project="${RepoRoot}src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Microsoft.NET.Sdk.Razor.props" Condition="'$(UsingMicrosoftNETSdkWeb)' == 'true' OR '$(RazorSdkCurrentVersionProps)' != ''" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ namespace Templates.Test.Helpers
|
|||
public string ProjectGuid { get; set; }
|
||||
public string TemplateOutputDir { get; set; }
|
||||
public string TargetFramework { get; set; } = GetAssemblyMetadata("Test.DefaultTargetFramework");
|
||||
public string RazorSdkDirectoryRoot { get; set; } = GetAssemblyMetadata("Test.RazorSdkDirectoryRoot");
|
||||
public string RuntimeIdentifier { get; set; } = string.Empty;
|
||||
|
||||
public string TemplateBuildDir => Path.Combine(TemplateOutputDir, "bin", "Debug", TargetFramework);
|
||||
public string TemplatePublishDir => Path.Combine(TemplateOutputDir, "bin", "Release", TargetFramework, "publish");
|
||||
public string TemplateBuildDir => Path.Combine(TemplateOutputDir, "bin", "Debug", TargetFramework, RuntimeIdentifier);
|
||||
public string TemplatePublishDir => Path.Combine(TemplateOutputDir, "bin", "Release", TargetFramework, RuntimeIdentifier, "publish");
|
||||
|
||||
public ITestOutputHelper Output { get; set; }
|
||||
public IMessageSink DiagnosticsMessageSink { get; set; }
|
||||
|
|
@ -117,9 +117,7 @@ namespace Templates.Test.Helpers
|
|||
// Avoid restoring as part of build or publish. These projects should have already restored as part of running dotnet new. Explicitly disabling restore
|
||||
// should avoid any global contention and we can execute a build or publish in a lock-free way
|
||||
|
||||
var razorSDKarg = string.IsNullOrEmpty(RazorSdkDirectoryRoot) ? string.Empty : $"/p:RazorSdkDirectoryRoot={RazorSdkDirectoryRoot}";
|
||||
|
||||
using var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish --no-restore -c Release /bl {razorSDKarg} {additionalArgs}", packageOptions);
|
||||
using var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"publish --no-restore -c Release /bl {additionalArgs}", packageOptions);
|
||||
await result.Exited;
|
||||
CaptureBinLogOnFailure(result);
|
||||
return new ProcessResult(result);
|
||||
|
|
@ -132,9 +130,7 @@ namespace Templates.Test.Helpers
|
|||
// Avoid restoring as part of build or publish. These projects should have already restored as part of running dotnet new. Explicitly disabling restore
|
||||
// should avoid any global contention and we can execute a build or publish in a lock-free way
|
||||
|
||||
var razorSDKarg = string.IsNullOrEmpty(RazorSdkDirectoryRoot) ? string.Empty : $"/p:RazorSdkDirectoryRoot={RazorSdkDirectoryRoot}";
|
||||
|
||||
using var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"build --no-restore -c Debug /bl {razorSDKarg} {additionalArgs}", packageOptions);
|
||||
using var result = ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), $"build --no-restore -c Debug /bl {additionalArgs}", packageOptions);
|
||||
await result.Exited;
|
||||
CaptureBinLogOnFailure(result);
|
||||
return new ProcessResult(result);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
|
||||
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
|
||||
<!--#if PWA -->
|
||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
<!--#endif -->
|
||||
|
|
@ -13,7 +14,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="${MicrosoftAspNetCoreComponentsWebAssemblyPackageVersion}" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="${MicrosoftAspNetCoreComponentsWebAssemblyBuildPackageVersion}" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="${MicrosoftAspNetCoreComponentsWebAssemblyDevServerPackageVersion}" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="${MicrosoftAspNetCoreComponentsWebAssemblyAuthenticationPackageVersion}" Condition="'$(IndividualLocalAuth)' == 'true'" />
|
||||
<PackageReference Include="Microsoft.Authentication.WebAssembly.Msal" Version="${MicrosoftAuthenticationWebAssemblyMsalPackageVersion}" Condition="'$(OrganizationalAuth)' == 'true' OR '$(IndividualB2CAuth)' == 'true'" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>${DefaultNetCoreTargetFramework}</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@
|
|||
<PackageVersionVariableReference Include="$(RepoRoot)src\Middleware\Diagnostics.EntityFrameworkCore\src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj" />
|
||||
<PackageVersionVariableReference Include="$(RepoRoot)src\Mvc\Mvc.Razor.RuntimeCompilation\src\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.csproj" />
|
||||
<PackageVersionVariableReference Include="$(ComponentsWebAssemblyProjectsRoot)WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
|
||||
<PackageVersionVariableReference Include="$(ComponentsWebAssemblyProjectsRoot)Build\src\Microsoft.AspNetCore.Components.WebAssembly.Build.csproj" />
|
||||
<PackageVersionVariableReference Include="$(ComponentsWebAssemblyProjectsRoot)DevServer\src\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj" />
|
||||
<PackageVersionVariableReference Include="$(ComponentsWebAssemblyProjectsRoot)Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
|
||||
<PackageVersionVariableReference Include="$(ComponentsWebAssemblyProjectsRoot)WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
|
||||
|
|
|
|||
|
|
@ -34,5 +34,8 @@
|
|||
We reference the project to ensure it's built before the other projects that use it. Since this is a project reference, we
|
||||
must explicitly import the props file and also specify the output location of the SDK directory.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RazorSdkDirectoryRoot>${ArtifactsBinDir}Microsoft.NET.Sdk.Razor\${Configuration}\sdk-output\</RazorSdkDirectoryRoot>
|
||||
</PropertyGroup>
|
||||
<Import Project="${RepoRoot}src\Razor\Microsoft.NET.Sdk.Razor\src\build\netstandard2.0\Microsoft.NET.Sdk.Razor.props" Condition="'$(UsingMicrosoftNETSdkWeb)' == 'true' OR '$(RazorSdkCurrentVersionProps)' != ''" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!-- Shared testing infrastructure for running E2E tests using selenium -->
|
||||
<Import Project="$(SharedSourceRoot)E2ETesting\E2ETesting.props" />
|
||||
|
|
@ -65,10 +65,6 @@
|
|||
<_Parameter1>Test.DefaultTargetFramework</_Parameter1>
|
||||
<_Parameter2>$(DefaultNetCoreTargetFramework)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
|
||||
<_Parameter1>Test.RazorSdkDirectoryRoot</_Parameter1>
|
||||
<_Parameter2>$(RazorSdkDirectoryRoot)</_Parameter2>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute" Condition="'$(ContinuousIntegrationBuild)' == 'true'">
|
||||
<_Parameter1>ContinuousIntegrationBuild</_Parameter1>
|
||||
<_Parameter2>true</_Parameter2>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
Commands.Add(new ShutdownCommand(this));
|
||||
Commands.Add(new DiscoverCommand(this));
|
||||
Commands.Add(new GenerateCommand(this));
|
||||
Commands.Add(new BrotliCompressCommand(this));
|
||||
}
|
||||
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
// 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 System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.CommandLineUtils;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Tools
|
||||
{
|
||||
internal class BrotliCompressCommand : CommandBase
|
||||
{
|
||||
public BrotliCompressCommand(Application parent)
|
||||
: base(parent, "brotli")
|
||||
{
|
||||
Sources = Option("-s", "files to compress", CommandOptionType.MultipleValue);
|
||||
Outputs = Option("-o", "Output file path", CommandOptionType.MultipleValue);
|
||||
CompressionLevelOption = Option("-c", "Compression level", CommandOptionType.SingleValue);
|
||||
}
|
||||
|
||||
public CommandOption Sources { get; }
|
||||
|
||||
public CommandOption Outputs { get; }
|
||||
|
||||
public CommandOption CompressionLevelOption { get; }
|
||||
|
||||
public CompressionLevel CompressionLevel { get; private set; } = CompressionLevel.Optimal;
|
||||
|
||||
protected override bool ValidateArguments()
|
||||
{
|
||||
if (Sources.Values.Count != Outputs.Values.Count)
|
||||
{
|
||||
Error.WriteLine($"{Sources.Description} has {Sources.Values.Count}, but {Outputs.Description} has {Outputs.Values.Count} values.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CompressionLevelOption.HasValue())
|
||||
{
|
||||
if (!Enum.TryParse<CompressionLevel>(CompressionLevelOption.Value(), out var value))
|
||||
{
|
||||
Error.WriteLine($"Invalid option {CompressionLevelOption.Value()} for {CompressionLevelOption.Template}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CompressionLevel = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override Task<int> ExecuteCoreAsync()
|
||||
{
|
||||
Parallel.For(0, Sources.Values.Count, i =>
|
||||
{
|
||||
var source = Sources.Values[i];
|
||||
var output = Outputs.Values[i];
|
||||
|
||||
using var sourceStream = File.OpenRead(source);
|
||||
using var fileStream = new FileStream(output, FileMode.Create);
|
||||
|
||||
using var stream = new BrotliStream(fileStream, CompressionLevel);
|
||||
|
||||
sourceStream.CopyTo(stream);
|
||||
});
|
||||
|
||||
return Task.FromResult(ExitCodeSuccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ using System.IO.Compression;
|
|||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
|
@ -238,6 +239,26 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
public static void FileHashEquals(MSBuildResult result, string filePath, string expectedSha256Base64)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(result));
|
||||
}
|
||||
|
||||
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
|
||||
FileExists(result, filePath);
|
||||
|
||||
var actual = File.ReadAllBytes(filePath);
|
||||
using var algorithm = SHA256.Create();
|
||||
var actualSha256 = algorithm.ComputeHash(actual);
|
||||
var actualSha256Base64 = Convert.ToBase64String(actualSha256);
|
||||
if (expectedSha256Base64 != actualSha256Base64)
|
||||
{
|
||||
throw new MSBuildXunitException(result, $"File hashes for {filePath} do not match. Expected {expectedSha256Base64}, Actual {actualSha256Base64}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void FileContainsLine(MSBuildResult result, string filePath, string match)
|
||||
{
|
||||
if (result == null)
|
||||
|
|
@ -298,7 +319,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
return filePath;
|
||||
}
|
||||
|
||||
public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern)
|
||||
public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
|
|
@ -319,7 +340,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
if (Directory.Exists(directoryPath))
|
||||
{
|
||||
var files = Directory.GetFiles(directoryPath, searchPattern, SearchOption.AllDirectories);
|
||||
var files = Directory.GetFiles(directoryPath, searchPattern, searchOption);
|
||||
if (files.Length != expected)
|
||||
{
|
||||
throw new FileCountException(result, expected, directoryPath, searchPattern, files);
|
||||
|
|
@ -508,6 +529,44 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
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<string> 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)
|
||||
|
|
@ -538,14 +597,20 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
private abstract class MSBuildXunitException : Xunit.Sdk.XunitException
|
||||
public class MSBuildXunitException : Xunit.Sdk.XunitException
|
||||
{
|
||||
protected MSBuildXunitException(MSBuildResult result)
|
||||
{
|
||||
Result = result;
|
||||
}
|
||||
|
||||
protected abstract string Heading { get; }
|
||||
public MSBuildXunitException(MSBuildResult result, string heading)
|
||||
{
|
||||
Result = result;
|
||||
Heading = heading;
|
||||
}
|
||||
|
||||
protected virtual string Heading { get; }
|
||||
|
||||
public MSBuildResult Result { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("SimpleMvc")]
|
||||
public async Task Build_RazorOutputPath_SetToNonDefault()
|
||||
{
|
||||
var customOutputPath = Path.Combine("bin", Configuration, TargetFramework, "Razor");
|
||||
var customOutputPath = Path.Combine("bin", Configuration, Project.TargetFramework, "Razor");
|
||||
var result = await DotnetMSBuild("Build", $"/p:RazorOutputPath={customOutputPath}");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
|
@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("SimpleMvc")]
|
||||
public async Task Build_MvcRazorOutputPath_SetToNonDefault()
|
||||
{
|
||||
var customOutputPath = Path.Combine("bin", Configuration, TargetFramework, "Razor");
|
||||
var customOutputPath = Path.Combine("bin", Configuration, Project.TargetFramework, "Razor");
|
||||
var result = await DotnetMSBuild("Build", $"/p:MvcRazorOutputPath={customOutputPath}");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
|
|
|||
|
|
@ -12,12 +12,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
{
|
||||
public class BuildServerIntegrationTest : MSBuildIntegrationTestBase, IClassFixture<BuildServerTestFixture>
|
||||
{
|
||||
private BuildServerTestFixture _buildServer;
|
||||
|
||||
public BuildServerIntegrationTest(BuildServerTestFixture buildServer)
|
||||
: base(buildServer)
|
||||
{
|
||||
_buildServer = buildServer;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -171,7 +169,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
var toolAssembly = Path.Combine(publishDir, "rzc.dll");
|
||||
var result = await DotnetMSBuild(
|
||||
"Build",
|
||||
$"/p:_RazorForceBuildServer=true /p:_RazorToolAssembly={toolAssembly}",
|
||||
$"/p:_RazorForceBuildServer=true /p:_RazorSdkToolAssembly={toolAssembly}",
|
||||
suppressBuildServer: true); // We don't want to specify a pipe name
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
|
|
|||
|
|
@ -20,5 +20,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
public static string RazorSdkDirectoryRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "RazorSdkDirectoryRoot").Value;
|
||||
|
||||
public static string RepoRoot => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "Testing.RepoRoot").Value;
|
||||
|
||||
public static string DefaultNetCoreTargetFramework => TestAssemblyMetadata.SingleOrDefault(a => a.Key == "DefaultNetCoreTargetFramework").Value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("blazor31")]
|
||||
public async Task Build_Components_WithDotNetCoreMSBuild_Works()
|
||||
{
|
||||
TargetFramework = "netcoreapp3.1";
|
||||
Project.TargetFramework = "netcoreapp3.1";
|
||||
var result = await DotnetMSBuild("Build");
|
||||
|
||||
Assert.BuildPassed(result);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("ComponentLibrary")]
|
||||
public async Task Build_WithoutRazorLangVersion_ProducesWarning()
|
||||
{
|
||||
TargetFramework = "netstandard2.0";
|
||||
Project.TargetFramework = "netstandard2.0";
|
||||
var result = await DotnetMSBuild("Build", "/p:RazorLangVersion=");
|
||||
|
||||
Assert.BuildPassed(result, allowWarnings: true);
|
||||
|
|
@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("ComponentLibrary")]
|
||||
public async Task Building_NetstandardComponentLibrary()
|
||||
{
|
||||
TargetFramework = "netstandard2.0";
|
||||
Project.TargetFramework = "netstandard2.0";
|
||||
|
||||
// Build
|
||||
var result = await DotnetMSBuild("Build");
|
||||
|
|
@ -96,7 +96,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("ComponentLibrary")]
|
||||
public async Task Build_DoesNotProduceRefsDirectory()
|
||||
{
|
||||
TargetFramework = "netstandard2.0";
|
||||
Project.TargetFramework = "netstandard2.0";
|
||||
|
||||
// Build
|
||||
var result = await DotnetMSBuild("Build");
|
||||
|
|
@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("ComponentLibrary")]
|
||||
public async Task Publish_DoesNotProduceRefsDirectory()
|
||||
{
|
||||
TargetFramework = "netstandard2.0";
|
||||
Project.TargetFramework = "netstandard2.0";
|
||||
|
||||
// Build
|
||||
var result = await DotnetMSBuild("Publish");
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
[InitializeTestProject("ComponentLibrary")]
|
||||
public async Task RazorGenerateComponentDesignTime_ReturnsRazorComponentWithTargetPath()
|
||||
{
|
||||
TargetFramework = "netstandard2.0";
|
||||
Project.TargetFramework = "netstandard2.0";
|
||||
|
||||
var result = await DotnetMSBuild("RazorGenerateComponentDesignTime;_IntrospectRazorComponentWithTargetPath");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||
|
|
@ -36,6 +38,24 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
return new FileThumbPrint(path, lastWriteTimeUtc, hash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of thumbprints for all files (recursive) in the specified directory, sorted by file paths.
|
||||
/// </summary>
|
||||
internal static List<FileThumbPrint> CreateFolderThumbprint(ProjectDirectory project, string directoryPath, params string[] filesToIgnore)
|
||||
{
|
||||
directoryPath = System.IO.Path.Combine(project.DirectoryPath, directoryPath);
|
||||
var files = Directory.GetFiles(directoryPath).Where(p => !filesToIgnore.Contains(p));
|
||||
var thumbprintLookup = new List<FileThumbPrint>();
|
||||
foreach (var file in files)
|
||||
{
|
||||
var thumbprint = Create(file);
|
||||
thumbprintLookup.Add(thumbprint);
|
||||
}
|
||||
|
||||
thumbprintLookup.Sort(Comparer<FileThumbPrint>.Create((a, b) => StringComparer.Ordinal.Compare(a.Path, b.Path)));
|
||||
return thumbprintLookup;
|
||||
}
|
||||
|
||||
public bool Equals(FileThumbPrint other)
|
||||
{
|
||||
return
|
||||
|
|
|
|||
|
|
@ -36,12 +36,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
throw new InvalidOperationException($"This should be used on a class derived from {typeof(MSBuildIntegrationTestBase)}");
|
||||
}
|
||||
|
||||
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_originalProjectName, _testProjectName, _baseDirectory, _additionalProjects, _language);
|
||||
#if NETCOREAPP
|
||||
MSBuildIntegrationTestBase.TargetFramework = "net5.0";
|
||||
#else
|
||||
#error Target frameworks need to be updated
|
||||
#endif
|
||||
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_originalProjectName, new ProjectDirectory.ProjectDirectoryOptions(_baseDirectory, _testProjectName, _language), _additionalProjects);
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodUnderTest)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
public abstract class MSBuildIntegrationTestBase
|
||||
{
|
||||
private static readonly AsyncLocal<ProjectDirectory> _project = new AsyncLocal<ProjectDirectory>();
|
||||
private static readonly AsyncLocal<string> _projectTfm = new AsyncLocal<string>();
|
||||
|
||||
protected MSBuildIntegrationTestBase(BuildServerTestFixtureBase buildServer)
|
||||
{
|
||||
|
|
@ -31,9 +30,9 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
#error Configuration not supported
|
||||
#endif
|
||||
|
||||
protected string IntermediateOutputPath => Path.Combine("obj", Configuration, TargetFramework);
|
||||
protected string IntermediateOutputPath => Path.Combine("obj", Configuration, Project.TargetFramework);
|
||||
|
||||
protected string OutputPath => Path.Combine("bin", Configuration, TargetFramework);
|
||||
protected string OutputPath => Path.Combine("bin", Configuration, Project.TargetFramework);
|
||||
|
||||
protected string PublishOutputPath => Path.Combine(OutputPath, "publish");
|
||||
|
||||
|
|
@ -50,12 +49,6 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
protected string RazorComponentIntermediateOutputPath => Path.Combine(IntermediateOutputPath, "RazorDeclaration");
|
||||
|
||||
internal static string TargetFramework
|
||||
{
|
||||
get => _projectTfm.Value;
|
||||
set => _projectTfm.Value = value;
|
||||
}
|
||||
|
||||
protected BuildServerTestFixtureBase BuildServer { get; set; }
|
||||
|
||||
internal Task<MSBuildResult> DotnetMSBuild(
|
||||
|
|
@ -111,16 +104,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
|
||||
internal void AddProjectFileContent(string content)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
var existing = File.ReadAllText(Project.ProjectFilePath);
|
||||
var updated = existing.Replace("<!-- Test Placeholder -->", content);
|
||||
File.WriteAllText(Project.ProjectFilePath, updated);
|
||||
}
|
||||
=> Project.AddProjectFileContent(content);
|
||||
|
||||
internal void ReplaceContent(string content, params string[] paths)
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue